linux/fs/ubifs/sysfs.c
ZhaoLong Wang 7037c96d8c ubifs: correct UBIFS_DFS_DIR_LEN macro definition and improve code clarity
The UBIFS_DFS_DIR_LEN macro, which defines the maximum length of the UBIFS
debugfs directory name, has an incorrect formula and misleading comments.
The current formula is (3 + 1 + 2*2 + 1), which assumes that both UBI device
number and volume ID are limited to 2 characters. However, UBI device number
ranges from 0 to 31 (2 characters), and volume ID ranges from 0 to 127 (up
to 3 characters).

Although the current code works due to the cancellation of mathematical
errors (9 + 1 = 10, which matches the correct UBIFS_DFS_DIR_LEN value), it
can lead to confusion and potential issues in the future.

This patch aims to improve the code clarity and maintainability by making
the following changes:

1. Corrects the UBIFS_DFS_DIR_LEN macro definition to (3 + 1 + 2 + 3 + 1),
   accommodating the maximum lengths of both UBI device number and volume ID,
   plus the separators and null terminator.
2. Updates the snprintf calls to use UBIFS_DFS_DIR_LEN instead of
   UBIFS_DFS_DIR_LEN + 1, removing the unnecessary +1.
3. Modifies the error checks to compare against UBIFS_DFS_DIR_LEN using >=
   instead of >, aligning with the corrected macro definition.
4. Removes the redundant +1 in the dfs_dir_name array definitions in ubi.h
   and debug.h.

While these changes do not affect the runtime behavior, they make the code
more readable, maintainable, and less prone to future errors.

v2->v3:

 - Removes the duplicated UBIFS_DFS_DIR_LEN and UBIFS_DFS_DIR_NAME macro
   definitions in ubifs.h, as they are already defined in debug.h.

Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
2024-07-12 21:52:24 +02:00

157 lines
3.2 KiB
C

// 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(sizeof(struct ubifs_stats_info), GFP_KERNEL);
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);
}