Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * This file is part of UBIFS.
0004  *
0005  * Copyright (C) 2021 Cisco Systems
0006  *
0007  * Author: Stefan Schaeckeler
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         /* The array size is too small */
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 }