ubi: Use the fault injection framework to enhance the fault injection capability

To make debug parameters configurable at run time, use the
fault injection framework to reconstruct the debugfs interface,
and retain the legacy fault injection interface.

Now, the file emulate_failures and fault_attr files control whether
to enable fault emmulation.

The file emulate_failures receives a mask that controls type and
process of fault injection. Generally, for ease of use, you can
directly enter a mask with all 1s.

echo 0xffff > /sys/kernel/debug/ubi/ubi0/emulate_failures

And you need to configure other fault-injection capabilities for
testing purpose:

echo 100 > /sys/kernel/debug/ubi/fault_inject/emulate_power_cut/probability
echo 15 > /sys/kernel/debug/ubi/fault_inject/emulate_power_cut/space
echo 2 > /sys/kernel/debug/ubi/fault_inject/emulate_power_cut/verbose
echo -1 > /sys/kernel/debug/ubi/fault_inject/emulate_power_cut/times

The CONFIG_MTD_UBI_FAULT_INJECTION to enable the Fault Injection is
added to kconfig.

Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Richard Weinberger <richard@nod.at>
This commit is contained in:
ZhaoLong Wang
2023-12-26 09:01:09 +08:00
committed by Richard Weinberger
parent 1e022216dc
commit 6931fb4485
5 changed files with 222 additions and 61 deletions

View File

@@ -10,7 +10,23 @@
#include <linux/uaccess.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/fault-inject.h>
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
static DECLARE_FAULT_ATTR(fault_bitflips_attr);
static DECLARE_FAULT_ATTR(fault_io_failures_attr);
static DECLARE_FAULT_ATTR(fault_power_cut_attr);
#define FAIL_ACTION(name, fault_attr) \
bool should_fail_##name(void) \
{ \
return should_fail(&fault_attr, 1); \
}
FAIL_ACTION(bitflips, fault_bitflips_attr)
FAIL_ACTION(io_failures, fault_io_failures_attr)
FAIL_ACTION(power_cut, fault_power_cut_attr)
#endif
/**
* ubi_dump_flash - dump a region of flash.
@@ -212,6 +228,31 @@ void ubi_dump_mkvol_req(const struct ubi_mkvol_req *req)
*/
static struct dentry *dfs_rootdir;
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
static void dfs_create_fault_entry(struct dentry *parent)
{
struct dentry *dir;
dir = debugfs_create_dir("fault_inject", parent);
if (IS_ERR_OR_NULL(dir)) {
int err = dir ? PTR_ERR(dir) : -ENODEV;
pr_warn("UBI error: cannot create \"fault_inject\" debugfs directory, error %d\n",
err);
return;
}
fault_create_debugfs_attr("emulate_bitflips", dir,
&fault_bitflips_attr);
fault_create_debugfs_attr("emulate_io_failures", dir,
&fault_io_failures_attr);
fault_create_debugfs_attr("emulate_power_cut", dir,
&fault_power_cut_attr);
}
#endif
/**
* ubi_debugfs_init - create UBI debugfs directory.
*
@@ -232,6 +273,10 @@ int ubi_debugfs_init(void)
return err;
}
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
dfs_create_fault_entry(dfs_rootdir);
#endif
return 0;
}
@@ -272,7 +317,12 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
val = d->emulate_bitflips;
else if (dent == d->dfs_emulate_io_failures)
val = d->emulate_io_failures;
else if (dent == d->dfs_emulate_power_cut) {
else if (dent == d->dfs_emulate_failures) {
snprintf(buf, sizeof(buf), "0x%04x\n", d->emulate_failures);
count = simple_read_from_buffer(user_buf, count, ppos,
buf, strlen(buf));
goto out;
} else if (dent == d->dfs_emulate_power_cut) {
snprintf(buf, sizeof(buf), "%u\n", d->emulate_power_cut);
count = simple_read_from_buffer(user_buf, count, ppos,
buf, strlen(buf));
@@ -287,8 +337,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
count = simple_read_from_buffer(user_buf, count, ppos,
buf, strlen(buf));
goto out;
}
else {
} else {
count = -EINVAL;
goto out;
}
@@ -330,7 +379,11 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
goto out;
}
if (dent == d->dfs_power_cut_min) {
if (dent == d->dfs_emulate_failures) {
if (kstrtouint(buf, 0, &d->emulate_failures) != 0)
count = -EINVAL;
goto out;
} else if (dent == d->dfs_power_cut_min) {
if (kstrtouint(buf, 0, &d->power_cut_min) != 0)
count = -EINVAL;
goto out;
@@ -559,6 +612,12 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
debugfs_create_file("detailed_erase_block_info", S_IRUSR, d->dfs_dir,
(void *)ubi_num, &eraseblk_count_fops);
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
d->dfs_emulate_failures = debugfs_create_file("emulate_failures",
mode, d->dfs_dir,
(void *)ubi_num,
&dfs_fops);
#endif
return 0;
}
@@ -600,7 +659,5 @@ int ubi_dbg_power_cut(struct ubi_device *ubi, int caller)
if (ubi->dbg.power_cut_counter)
return 0;
ubi_msg(ubi, "XXXXXXXXXXXXXXX emulating a power cut XXXXXXXXXXXXXXXX");
ubi_ro_mode(ubi);
return 1;
}