xref: /openbmc/linux/fs/ubifs/sysfs.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
12e3cbf42SStefan Schaeckeler // SPDX-License-Identifier: GPL-2.0-only
22e3cbf42SStefan Schaeckeler /*
32e3cbf42SStefan Schaeckeler  * This file is part of UBIFS.
42e3cbf42SStefan Schaeckeler  *
52e3cbf42SStefan Schaeckeler  * Copyright (C) 2021 Cisco Systems
62e3cbf42SStefan Schaeckeler  *
72e3cbf42SStefan Schaeckeler  * Author: Stefan Schaeckeler
82e3cbf42SStefan Schaeckeler  */
92e3cbf42SStefan Schaeckeler 
102e3cbf42SStefan Schaeckeler 
112e3cbf42SStefan Schaeckeler #include <linux/fs.h>
122e3cbf42SStefan Schaeckeler #include "ubifs.h"
132e3cbf42SStefan Schaeckeler 
142e3cbf42SStefan Schaeckeler enum attr_id_t {
152e3cbf42SStefan Schaeckeler 	attr_errors_magic,
162e3cbf42SStefan Schaeckeler 	attr_errors_node,
172e3cbf42SStefan Schaeckeler 	attr_errors_crc,
182e3cbf42SStefan Schaeckeler };
192e3cbf42SStefan Schaeckeler 
202e3cbf42SStefan Schaeckeler struct ubifs_attr {
212e3cbf42SStefan Schaeckeler 	struct attribute attr;
222e3cbf42SStefan Schaeckeler 	enum attr_id_t attr_id;
232e3cbf42SStefan Schaeckeler };
242e3cbf42SStefan Schaeckeler 
252e3cbf42SStefan Schaeckeler #define UBIFS_ATTR(_name, _mode, _id)					\
262e3cbf42SStefan Schaeckeler static struct ubifs_attr ubifs_attr_##_name = {				\
272e3cbf42SStefan Schaeckeler 	.attr = {.name = __stringify(_name), .mode = _mode },		\
282e3cbf42SStefan Schaeckeler 	.attr_id = attr_##_id,						\
292e3cbf42SStefan Schaeckeler }
302e3cbf42SStefan Schaeckeler 
312e3cbf42SStefan Schaeckeler #define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
322e3cbf42SStefan Schaeckeler 
332e3cbf42SStefan Schaeckeler UBIFS_ATTR_FUNC(errors_magic, 0444);
342e3cbf42SStefan Schaeckeler UBIFS_ATTR_FUNC(errors_crc, 0444);
352e3cbf42SStefan Schaeckeler UBIFS_ATTR_FUNC(errors_node, 0444);
362e3cbf42SStefan Schaeckeler 
372e3cbf42SStefan Schaeckeler #define ATTR_LIST(name) (&ubifs_attr_##name.attr)
382e3cbf42SStefan Schaeckeler 
392e3cbf42SStefan Schaeckeler static struct attribute *ubifs_attrs[] = {
402e3cbf42SStefan Schaeckeler 	ATTR_LIST(errors_magic),
412e3cbf42SStefan Schaeckeler 	ATTR_LIST(errors_node),
422e3cbf42SStefan Schaeckeler 	ATTR_LIST(errors_crc),
432e3cbf42SStefan Schaeckeler 	NULL,
442e3cbf42SStefan Schaeckeler };
45c6479f19SGreg Kroah-Hartman ATTRIBUTE_GROUPS(ubifs);
462e3cbf42SStefan Schaeckeler 
ubifs_attr_show(struct kobject * kobj,struct attribute * attr,char * buf)472e3cbf42SStefan Schaeckeler static ssize_t ubifs_attr_show(struct kobject *kobj,
482e3cbf42SStefan Schaeckeler 			       struct attribute *attr, char *buf)
492e3cbf42SStefan Schaeckeler {
502e3cbf42SStefan Schaeckeler 	struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
512e3cbf42SStefan Schaeckeler 					      kobj);
522e3cbf42SStefan Schaeckeler 
532e3cbf42SStefan Schaeckeler 	struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
542e3cbf42SStefan Schaeckeler 
552e3cbf42SStefan Schaeckeler 	switch (a->attr_id) {
562e3cbf42SStefan Schaeckeler 	case attr_errors_magic:
572e3cbf42SStefan Schaeckeler 		return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
582e3cbf42SStefan Schaeckeler 	case attr_errors_node:
592e3cbf42SStefan Schaeckeler 		return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
602e3cbf42SStefan Schaeckeler 	case attr_errors_crc:
612e3cbf42SStefan Schaeckeler 		return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
622e3cbf42SStefan Schaeckeler 	}
632e3cbf42SStefan Schaeckeler 	return 0;
642e3cbf42SStefan Schaeckeler };
652e3cbf42SStefan Schaeckeler 
ubifs_sb_release(struct kobject * kobj)662e3cbf42SStefan Schaeckeler static void ubifs_sb_release(struct kobject *kobj)
672e3cbf42SStefan Schaeckeler {
682e3cbf42SStefan Schaeckeler 	struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
692e3cbf42SStefan Schaeckeler 
702e3cbf42SStefan Schaeckeler 	complete(&c->kobj_unregister);
712e3cbf42SStefan Schaeckeler }
722e3cbf42SStefan Schaeckeler 
732e3cbf42SStefan Schaeckeler static const struct sysfs_ops ubifs_attr_ops = {
742e3cbf42SStefan Schaeckeler 	.show	= ubifs_attr_show,
752e3cbf42SStefan Schaeckeler };
762e3cbf42SStefan Schaeckeler 
77*22d74bc2SThomas Weißschuh static const struct kobj_type ubifs_sb_ktype = {
78c6479f19SGreg Kroah-Hartman 	.default_groups	= ubifs_groups,
792e3cbf42SStefan Schaeckeler 	.sysfs_ops	= &ubifs_attr_ops,
802e3cbf42SStefan Schaeckeler 	.release	= ubifs_sb_release,
812e3cbf42SStefan Schaeckeler };
822e3cbf42SStefan Schaeckeler 
83*22d74bc2SThomas Weißschuh static const struct kobj_type ubifs_ktype = {
842e3cbf42SStefan Schaeckeler 	.sysfs_ops	= &ubifs_attr_ops,
852e3cbf42SStefan Schaeckeler };
862e3cbf42SStefan Schaeckeler 
872e3cbf42SStefan Schaeckeler static struct kset ubifs_kset = {
882e3cbf42SStefan Schaeckeler 	.kobj	= {.ktype = &ubifs_ktype},
892e3cbf42SStefan Schaeckeler };
902e3cbf42SStefan Schaeckeler 
ubifs_sysfs_register(struct ubifs_info * c)912e3cbf42SStefan Schaeckeler int ubifs_sysfs_register(struct ubifs_info *c)
922e3cbf42SStefan Schaeckeler {
932e3cbf42SStefan Schaeckeler 	int ret, n;
942e3cbf42SStefan Schaeckeler 	char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];
952e3cbf42SStefan Schaeckeler 
962e3cbf42SStefan Schaeckeler 	c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
972e3cbf42SStefan Schaeckeler 	if (!c->stats) {
982e3cbf42SStefan Schaeckeler 		ret = -ENOMEM;
992e3cbf42SStefan Schaeckeler 		goto out_last;
1002e3cbf42SStefan Schaeckeler 	}
1012e3cbf42SStefan Schaeckeler 	n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
1022e3cbf42SStefan Schaeckeler 		     c->vi.ubi_num, c->vi.vol_id);
1032e3cbf42SStefan Schaeckeler 
104d3de970bSDan Carpenter 	if (n > UBIFS_DFS_DIR_LEN) {
1052e3cbf42SStefan Schaeckeler 		/* The array size is too small */
1062e3cbf42SStefan Schaeckeler 		ret = -EINVAL;
1072e3cbf42SStefan Schaeckeler 		goto out_free;
1082e3cbf42SStefan Schaeckeler 	}
1092e3cbf42SStefan Schaeckeler 
1102e3cbf42SStefan Schaeckeler 	c->kobj.kset = &ubifs_kset;
1112e3cbf42SStefan Schaeckeler 	init_completion(&c->kobj_unregister);
1122e3cbf42SStefan Schaeckeler 
1132e3cbf42SStefan Schaeckeler 	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
1142e3cbf42SStefan Schaeckeler 				   "%s", dfs_dir_name);
1152e3cbf42SStefan Schaeckeler 	if (ret)
1162e3cbf42SStefan Schaeckeler 		goto out_put;
1172e3cbf42SStefan Schaeckeler 
1182e3cbf42SStefan Schaeckeler 	return 0;
1192e3cbf42SStefan Schaeckeler 
1202e3cbf42SStefan Schaeckeler out_put:
1212e3cbf42SStefan Schaeckeler 	kobject_put(&c->kobj);
1222e3cbf42SStefan Schaeckeler 	wait_for_completion(&c->kobj_unregister);
1232e3cbf42SStefan Schaeckeler out_free:
1242e3cbf42SStefan Schaeckeler 	kfree(c->stats);
1252e3cbf42SStefan Schaeckeler out_last:
1262e3cbf42SStefan Schaeckeler 	ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
1272e3cbf42SStefan Schaeckeler 		  c->vi.ubi_num, c->vi.vol_id, ret);
1282e3cbf42SStefan Schaeckeler 	return ret;
1292e3cbf42SStefan Schaeckeler }
1302e3cbf42SStefan Schaeckeler 
ubifs_sysfs_unregister(struct ubifs_info * c)1312e3cbf42SStefan Schaeckeler void ubifs_sysfs_unregister(struct ubifs_info *c)
1322e3cbf42SStefan Schaeckeler {
1332e3cbf42SStefan Schaeckeler 	kobject_del(&c->kobj);
1342e3cbf42SStefan Schaeckeler 	kobject_put(&c->kobj);
1352e3cbf42SStefan Schaeckeler 	wait_for_completion(&c->kobj_unregister);
1362e3cbf42SStefan Schaeckeler 
1372e3cbf42SStefan Schaeckeler 	kfree(c->stats);
1382e3cbf42SStefan Schaeckeler }
1392e3cbf42SStefan Schaeckeler 
ubifs_sysfs_init(void)1402e3cbf42SStefan Schaeckeler int __init ubifs_sysfs_init(void)
1412e3cbf42SStefan Schaeckeler {
1422e3cbf42SStefan Schaeckeler 	int ret;
1432e3cbf42SStefan Schaeckeler 
1442e3cbf42SStefan Schaeckeler 	kobject_set_name(&ubifs_kset.kobj, "ubifs");
1452e3cbf42SStefan Schaeckeler 	ubifs_kset.kobj.parent = fs_kobj;
1462e3cbf42SStefan Schaeckeler 	ret = kset_register(&ubifs_kset);
147203a55f0SLiu Shixin 	if (ret)
148203a55f0SLiu Shixin 		kset_put(&ubifs_kset);
1492e3cbf42SStefan Schaeckeler 
1502e3cbf42SStefan Schaeckeler 	return ret;
1512e3cbf42SStefan Schaeckeler }
1522e3cbf42SStefan Schaeckeler 
ubifs_sysfs_exit(void)1532e3cbf42SStefan Schaeckeler void ubifs_sysfs_exit(void)
1542e3cbf42SStefan Schaeckeler {
1552e3cbf42SStefan Schaeckeler 	kset_unregister(&ubifs_kset);
1562e3cbf42SStefan Schaeckeler }
157