0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #include <linux/fs.h>
0012 #include "ubifs.h"
0013
0014 enum attr_id_t {
0015 attr_errors_magic,
0016 attr_errors_node,
0017 attr_errors_crc,
0018 };
0019
0020 struct ubifs_attr {
0021 struct attribute attr;
0022 enum attr_id_t attr_id;
0023 };
0024
0025 #define UBIFS_ATTR(_name, _mode, _id) \
0026 static struct ubifs_attr ubifs_attr_##_name = { \
0027 .attr = {.name = __stringify(_name), .mode = _mode }, \
0028 .attr_id = attr_##_id, \
0029 }
0030
0031 #define UBIFS_ATTR_FUNC(_name, _mode) UBIFS_ATTR(_name, _mode, _name)
0032
0033 UBIFS_ATTR_FUNC(errors_magic, 0444);
0034 UBIFS_ATTR_FUNC(errors_crc, 0444);
0035 UBIFS_ATTR_FUNC(errors_node, 0444);
0036
0037 #define ATTR_LIST(name) (&ubifs_attr_##name.attr)
0038
0039 static struct attribute *ubifs_attrs[] = {
0040 ATTR_LIST(errors_magic),
0041 ATTR_LIST(errors_node),
0042 ATTR_LIST(errors_crc),
0043 NULL,
0044 };
0045 ATTRIBUTE_GROUPS(ubifs);
0046
0047 static ssize_t ubifs_attr_show(struct kobject *kobj,
0048 struct attribute *attr, char *buf)
0049 {
0050 struct ubifs_info *sbi = container_of(kobj, struct ubifs_info,
0051 kobj);
0052
0053 struct ubifs_attr *a = container_of(attr, struct ubifs_attr, attr);
0054
0055 switch (a->attr_id) {
0056 case attr_errors_magic:
0057 return sysfs_emit(buf, "%u\n", sbi->stats->magic_errors);
0058 case attr_errors_node:
0059 return sysfs_emit(buf, "%u\n", sbi->stats->node_errors);
0060 case attr_errors_crc:
0061 return sysfs_emit(buf, "%u\n", sbi->stats->crc_errors);
0062 }
0063 return 0;
0064 };
0065
0066 static void ubifs_sb_release(struct kobject *kobj)
0067 {
0068 struct ubifs_info *c = container_of(kobj, struct ubifs_info, kobj);
0069
0070 complete(&c->kobj_unregister);
0071 }
0072
0073 static const struct sysfs_ops ubifs_attr_ops = {
0074 .show = ubifs_attr_show,
0075 };
0076
0077 static struct kobj_type ubifs_sb_ktype = {
0078 .default_groups = ubifs_groups,
0079 .sysfs_ops = &ubifs_attr_ops,
0080 .release = ubifs_sb_release,
0081 };
0082
0083 static struct kobj_type ubifs_ktype = {
0084 .sysfs_ops = &ubifs_attr_ops,
0085 };
0086
0087 static struct kset ubifs_kset = {
0088 .kobj = {.ktype = &ubifs_ktype},
0089 };
0090
0091 int ubifs_sysfs_register(struct ubifs_info *c)
0092 {
0093 int ret, n;
0094 char dfs_dir_name[UBIFS_DFS_DIR_LEN+1];
0095
0096 c->stats = kzalloc(sizeof(struct ubifs_stats_info), GFP_KERNEL);
0097 if (!c->stats) {
0098 ret = -ENOMEM;
0099 goto out_last;
0100 }
0101 n = snprintf(dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
0102 c->vi.ubi_num, c->vi.vol_id);
0103
0104 if (n > UBIFS_DFS_DIR_LEN) {
0105
0106 ret = -EINVAL;
0107 goto out_free;
0108 }
0109
0110 c->kobj.kset = &ubifs_kset;
0111 init_completion(&c->kobj_unregister);
0112
0113 ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
0114 "%s", dfs_dir_name);
0115 if (ret)
0116 goto out_put;
0117
0118 return 0;
0119
0120 out_put:
0121 kobject_put(&c->kobj);
0122 wait_for_completion(&c->kobj_unregister);
0123 out_free:
0124 kfree(c->stats);
0125 out_last:
0126 ubifs_err(c, "cannot create sysfs entry for ubifs%d_%d, error %d\n",
0127 c->vi.ubi_num, c->vi.vol_id, ret);
0128 return ret;
0129 }
0130
0131 void ubifs_sysfs_unregister(struct ubifs_info *c)
0132 {
0133 kobject_del(&c->kobj);
0134 kobject_put(&c->kobj);
0135 wait_for_completion(&c->kobj_unregister);
0136
0137 kfree(c->stats);
0138 }
0139
0140 int __init ubifs_sysfs_init(void)
0141 {
0142 int ret;
0143
0144 kobject_set_name(&ubifs_kset.kobj, "ubifs");
0145 ubifs_kset.kobj.parent = fs_kobj;
0146 ret = kset_register(&ubifs_kset);
0147
0148 return ret;
0149 }
0150
0151 void ubifs_sysfs_exit(void)
0152 {
0153 kset_unregister(&ubifs_kset);
0154 }