// SPDX-License-Identifier: GPL-2.0-only
/*
 * This file is part of UBIFS.
 *
 * Copyright (C) 2021 Cisco Systems
 *
 * Author: Stefan Schaeckeler
 */


#include <linux/fs.h>
#include "ubifs.h"

enum attr_id_t {
	attr_errors_magic,
	attr_errors_node,
	attr_errors_crc,
};

struct ubifs_attr {
	struct attribute attr;
	enum attr_id_t attr_id;
};

#define UBIFS_ATTR(_name, _mode, _id)					\
static struct ubifs_attr ubifs_attr_##_name = {				\
	.attr = {.name = __stringify(_name), .mode = _mode },		\
	.attr_id = attr_##_id,						\
}

#define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)

UBIFS_ATTR_FUNC(errors_magic, 0444);
UBIFS_ATTR_FUNC(errors_crc, 0444);
UBIFS_ATTR_FUNC(errors_node, 0444);

#define ATTR_LIST(name) (&ubifs_attr_##name.attr)

static struct attribute *ubifs_attrs[] = {
	ATTR_LIST(errors_magic),
	ATTR_LIST(errors_node),
	ATTR_LIST(errors_crc),
	NULL,
};
ATTRIBUTE_GROUPS(ubifs);

static ssize_t ubifs_attr_show(struct kobject *kobj,
			       struct attribute *attr, char *buf)
{
	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
					      kobj);

	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);

	switch (a->attr_id) {
	case attr_errors_magic:
		return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
	case attr_errors_node:
		return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
	case attr_errors_crc:
		return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
	}
	return 0;
};

static void ubifs_sb_release(struct kobject *kobj)
{
	struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);

	complete(&c->kobj_unregister);
}

static const struct sysfs_ops ubifs_attr_ops = {
	.show	= ubifs_attr_show,
};

static const struct kobj_type ubifs_sb_ktype = {
	.default_groups	= ubifs_groups,
	.sysfs_ops	= &ubifs_attr_ops,
	.release	= ubifs_sb_release,
};

static const struct kobj_type ubifs_ktype = {
	.sysfs_ops	= &ubifs_attr_ops,
};

static struct kset ubifs_kset = {
	.kobj	= {.ktype = &ubifs_ktype},
};

int ubifs_sysfs_register(struct ubifs_info *c)
{
	int ret, n;
	char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];

	c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
	if (!c->stats) {
		ret = -ENOMEM;
		goto out_last;
	}
	n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
		     c->vi.ubi_num, c->vi.vol_id);

	if (n > UBIFS_DFS_DIR_LEN) {
		/* The array size is too small */
		ret = -EINVAL;
		goto out_free;
	}

	c->kobj.kset = &ubifs_kset;
	init_completion(&c->kobj_unregister);

	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
				   "%s", dfs_dir_name);
	if (ret)
		goto out_put;

	return 0;

out_put:
	kobject_put(&c->kobj);
	wait_for_completion(&c->kobj_unregister);
out_free:
	kfree(c->stats);
out_last:
	ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
		  c->vi.ubi_num, c->vi.vol_id, ret);
	return ret;
}

void ubifs_sysfs_unregister(struct ubifs_info *c)
{
	kobject_del(&c->kobj);
	kobject_put(&c->kobj);
	wait_for_completion(&c->kobj_unregister);

	kfree(c->stats);
}

int __init ubifs_sysfs_init(void)
{
	int ret;

	kobject_set_name(&ubifs_kset.kobj, "ubifs");
	ubifs_kset.kobj.parent = fs_kobj;
	ret = kset_register(&ubifs_kset);
	if (ret)
		kset_put(&ubifs_kset);

	return ret;
}

void ubifs_sysfs_exit(void)
{
	kset_unregister(&ubifs_kset);
}
