| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- // 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];
- c->stats = kzalloc_obj(struct ubifs_stats_info);
- if (!c->stats) {
- ret = -ENOMEM;
- goto out_last;
- }
- n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN, 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);
- }
|