* [PATCH V2 1/5] ubi: Use the fault injection framework to enhance the fault injection capability
2023-07-18 8:51 [PATCH V2 0/5] ubi: Enhanced fault injection capability for the UBI driver ZhaoLong Wang
@ 2023-07-18 8:51 ` ZhaoLong Wang
2023-07-31 11:15 ` Zhihao Cheng
2023-07-18 8:51 ` [PATCH V2 2/5] ubi: Split io_failures into write_failure and erase_failure ZhaoLong Wang
` (3 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: ZhaoLong Wang @ 2023-07-18 8:51 UTC (permalink / raw)
To: richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang
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>
---
V2:
- Retain the original interface.
- When both the new and original interfaces are enabled, the original
interface takes precedence over the new interface.
- Adjusted the order of masks to be compatible with original interfaces.
drivers/mtd/ubi/Kconfig | 9 +++
drivers/mtd/ubi/debug.c | 68 +++++++++++++++++--
drivers/mtd/ubi/debug.h | 142 +++++++++++++++++++++++++++++++++-------
drivers/mtd/ubi/io.c | 10 ++-
drivers/mtd/ubi/ubi.h | 15 ++---
5 files changed, 202 insertions(+), 42 deletions(-)
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 2ed77b7b3fcb..138fae7e8f96 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -104,4 +104,13 @@ config MTD_UBI_BLOCK
If in doubt, say "N".
+config MTD_UBI_FAULT_INJECTION
+ bool "Fault injection capability of UBI device"
+ default n
+ depends on FAULT_INJECTION_DEBUG_FS
+ help
+ this option enable fault-injection support for UBI devices for
+ testing purposes.
+
+ If in doubt, say "N".
endif # MTD_UBI
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 27168f511d6d..9ca584da32c6 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -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), "%u\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,11 @@ 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 +658,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;
}
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 23676f32b681..fc4234c9a90a 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -53,56 +53,153 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi);
void ubi_debugfs_exit_dev(struct ubi_device *ubi);
/**
- * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * The following function is a legacy implementation of UBI fault-injection
+ * hook. When using more powerful fault injection capabilities, the legacy
+ * fault injection interface should be retained.
+ */
+int ubi_dbg_power_cut(struct ubi_device *ubi, int caller);
+
+static inline int ubi_dbg_bitflip(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_bitflips)
+ return !get_random_u32_below(200);
+ return 0;
+}
+
+static inline int ubi_dbg_write_failure(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_io_failures)
+ return !get_random_u32_below(500);
+ return 0;
+}
+
+static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_io_failures)
+ return !get_random_u32_below(400);
+ return 0;
+}
+
+/**
+ * MASK_XXX: Mask for emulate_failures in ubi_debug_info.The mask is used to
+ * precisely control the type and process of fault injection.
+ */
+/* Emulate a power cut when writing EC/VID header */
+#define MASK_POWER_CUT_EC (1 << 1)
+#define MASK_POWER_CUT_VID (1 << 2)
+
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+/* Emulate bit-flips */
+#define MASK_BITFLIPS (1 << 3)
+/* Emulates -EIO during write/erase */
+#define MASK_IO_FAILURE (1 << 4)
+
+extern bool should_fail_bitflips(void);
+extern bool should_fail_io_failures(void);
+extern bool should_fail_power_cut(void);
+
+static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_failures & MASK_BITFLIPS)
+ return should_fail_bitflips();
+ return false;
+}
+
+static inline bool ubi_dbg_fail_write(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
+ return should_fail_io_failures();
+ return false;
+}
+
+static inline bool ubi_dbg_fail_erase(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
+ return should_fail_io_failures();
+ return false;
+}
+
+static inline bool ubi_dbg_fail_power_cut(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_power_cut();
+ return false;
+}
+
+#else /* CONFIG_MTD_UBI_FAULT_INJECTION */
+
+#define ubi_dbg_fail_bitflip(u) false
+#define ubi_dbg_fail_write(u) false
+#define ubi_dbg_fail_erase(u) false
+#define ubi_dbg_fail_power_cut(u,c) false
+#endif
+
+/**
+ * ubi_dbg_is_power_cut - if it is time to emulate power cut.
* @ubi: UBI device description object
*
- * Returns non-zero if the UBI background thread is disabled for testing
- * purposes.
+ * Returns true if power cut should be emulated, otherwise returns false.
*/
-static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
+static inline bool ubi_dbg_is_power_cut(struct ubi_device *ubi,
+ unsigned int caller)
{
- return ubi->dbg.disable_bgt;
+ if (ubi_dbg_power_cut(ubi, caller))
+ return true;
+ return ubi_dbg_fail_power_cut(ubi, caller);
}
/**
* ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
* @ubi: UBI device description object
*
- * Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
+ * Returns true if a bit-flip should be emulated, otherwise returns false.
*/
-static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
+static inline bool ubi_dbg_is_bitflip(const struct ubi_device *ubi)
{
- if (ubi->dbg.emulate_bitflips)
- return !get_random_u32_below(200);
- return 0;
+ if (ubi_dbg_bitflip(ubi))
+ return true;
+ return ubi_dbg_fail_bitflip(ubi);
}
/**
* ubi_dbg_is_write_failure - if it is time to emulate a write failure.
* @ubi: UBI device description object
*
- * Returns non-zero if a write failure should be emulated, otherwise returns
- * zero.
+ * Returns true if a write failure should be emulated, otherwise returns
+ * false.
*/
-static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
+static inline bool ubi_dbg_is_write_failure(const struct ubi_device *ubi)
{
- if (ubi->dbg.emulate_io_failures)
- return !get_random_u32_below(500);
- return 0;
+ if (ubi_dbg_write_failure(ubi))
+ return true;;
+ return ubi_dbg_fail_write(ubi);
}
/**
* ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
* @ubi: UBI device description object
*
- * Returns non-zero if an erase failure should be emulated, otherwise returns
- * zero.
+ * Returns true if an erase failure should be emulated, otherwise returns
+ * false.
*/
-static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
+static inline bool ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
{
- if (ubi->dbg.emulate_io_failures)
- return !get_random_u32_below(400);
- return 0;
+ if (ubi_dbg_erase_failure(ubi))
+ return true;
+ return ubi_dbg_fail_erase(ubi);
+}
+
+/**
+ * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ * @ubi: UBI device description object
+ *
+ * Returns non-zero if the UBI background thread is disabled for testing
+ * purposes.
+ */
+static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
+{
+ return ubi->dbg.disable_bgt;
}
static inline int ubi_dbg_chk_io(const struct ubi_device *ubi)
@@ -125,5 +222,4 @@ static inline void ubi_enable_dbg_chk_fastmap(struct ubi_device *ubi)
ubi->dbg.chk_fastmap = 1;
}
-int ubi_dbg_power_cut(struct ubi_device *ubi, int caller);
#endif /* !__UBI_DEBUG_H__ */
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index 01b644861253..ffa7bbf27bc2 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -821,8 +821,11 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
if (err)
return err;
- if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE))
+ if (ubi_dbg_is_power_cut(ubi, MASK_POWER_CUT_EC)) {
+ ubi_warn(ubi, "XXXXX emulating a power cut when writing EC header XXXXX");
+ ubi_ro_mode(ubi);
return -EROFS;
+ }
err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
return err;
@@ -1071,8 +1074,11 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
if (err)
return err;
- if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE))
+ if (ubi_dbg_is_power_cut(ubi, MASK_POWER_CUT_VID)) {
+ ubi_warn(ubi, "XXXXX emulating a power cut when writing VID header XXXXX");
+ ubi_ro_mode(ubi);
return -EROFS;
+ }
err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
ubi->vid_hdr_alsize);
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index c8f1bd4fa100..41f57d5717b2 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -142,17 +142,6 @@ enum {
UBI_BAD_FASTMAP,
};
-/*
- * Flags for emulate_power_cut in ubi_debug_info
- *
- * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header
- * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header
- */
-enum {
- POWER_CUT_EC_WRITE = 0x01,
- POWER_CUT_VID_WRITE = 0x02,
-};
-
/**
* struct ubi_vid_io_buf - VID buffer used to read/write VID info to/from the
* flash.
@@ -401,6 +390,7 @@ struct ubi_volume_desc {
* @power_cut_counter: count down for writes left until emulated power cut
* @power_cut_min: minimum number of writes before emulating a power cut
* @power_cut_max: maximum number of writes until emulating a power cut
+ * @emulate_failures: emulate failures for testing purposes
* @dfs_dir_name: name of debugfs directory containing files of this UBI device
* @dfs_dir: direntry object of the UBI device debugfs directory
* @dfs_chk_gen: debugfs knob to enable UBI general extra checks
@@ -412,6 +402,7 @@ struct ubi_volume_desc {
* @dfs_emulate_power_cut: debugfs knob to emulate power cuts
* @dfs_power_cut_min: debugfs knob for minimum writes before power cut
* @dfs_power_cut_max: debugfs knob for maximum writes until power cut
+ * @dfs_emulate_failures: debugfs entry to control the fault injection type
*/
struct ubi_debug_info {
unsigned int chk_gen:1;
@@ -424,6 +415,7 @@ struct ubi_debug_info {
unsigned int power_cut_counter;
unsigned int power_cut_min;
unsigned int power_cut_max;
+ unsigned int emulate_failures;
char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
struct dentry *dfs_dir;
struct dentry *dfs_chk_gen;
@@ -435,6 +427,7 @@ struct ubi_debug_info {
struct dentry *dfs_emulate_power_cut;
struct dentry *dfs_power_cut_min;
struct dentry *dfs_power_cut_max;
+ struct dentry *dfs_emulate_failures;
};
/**
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 1/5] ubi: Use the fault injection framework to enhance the fault injection capability
2023-07-18 8:51 ` [PATCH V2 1/5] ubi: Use the fault injection framework to enhance the fault injection capability ZhaoLong Wang
@ 2023-07-31 11:15 ` Zhihao Cheng
0 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 11:15 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> 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>
> ---
> V2:
> - Retain the original interface.
> - When both the new and original interfaces are enabled, the original
> interface takes precedence over the new interface.
> - Adjusted the order of masks to be compatible with original interfaces.
>
> drivers/mtd/ubi/Kconfig | 9 +++
> drivers/mtd/ubi/debug.c | 68 +++++++++++++++++--
> drivers/mtd/ubi/debug.h | 142 +++++++++++++++++++++++++++++++++-------
> drivers/mtd/ubi/io.c | 10 ++-
> drivers/mtd/ubi/ubi.h | 15 ++---
> 5 files changed, 202 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
> index 2ed77b7b3fcb..138fae7e8f96 100644
> --- a/drivers/mtd/ubi/Kconfig
> +++ b/drivers/mtd/ubi/Kconfig
> @@ -104,4 +104,13 @@ config MTD_UBI_BLOCK
>
> If in doubt, say "N".
>
> +config MTD_UBI_FAULT_INJECTION
> + bool "Fault injection capability of UBI device"
> + default n
> + depends on FAULT_INJECTION_DEBUG_FS
> + help
> + this option enable fault-injection support for UBI devices for
> + testing purposes.
> +
> + If in doubt, say "N".
> endif # MTD_UBI
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 27168f511d6d..9ca584da32c6 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -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), "%u\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,11 @@ 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 +658,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;
> }
> diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
> index 23676f32b681..fc4234c9a90a 100644
> --- a/drivers/mtd/ubi/debug.h
> +++ b/drivers/mtd/ubi/debug.h
> @@ -53,56 +53,153 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi);
> void ubi_debugfs_exit_dev(struct ubi_device *ubi);
>
> /**
> - * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
> + * The following function is a legacy implementation of UBI fault-injection
> + * hook. When using more powerful fault injection capabilities, the legacy
> + * fault injection interface should be retained.
> + */
> +int ubi_dbg_power_cut(struct ubi_device *ubi, int caller);
> +
> +static inline int ubi_dbg_bitflip(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_bitflips)
> + return !get_random_u32_below(200);
> + return 0;
> +}
> +
> +static inline int ubi_dbg_write_failure(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_io_failures)
> + return !get_random_u32_below(500);
> + return 0;
> +}
> +
> +static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_io_failures)
> + return !get_random_u32_below(400);
> + return 0;
> +}
> +
> +/**
> + * MASK_XXX: Mask for emulate_failures in ubi_debug_info.The mask is used to
> + * precisely control the type and process of fault injection.
> + */
> +/* Emulate a power cut when writing EC/VID header */
> +#define MASK_POWER_CUT_EC (1 << 1)
> +#define MASK_POWER_CUT_VID (1 << 2)
POWER_CUT_EC_WRITE=0x1, POWER_CUT_VID_WRITE=0x02
To be compatible with old interface, please define MASK_POWER_CUT_EC as
(1 << 0) and define MASK_POWER_CUT_VID (1<<1)
> +
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/* Emulate bit-flips */
> +#define MASK_BITFLIPS (1 << 3)
> +/* Emulates -EIO during write/erase */
> +#define MASK_IO_FAILURE (1 << 4)
> +
> +extern bool should_fail_bitflips(void);
> +extern bool should_fail_io_failures(void);
> +extern bool should_fail_power_cut(void);
> +
> +static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_failures & MASK_BITFLIPS)
> + return should_fail_bitflips();
> + return false;
> +}
> +
> +static inline bool ubi_dbg_fail_write(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
> + return should_fail_io_failures();
> + return false;
> +}
> +
> +static inline bool ubi_dbg_fail_erase(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
> + return should_fail_io_failures();
> + return false;
> +}
> +
> +static inline bool ubi_dbg_fail_power_cut(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_power_cut();
> + return false;
> +}
> +
> +#else /* CONFIG_MTD_UBI_FAULT_INJECTION */
> +
> +#define ubi_dbg_fail_bitflip(u) false
> +#define ubi_dbg_fail_write(u) false
> +#define ubi_dbg_fail_erase(u) false
> +#define ubi_dbg_fail_power_cut(u,c) false
> +#endif
> +
> +/**
> + * ubi_dbg_is_power_cut - if it is time to emulate power cut.
> * @ubi: UBI device description object
> *
> - * Returns non-zero if the UBI background thread is disabled for testing
> - * purposes.
> + * Returns true if power cut should be emulated, otherwise returns false.
> */
> -static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
> +static inline bool ubi_dbg_is_power_cut(struct ubi_device *ubi,
> + unsigned int caller)
> {
> - return ubi->dbg.disable_bgt;
> + if (ubi_dbg_power_cut(ubi, caller))
> + return true;
> + return ubi_dbg_fail_power_cut(ubi, caller);
> }
>
> /**
> * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
> * @ubi: UBI device description object
> *
> - * Returns non-zero if a bit-flip should be emulated, otherwise returns zero.
> + * Returns true if a bit-flip should be emulated, otherwise returns false.
> */
> -static inline int ubi_dbg_is_bitflip(const struct ubi_device *ubi)
> +static inline bool ubi_dbg_is_bitflip(const struct ubi_device *ubi)
> {
> - if (ubi->dbg.emulate_bitflips)
> - return !get_random_u32_below(200);
> - return 0;
> + if (ubi_dbg_bitflip(ubi))
> + return true;
> + return ubi_dbg_fail_bitflip(ubi);
> }
>
> /**
> * ubi_dbg_is_write_failure - if it is time to emulate a write failure.
> * @ubi: UBI device description object
> *
> - * Returns non-zero if a write failure should be emulated, otherwise returns
> - * zero.
> + * Returns true if a write failure should be emulated, otherwise returns
> + * false.
> */
> -static inline int ubi_dbg_is_write_failure(const struct ubi_device *ubi)
> +static inline bool ubi_dbg_is_write_failure(const struct ubi_device *ubi)
> {
> - if (ubi->dbg.emulate_io_failures)
> - return !get_random_u32_below(500);
> - return 0;
> + if (ubi_dbg_write_failure(ubi))
> + return true;;
> + return ubi_dbg_fail_write(ubi);
> }
>
> /**
> * ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
> * @ubi: UBI device description object
> *
> - * Returns non-zero if an erase failure should be emulated, otherwise returns
> - * zero.
> + * Returns true if an erase failure should be emulated, otherwise returns
> + * false.
> */
> -static inline int ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
> +static inline bool ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
> {
> - if (ubi->dbg.emulate_io_failures)
> - return !get_random_u32_below(400);
> - return 0;
> + if (ubi_dbg_erase_failure(ubi))
> + return true;
> + return ubi_dbg_fail_erase(ubi);
> +}
> +
> +/**
> + * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
> + * @ubi: UBI device description object
> + *
> + * Returns non-zero if the UBI background thread is disabled for testing
> + * purposes.
> + */
> +static inline int ubi_dbg_is_bgt_disabled(const struct ubi_device *ubi)
> +{
> + return ubi->dbg.disable_bgt;
> }
>
> static inline int ubi_dbg_chk_io(const struct ubi_device *ubi)
> @@ -125,5 +222,4 @@ static inline void ubi_enable_dbg_chk_fastmap(struct ubi_device *ubi)
> ubi->dbg.chk_fastmap = 1;
> }
>
> -int ubi_dbg_power_cut(struct ubi_device *ubi, int caller);
> #endif /* !__UBI_DEBUG_H__ */
> diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
> index 01b644861253..ffa7bbf27bc2 100644
> --- a/drivers/mtd/ubi/io.c
> +++ b/drivers/mtd/ubi/io.c
> @@ -821,8 +821,11 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum,
> if (err)
> return err;
>
> - if (ubi_dbg_power_cut(ubi, POWER_CUT_EC_WRITE))
> + if (ubi_dbg_is_power_cut(ubi, MASK_POWER_CUT_EC)) {
> + ubi_warn(ubi, "XXXXX emulating a power cut when writing EC header XXXXX");
> + ubi_ro_mode(ubi);
> return -EROFS;
> + }
>
> err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
> return err;
> @@ -1071,8 +1074,11 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum,
> if (err)
> return err;
>
> - if (ubi_dbg_power_cut(ubi, POWER_CUT_VID_WRITE))
> + if (ubi_dbg_is_power_cut(ubi, MASK_POWER_CUT_VID)) {
> + ubi_warn(ubi, "XXXXX emulating a power cut when writing VID header XXXXX");
> + ubi_ro_mode(ubi);
> return -EROFS;
> + }
>
> err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
> ubi->vid_hdr_alsize);
> diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
> index c8f1bd4fa100..41f57d5717b2 100644
> --- a/drivers/mtd/ubi/ubi.h
> +++ b/drivers/mtd/ubi/ubi.h
> @@ -142,17 +142,6 @@ enum {
> UBI_BAD_FASTMAP,
> };
>
> -/*
> - * Flags for emulate_power_cut in ubi_debug_info
> - *
> - * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header
> - * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header
> - */
> -enum {
> - POWER_CUT_EC_WRITE = 0x01,
> - POWER_CUT_VID_WRITE = 0x02,
> -};
> -
> /**
> * struct ubi_vid_io_buf - VID buffer used to read/write VID info to/from the
> * flash.
> @@ -401,6 +390,7 @@ struct ubi_volume_desc {
> * @power_cut_counter: count down for writes left until emulated power cut
> * @power_cut_min: minimum number of writes before emulating a power cut
> * @power_cut_max: maximum number of writes until emulating a power cut
> + * @emulate_failures: emulate failures for testing purposes
> * @dfs_dir_name: name of debugfs directory containing files of this UBI device
> * @dfs_dir: direntry object of the UBI device debugfs directory
> * @dfs_chk_gen: debugfs knob to enable UBI general extra checks
> @@ -412,6 +402,7 @@ struct ubi_volume_desc {
> * @dfs_emulate_power_cut: debugfs knob to emulate power cuts
> * @dfs_power_cut_min: debugfs knob for minimum writes before power cut
> * @dfs_power_cut_max: debugfs knob for maximum writes until power cut
> + * @dfs_emulate_failures: debugfs entry to control the fault injection type
> */
> struct ubi_debug_info {
> unsigned int chk_gen:1;
> @@ -424,6 +415,7 @@ struct ubi_debug_info {
> unsigned int power_cut_counter;
> unsigned int power_cut_min;
> unsigned int power_cut_max;
> + unsigned int emulate_failures;
> char dfs_dir_name[UBI_DFS_DIR_LEN + 1];
> struct dentry *dfs_dir;
> struct dentry *dfs_chk_gen;
> @@ -435,6 +427,7 @@ struct ubi_debug_info {
> struct dentry *dfs_emulate_power_cut;
> struct dentry *dfs_power_cut_min;
> struct dentry *dfs_power_cut_max;
> + struct dentry *dfs_emulate_failures;
> };
>
> /**
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH V2 2/5] ubi: Split io_failures into write_failure and erase_failure
2023-07-18 8:51 [PATCH V2 0/5] ubi: Enhanced fault injection capability for the UBI driver ZhaoLong Wang
2023-07-18 8:51 ` [PATCH V2 1/5] ubi: Use the fault injection framework to enhance the fault injection capability ZhaoLong Wang
@ 2023-07-18 8:51 ` ZhaoLong Wang
2023-07-31 11:24 ` Zhihao Cheng
2023-07-18 8:51 ` [PATCH V2 3/5] ubi: Add six fault injection type for testing ZhaoLong Wang
` (2 subsequent siblings)
4 siblings, 1 reply; 13+ messages in thread
From: ZhaoLong Wang @ 2023-07-18 8:51 UTC (permalink / raw)
To: richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang
The emulate_io_failures debugfs entry controls both write
failure and erase failure. This patch split io_failures
to write_failure and erase_failure.
Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
---
drivers/mtd/ubi/debug.c | 13 +++++++++----
drivers/mtd/ubi/debug.h | 14 ++++++++------
2 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 9ca584da32c6..7826bc8166e8 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -14,7 +14,8 @@
#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_write_failure_attr);
+static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
static DECLARE_FAULT_ATTR(fault_power_cut_attr);
#define FAIL_ACTION(name, fault_attr) \
@@ -24,7 +25,8 @@ bool should_fail_##name(void) \
}
FAIL_ACTION(bitflips, fault_bitflips_attr)
-FAIL_ACTION(io_failures, fault_io_failures_attr)
+FAIL_ACTION(write_failure, fault_write_failure_attr)
+FAIL_ACTION(erase_failure, fault_erase_failure_attr)
FAIL_ACTION(power_cut, fault_power_cut_attr)
#endif
@@ -245,8 +247,11 @@ static void dfs_create_fault_entry(struct dentry *parent)
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_write_failure", dir,
+ &fault_write_failure_attr);
+
+ fault_create_debugfs_attr("emulate_erase_failure", dir,
+ &fault_erase_failure_attr);
fault_create_debugfs_attr("emulate_power_cut", dir,
&fault_power_cut_attr);
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index fc4234c9a90a..6bc698b38e35 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -92,10 +92,12 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
/* Emulate bit-flips */
#define MASK_BITFLIPS (1 << 3)
/* Emulates -EIO during write/erase */
-#define MASK_IO_FAILURE (1 << 4)
+#define MASK_WRITE_FAILURE (1 << 4)
+#define MASK_ERASE_FAILURE (1 << 5)
extern bool should_fail_bitflips(void);
-extern bool should_fail_io_failures(void);
+extern bool should_fail_write_failure(void);
+extern bool should_fail_erase_failure(void);
extern bool should_fail_power_cut(void);
static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
@@ -107,15 +109,15 @@ static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
static inline bool ubi_dbg_fail_write(const struct ubi_device *ubi)
{
- if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
- return should_fail_io_failures();
+ if (ubi->dbg.emulate_failures & MASK_WRITE_FAILURE)
+ return should_fail_write_failure();
return false;
}
static inline bool ubi_dbg_fail_erase(const struct ubi_device *ubi)
{
- if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
- return should_fail_io_failures();
+ if (ubi->dbg.emulate_failures & MASK_ERASE_FAILURE)
+ return should_fail_erase_failure();
return false;
}
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 2/5] ubi: Split io_failures into write_failure and erase_failure
2023-07-18 8:51 ` [PATCH V2 2/5] ubi: Split io_failures into write_failure and erase_failure ZhaoLong Wang
@ 2023-07-31 11:24 ` Zhihao Cheng
0 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 11:24 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> The emulate_io_failures debugfs entry controls both write
> failure and erase failure. This patch split io_failures
> to write_failure and erase_failure.
>
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> drivers/mtd/ubi/debug.c | 13 +++++++++----
> drivers/mtd/ubi/debug.h | 14 ++++++++------
> 2 files changed, 17 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 9ca584da32c6..7826bc8166e8 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -14,7 +14,8 @@
>
> #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_write_failure_attr);
> +static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
> static DECLARE_FAULT_ATTR(fault_power_cut_attr);
>
> #define FAIL_ACTION(name, fault_attr) \
> @@ -24,7 +25,8 @@ bool should_fail_##name(void) \
> }
>
> FAIL_ACTION(bitflips, fault_bitflips_attr)
> -FAIL_ACTION(io_failures, fault_io_failures_attr)
> +FAIL_ACTION(write_failure, fault_write_failure_attr)
> +FAIL_ACTION(erase_failure, fault_erase_failure_attr)
> FAIL_ACTION(power_cut, fault_power_cut_attr)
> #endif
>
> @@ -245,8 +247,11 @@ static void dfs_create_fault_entry(struct dentry *parent)
> 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_write_failure", dir,
> + &fault_write_failure_attr);
> +
> + fault_create_debugfs_attr("emulate_erase_failure", dir,
> + &fault_erase_failure_attr);
>
> fault_create_debugfs_attr("emulate_power_cut", dir,
> &fault_power_cut_attr);
> diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
> index fc4234c9a90a..6bc698b38e35 100644
> --- a/drivers/mtd/ubi/debug.h
> +++ b/drivers/mtd/ubi/debug.h
> @@ -92,10 +92,12 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
> /* Emulate bit-flips */
> #define MASK_BITFLIPS (1 << 3)
> /* Emulates -EIO during write/erase */
> -#define MASK_IO_FAILURE (1 << 4)
> +#define MASK_WRITE_FAILURE (1 << 4)
> +#define MASK_ERASE_FAILURE (1 << 5)
>
> extern bool should_fail_bitflips(void);
> -extern bool should_fail_io_failures(void);
> +extern bool should_fail_write_failure(void);
> +extern bool should_fail_erase_failure(void);
> extern bool should_fail_power_cut(void);
>
> static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
> @@ -107,15 +109,15 @@ static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
>
> static inline bool ubi_dbg_fail_write(const struct ubi_device *ubi)
> {
> - if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
> - return should_fail_io_failures();
> + if (ubi->dbg.emulate_failures & MASK_WRITE_FAILURE)
> + return should_fail_write_failure();
> return false;
> }
>
> static inline bool ubi_dbg_fail_erase(const struct ubi_device *ubi)
> {
> - if (ubi->dbg.emulate_failures & MASK_IO_FAILURE)
> - return should_fail_io_failures();
> + if (ubi->dbg.emulate_failures & MASK_ERASE_FAILURE)
> + return should_fail_erase_failure();
> return false;
> }
>
>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH V2 3/5] ubi: Add six fault injection type for testing
2023-07-18 8:51 [PATCH V2 0/5] ubi: Enhanced fault injection capability for the UBI driver ZhaoLong Wang
2023-07-18 8:51 ` [PATCH V2 1/5] ubi: Use the fault injection framework to enhance the fault injection capability ZhaoLong Wang
2023-07-18 8:51 ` [PATCH V2 2/5] ubi: Split io_failures into write_failure and erase_failure ZhaoLong Wang
@ 2023-07-18 8:51 ` ZhaoLong Wang
2023-07-31 11:57 ` Zhihao Cheng
` (2 more replies)
2023-07-18 8:51 ` [PATCH V2 4/5] ubi: Reserve sufficient buffer length for the input mask ZhaoLong Wang
2023-07-18 8:51 ` [PATCH V2 5/5] mtd: Add several functions to the fail_function list ZhaoLong Wang
4 siblings, 3 replies; 13+ messages in thread
From: ZhaoLong Wang @ 2023-07-18 8:51 UTC (permalink / raw)
To: richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang
This commit adds six fault injection type for testing to cover the
abnormal path of the UBI driver.
Inject the following faults when the UBI reads the LEB:
+----------------------------+-----------------------------------+
| Interface name | emulate behavior |
+----------------------------+-----------------------------------+
| emulate_eccerr | ECC error |
+----------------------------+-----------------------------------+
| emulate_read_failure | read failure |
|----------------------------+-----------------------------------+
| emulate_io_ff | read content as all FF |
|----------------------------+-----------------------------------+
| emulate_io_ff_bitflips | content FF with MTD err reported |
+----------------------------+-----------------------------------+
| emulate_bad_hdr | bad leb header |
|----------------------------+-----------------------------------+
| emulate_bad_hdr_ebadmsg | bad header with ECC err |
+----------------------------+-----------------------------------+
Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
---
drivers/mtd/ubi/debug.c | 30 +++++++++
drivers/mtd/ubi/debug.h | 132 ++++++++++++++++++++++++++++++++++++++--
drivers/mtd/ubi/io.c | 75 ++++++++++++++++++++++-
drivers/mtd/ubi/ubi.h | 31 ++++++----
4 files changed, 248 insertions(+), 20 deletions(-)
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 7826bc8166e8..016a861c5029 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -13,10 +13,16 @@
#include <linux/fault-inject.h>
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+static DECLARE_FAULT_ATTR(fault_eccerr_attr);
static DECLARE_FAULT_ATTR(fault_bitflips_attr);
+static DECLARE_FAULT_ATTR(fault_read_failure_attr);
static DECLARE_FAULT_ATTR(fault_write_failure_attr);
static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
static DECLARE_FAULT_ATTR(fault_power_cut_attr);
+static DECLARE_FAULT_ATTR(fault_io_ff_attr);
+static DECLARE_FAULT_ATTR(fault_io_ff_bitflips_attr);
+static DECLARE_FAULT_ATTR(fault_bad_hdr_attr);
+static DECLARE_FAULT_ATTR(fault_bad_hdr_ebadmsg_attr);
#define FAIL_ACTION(name, fault_attr) \
bool should_fail_##name(void) \
@@ -24,10 +30,16 @@ bool should_fail_##name(void) \
return should_fail(&fault_attr, 1); \
}
+FAIL_ACTION(eccerr, fault_eccerr_attr)
FAIL_ACTION(bitflips, fault_bitflips_attr)
+FAIL_ACTION(read_failure, fault_read_failure_attr)
FAIL_ACTION(write_failure, fault_write_failure_attr)
FAIL_ACTION(erase_failure, fault_erase_failure_attr)
FAIL_ACTION(power_cut, fault_power_cut_attr)
+FAIL_ACTION(io_ff, fault_io_ff_attr)
+FAIL_ACTION(io_ff_bitflips, fault_io_ff_bitflips_attr)
+FAIL_ACTION(bad_hdr, fault_bad_hdr_attr)
+FAIL_ACTION(bad_hdr_ebadmsg, fault_bad_hdr_ebadmsg_attr)
#endif
/**
@@ -244,6 +256,12 @@ static void dfs_create_fault_entry(struct dentry *parent)
return;
}
+ fault_create_debugfs_attr("emulate_eccerr", dir,
+ &fault_eccerr_attr);
+
+ fault_create_debugfs_attr("emulate_read_failure", dir,
+ &fault_read_failure_attr);
+
fault_create_debugfs_attr("emulate_bitflips", dir,
&fault_bitflips_attr);
@@ -255,6 +273,18 @@ static void dfs_create_fault_entry(struct dentry *parent)
fault_create_debugfs_attr("emulate_power_cut", dir,
&fault_power_cut_attr);
+
+ fault_create_debugfs_attr("emulate_io_ff", dir,
+ &fault_io_ff_attr);
+
+ fault_create_debugfs_attr("emulate_io_ff_bitflips", dir,
+ &fault_io_ff_bitflips_attr);
+
+ fault_create_debugfs_attr("emulate_bad_hdr", dir,
+ &fault_bad_hdr_attr);
+
+ fault_create_debugfs_attr("emulate_bad_hdr_ebadmsg", dir,
+ &fault_bad_hdr_ebadmsg_attr);
}
#endif
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
index 6bc698b38e35..29fbd971964a 100644
--- a/drivers/mtd/ubi/debug.h
+++ b/drivers/mtd/ubi/debug.h
@@ -85,20 +85,47 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
* precisely control the type and process of fault injection.
*/
/* Emulate a power cut when writing EC/VID header */
-#define MASK_POWER_CUT_EC (1 << 1)
-#define MASK_POWER_CUT_VID (1 << 2)
+#define MASK_POWER_CUT_EC (1 << 0)
+#define MASK_POWER_CUT_VID (1 << 1)
#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+/* Emulate a power cut when writing data*/
+#define MASK_POWER_CUT_DATA (1 << 2)
/* Emulate bit-flips */
-#define MASK_BITFLIPS (1 << 3)
-/* Emulates -EIO during write/erase */
-#define MASK_WRITE_FAILURE (1 << 4)
-#define MASK_ERASE_FAILURE (1 << 5)
+#define MASK_BITFLIPS (1 << 3)
+/* Emulate ecc error */
+#define MASK_ECCERR (1 << 4)
+/* Emulates -EIO during data read */
+#define MASK_READ_FAILURE (1 << 5)
+#define MASK_READ_FAILURE_EC (1 << 6)
+#define MASK_READ_FAILURE_VID (1 << 7)
+/* Emulates -EIO during data write */
+#define MASK_WRITE_FAILURE (1 << 8)
+/* Emulates -EIO during erase a PEB*/
+#define MASK_ERASE_FAILURE (1 << 9)
+/* Return UBI_IO_FF when reading EC/VID header */
+#define MASK_IO_FF_EC (1 << 10)
+#define MASK_IO_FF_VID (1 << 11)
+/* Return UBI_IO_FF_BITFLIPS when reading EC/VID header */
+#define MASK_IO_FF_BITFLIPS_EC (1 << 12)
+#define MASK_IO_FF_BITFLIPS_VID (1 << 13)
+/* Return UBI_IO_BAD_HDR when reading EC/VID header */
+#define MASK_BAD_HDR_EC (1 << 14)
+#define MASK_BAD_HDR_VID (1 << 15)
+/* Return UBI_IO_BAD_HDR_EBADMSG when reading EC/VID header */
+#define MASK_BAD_HDR_EBADMSG_EC (1 << 16)
+#define MASK_BAD_HDR_EBADMSG_VID (1 << 17)
+extern bool should_fail_eccerr(void);
extern bool should_fail_bitflips(void);
+extern bool should_fail_read_failure(void);
extern bool should_fail_write_failure(void);
extern bool should_fail_erase_failure(void);
extern bool should_fail_power_cut(void);
+extern bool should_fail_io_ff(void);
+extern bool should_fail_io_ff_bitflips(void);
+extern bool should_fail_bad_hdr(void);
+extern bool should_fail_bad_hdr_ebadmsg(void);
static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
{
@@ -192,6 +219,99 @@ static inline bool ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
return ubi_dbg_fail_erase(ubi);
}
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+/**
+ * ubi_dbg_is_eccerr - if it is time to emulate ECC error.
+ * @ubi: UBI device description object
+ *
+ * Returns true if a ECC error should be emulated, otherwise returns false.
+ */
+static inline bool ubi_dbg_is_eccerr(const struct ubi_device *ubi)
+{
+ if (ubi->dbg.emulate_failures & MASK_ECCERR)
+ return should_fail_eccerr();
+ return false;
+}
+
+/**
+ * ubi_dbg_is_read_failure - if it is time to emulate a read failure.
+ * @ubi: UBI device description object
+ *
+ * Returns true if a read failure should be emulated, otherwise returns
+ * false.
+ */
+static inline bool ubi_dbg_is_read_failure(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_read_failure();
+ return false;
+}
+
+/**
+ * ubi_dbg_is_ff - if it is time to emulate that read region is only 0xFF.
+ * @ubi: UBI device description object
+ *
+ * Returns true if read region should be emulated 0xFF, otherwise
+ * returns false.
+ */
+static inline bool ubi_dbg_is_ff(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_io_ff();
+ return false;
+}
+
+/**
+ * ubi_dbg_is_ff_bitflips - if it is time to emulate that read region is only 0xFF
+ * with error reported by the MTD driver
+ *
+ * @ubi: UBI device description object
+ *
+ * Returns true if read region should be emulated 0xFF and error
+ * reported by the MTD driver, otherwise returns false.
+ */
+static inline bool ubi_dbg_is_ff_bitflips(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_io_ff_bitflips();
+ return false;
+}
+
+/**
+ * ubi_dbg_is_bad_hdr - if it is time to emulate a bad header
+ * @ubi: UBI device description object
+ *
+ * Returns true if a bad header error should be emulated, otherwise
+ * returns false.
+ */
+static inline bool ubi_dbg_is_bad_hdr(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_bad_hdr();
+ return false;
+}
+
+/**
+ * ubi_dbg_is_bad_hdr_ebadmsg - if it is time to emulate a bad header with
+ * ECC error.
+ *
+ * @ubi: UBI device description object
+ *
+ * Returns true if a bad header with ECC error should be emulated, otherwise
+ * returns false.
+ */
+static inline bool ubi_dbg_is_bad_hdr_ebadmsg(const struct ubi_device *ubi,
+ unsigned int caller)
+{
+ if (ubi->dbg.emulate_failures & caller)
+ return should_fail_bad_hdr_ebadmsg();
+ return false;
+}
+#endif
/**
* ubi_dbg_is_bgt_disabled - if the background thread is disabled.
* @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
index ffa7bbf27bc2..059032132bdd 100644
--- a/drivers/mtd/ubi/io.c
+++ b/drivers/mtd/ubi/io.c
@@ -197,6 +197,19 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
dbg_gen("bit-flip (emulated)");
err = UBI_IO_BITFLIPS;
}
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+ if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE)) {
+ ubi_warn(ubi, "cannot read %d bytes from PEB %d:%d (emulated)",
+ len, pnum, offset);
+ return -EIO;
+ }
+
+ if (ubi_dbg_is_eccerr(ubi)) {
+ ubi_warn(ubi, "ECC error (emulated) while reading %d bytes from PEB %d:%d, read %zd bytes",
+ len, pnum, offset, read);
+ return -EBADMSG;
+ }
+#endif
}
return err;
@@ -782,7 +795,36 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
* If there was %-EBADMSG, but the header CRC is still OK, report about
* a bit-flip to force scrubbing on this PEB.
*/
- return read_err ? UBI_IO_BITFLIPS : 0;
+ if (read_err)
+ return UBI_IO_BITFLIPS;
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+ if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_EC)) {
+ ubi_warn(ubi, "cannot read EC header from PEB %d(emulated)",
+ pnum);
+ return -EIO;
+ }
+
+ if (ubi_dbg_is_ff(ubi, MASK_IO_FF_EC)) {
+ ubi_warn(ubi, "bit-all-ff (emulated)");
+ return UBI_IO_FF;
+ }
+
+ if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_EC)) {
+ ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)");
+ return UBI_IO_FF_BITFLIPS;
+ }
+
+ if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_EC)) {
+ ubi_warn(ubi, "bad_hdr (emulated)");
+ return UBI_IO_BAD_HDR;
+ }
+
+ if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_EC)) {
+ ubi_warn(ubi, "bad_hdr with ECC error (emulated)");
+ return UBI_IO_BAD_HDR_EBADMSG;
+ }
+#endif
+ return 0;
}
/**
@@ -1032,7 +1074,36 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
return -EINVAL;
}
- return read_err ? UBI_IO_BITFLIPS : 0;
+ if (read_err)
+ return UBI_IO_BITFLIPS;
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+ if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_VID)) {
+ ubi_warn(ubi, "cannot read VID header from PEB %d(emulated)",
+ pnum);
+ return -EIO;
+ }
+
+ if (ubi_dbg_is_ff(ubi, MASK_IO_FF_VID)) {
+ ubi_warn(ubi, "bit-all-ff (emulated)\n");
+ return UBI_IO_FF;
+ }
+
+ if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_VID)) {
+ ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)\n");
+ return UBI_IO_FF_BITFLIPS;
+ }
+
+ if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_VID)) {
+ ubi_warn(ubi, "bad_hdr (emulated)\n");
+ return UBI_IO_BAD_HDR;
+ }
+
+ if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_VID)) {
+ ubi_warn(ubi, "bad_hdr with ECC error (emulated)\n");
+ return UBI_IO_BAD_HDR_EBADMSG;
+ }
+#endif
+ return 0;
}
/**
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 41f57d5717b2..36d46425ed4c 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -1117,18 +1117,6 @@ static inline struct ubi_vid_hdr *ubi_get_vid_hdr(struct ubi_vid_io_buf *vidb)
return vidb->hdr;
}
-/*
- * This function is equivalent to 'ubi_io_read()', but @offset is relative to
- * the beginning of the logical eraseblock, not to the beginning of the
- * physical eraseblock.
- */
-static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
- int pnum, int offset, int len)
-{
- ubi_assert(offset >= 0);
- return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
-}
-
/*
* This function is equivalent to 'ubi_io_write()', but @offset is relative to
* the beginning of the logical eraseblock, not to the beginning of the
@@ -1154,6 +1142,25 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
}
}
+/*
+ * This function is equivalent to 'ubi_io_read()', but @offset is relative to
+ * the beginning of the logical eraseblock, not to the beginning of the
+ * physical eraseblock.
+ */
+static inline int ubi_io_read_data(struct ubi_device *ubi, void *buf,
+ int pnum, int offset, int len)
+{
+ ubi_assert(offset >= 0);
+#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
+ if (ubi_dbg_power_cut(ubi, MASK_POWER_CUT_DATA)) {
+ ubi_warn(ubi, "XXXXX emulating a power cut when writing data XXXXX");
+ ubi_ro_mode(ubi);
+ return -EROFS;
+ }
+#endif
+ return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
+}
+
/**
* vol_id2idx - get table index by volume ID.
* @ubi: UBI device description object
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 3/5] ubi: Add six fault injection type for testing
2023-07-18 8:51 ` [PATCH V2 3/5] ubi: Add six fault injection type for testing ZhaoLong Wang
@ 2023-07-31 11:57 ` Zhihao Cheng
2023-07-31 12:09 ` Zhihao Cheng
2023-07-31 12:21 ` Zhihao Cheng
2 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 11:57 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> This commit adds six fault injection type for testing to cover the
> abnormal path of the UBI driver.
>
> Inject the following faults when the UBI reads the LEB:
> +----------------------------+-----------------------------------+
> | Interface name | emulate behavior |
> +----------------------------+-----------------------------------+
> | emulate_eccerr | ECC error |
> +----------------------------+-----------------------------------+
> | emulate_read_failure | read failure |
> |----------------------------+-----------------------------------+
> | emulate_io_ff | read content as all FF |
> |----------------------------+-----------------------------------+
> | emulate_io_ff_bitflips | content FF with MTD err reported |
> +----------------------------+-----------------------------------+
> | emulate_bad_hdr | bad leb header |
> |----------------------------+-----------------------------------+
> | emulate_bad_hdr_ebadmsg | bad header with ECC err |
> +----------------------------+-----------------------------------+
>
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> drivers/mtd/ubi/debug.c | 30 +++++++++
> drivers/mtd/ubi/debug.h | 132 ++++++++++++++++++++++++++++++++++++++--
> drivers/mtd/ubi/io.c | 75 ++++++++++++++++++++++-
> drivers/mtd/ubi/ubi.h | 31 ++++++----
> 4 files changed, 248 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 7826bc8166e8..016a861c5029 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -13,10 +13,16 @@
> #include <linux/fault-inject.h>
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +static DECLARE_FAULT_ATTR(fault_eccerr_attr);
> static DECLARE_FAULT_ATTR(fault_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_read_failure_attr);
> static DECLARE_FAULT_ATTR(fault_write_failure_attr);
> static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
> static DECLARE_FAULT_ATTR(fault_power_cut_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_ebadmsg_attr);
>
> #define FAIL_ACTION(name, fault_attr) \
> bool should_fail_##name(void) \
> @@ -24,10 +30,16 @@ bool should_fail_##name(void) \
> return should_fail(&fault_attr, 1); \
> }
>
> +FAIL_ACTION(eccerr, fault_eccerr_attr)
> FAIL_ACTION(bitflips, fault_bitflips_attr)
> +FAIL_ACTION(read_failure, fault_read_failure_attr)
> FAIL_ACTION(write_failure, fault_write_failure_attr)
> FAIL_ACTION(erase_failure, fault_erase_failure_attr)
> FAIL_ACTION(power_cut, fault_power_cut_attr)
> +FAIL_ACTION(io_ff, fault_io_ff_attr)
> +FAIL_ACTION(io_ff_bitflips, fault_io_ff_bitflips_attr)
> +FAIL_ACTION(bad_hdr, fault_bad_hdr_attr)
> +FAIL_ACTION(bad_hdr_ebadmsg, fault_bad_hdr_ebadmsg_attr)
> #endif
>
> /**
> @@ -244,6 +256,12 @@ static void dfs_create_fault_entry(struct dentry *parent)
> return;
> }
>
> + fault_create_debugfs_attr("emulate_eccerr", dir,
> + &fault_eccerr_attr);
> +
> + fault_create_debugfs_attr("emulate_read_failure", dir,
> + &fault_read_failure_attr);
> +
> fault_create_debugfs_attr("emulate_bitflips", dir,
> &fault_bitflips_attr);
>
> @@ -255,6 +273,18 @@ static void dfs_create_fault_entry(struct dentry *parent)
>
> fault_create_debugfs_attr("emulate_power_cut", dir,
> &fault_power_cut_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff", dir,
> + &fault_io_ff_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff_bitflips", dir,
> + &fault_io_ff_bitflips_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr", dir,
> + &fault_bad_hdr_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr_ebadmsg", dir,
> + &fault_bad_hdr_ebadmsg_attr);
> }
> #endif
>
> diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
> index 6bc698b38e35..29fbd971964a 100644
> --- a/drivers/mtd/ubi/debug.h
> +++ b/drivers/mtd/ubi/debug.h
> @@ -85,20 +85,47 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
> * precisely control the type and process of fault injection.
> */
> /* Emulate a power cut when writing EC/VID header */
> -#define MASK_POWER_CUT_EC (1 << 1)
> -#define MASK_POWER_CUT_VID (1 << 2)
> +#define MASK_POWER_CUT_EC (1 << 0)
> +#define MASK_POWER_CUT_VID (1 << 1)
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/* Emulate a power cut when writing data*/
> +#define MASK_POWER_CUT_DATA (1 << 2)
> /* Emulate bit-flips */
> -#define MASK_BITFLIPS (1 << 3)
> -/* Emulates -EIO during write/erase */
> -#define MASK_WRITE_FAILURE (1 << 4)
> -#define MASK_ERASE_FAILURE (1 << 5)
> +#define MASK_BITFLIPS (1 << 3)
> +/* Emulate ecc error */
> +#define MASK_ECCERR (1 << 4)
> +/* Emulates -EIO during data read */
> +#define MASK_READ_FAILURE (1 << 5)
> +#define MASK_READ_FAILURE_EC (1 << 6)
> +#define MASK_READ_FAILURE_VID (1 << 7)
> +/* Emulates -EIO during data write */
> +#define MASK_WRITE_FAILURE (1 << 8)
> +/* Emulates -EIO during erase a PEB*/
> +#define MASK_ERASE_FAILURE (1 << 9)
> +/* Return UBI_IO_FF when reading EC/VID header */
> +#define MASK_IO_FF_EC (1 << 10)
> +#define MASK_IO_FF_VID (1 << 11)
> +/* Return UBI_IO_FF_BITFLIPS when reading EC/VID header */
> +#define MASK_IO_FF_BITFLIPS_EC (1 << 12)
> +#define MASK_IO_FF_BITFLIPS_VID (1 << 13)
> +/* Return UBI_IO_BAD_HDR when reading EC/VID header */
> +#define MASK_BAD_HDR_EC (1 << 14)
> +#define MASK_BAD_HDR_VID (1 << 15)
> +/* Return UBI_IO_BAD_HDR_EBADMSG when reading EC/VID header */
> +#define MASK_BAD_HDR_EBADMSG_EC (1 << 16)
> +#define MASK_BAD_HDR_EBADMSG_VID (1 << 17)
>
> +extern bool should_fail_eccerr(void);
> extern bool should_fail_bitflips(void);
> +extern bool should_fail_read_failure(void);
> extern bool should_fail_write_failure(void);
> extern bool should_fail_erase_failure(void);
> extern bool should_fail_power_cut(void);
> +extern bool should_fail_io_ff(void);
> +extern bool should_fail_io_ff_bitflips(void);
> +extern bool should_fail_bad_hdr(void);
> +extern bool should_fail_bad_hdr_ebadmsg(void);
>
> static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
> {
> @@ -192,6 +219,99 @@ static inline bool ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
> return ubi_dbg_fail_erase(ubi);
> }
>
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/**
> + * ubi_dbg_is_eccerr - if it is time to emulate ECC error.
> + * @ubi: UBI device description object
> + *
> + * Returns true if a ECC error should be emulated, otherwise returns false.
> + */
> +static inline bool ubi_dbg_is_eccerr(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_failures & MASK_ECCERR)
> + return should_fail_eccerr();
> + return false;
> +}
I prefer to keep the same style as ubi_dbg_fail_bitflip, which means
that define two functions corresponding to enabling
CONFIG_MTD_UBI_FAULT_INJECTION and disabling CONFIG_MTD_UBI_FAULT_INJECTION.
> +
> +/**
> + * ubi_dbg_is_read_failure - if it is time to emulate a read failure.
> + * @ubi: UBI device description object
> + *
> + * Returns true if a read failure should be emulated, otherwise returns
> + * false.
> + */
> +static inline bool ubi_dbg_is_read_failure(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_read_failure();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_ff - if it is time to emulate that read region is only 0xFF.
> + * @ubi: UBI device description object
> + *
> + * Returns true if read region should be emulated 0xFF, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_ff(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_io_ff();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_ff_bitflips - if it is time to emulate that read region is only 0xFF
> + * with error reported by the MTD driver
> + *
> + * @ubi: UBI device description object
> + *
> + * Returns true if read region should be emulated 0xFF and error
> + * reported by the MTD driver, otherwise returns false.
> + */
> +static inline bool ubi_dbg_is_ff_bitflips(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_io_ff_bitflips();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_bad_hdr - if it is time to emulate a bad header
> + * @ubi: UBI device description object
> + *
> + * Returns true if a bad header error should be emulated, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_bad_hdr(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_bad_hdr();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_bad_hdr_ebadmsg - if it is time to emulate a bad header with
> + * ECC error.
> + *
> + * @ubi: UBI device description object
> + *
> + * Returns true if a bad header with ECC error should be emulated, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_bad_hdr_ebadmsg(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_bad_hdr_ebadmsg();
> + return false;
> +}
> +#endif
> /**
> * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
> * @ubi: UBI device description object
> diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
> index ffa7bbf27bc2..059032132bdd 100644
> --- a/drivers/mtd/ubi/io.c
> +++ b/drivers/mtd/ubi/io.c
> @@ -197,6 +197,19 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
> dbg_gen("bit-flip (emulated)");
> err = UBI_IO_BITFLIPS;
> }
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE)) {
> + ubi_warn(ubi, "cannot read %d bytes from PEB %d:%d (emulated)",
> + len, pnum, offset);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_eccerr(ubi)) {
> + ubi_warn(ubi, "ECC error (emulated) while reading %d bytes from PEB %d:%d, read %zd bytes",
> + len, pnum, offset, read);
> + return -EBADMSG;
> + }
> +#endif
> }
>
> return err;
> @@ -782,7 +795,36 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
> * If there was %-EBADMSG, but the header CRC is still OK, report about
> * a bit-flip to force scrubbing on this PEB.
> */
> - return read_err ? UBI_IO_BITFLIPS : 0;
> + if (read_err)
> + return UBI_IO_BITFLIPS;
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_EC)) {
> + ubi_warn(ubi, "cannot read EC header from PEB %d(emulated)",
> + pnum);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_ff(ubi, MASK_IO_FF_EC)) {
> + ubi_warn(ubi, "bit-all-ff (emulated)");
> + return UBI_IO_FF;
> + }
> +
> + if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_EC)) {
> + ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)");
> + return UBI_IO_FF_BITFLIPS;
> + }
> +
> + if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_EC)) {
> + ubi_warn(ubi, "bad_hdr (emulated)");
> + return UBI_IO_BAD_HDR;
> + }
> +
> + if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_EC)) {
> + ubi_warn(ubi, "bad_hdr with ECC error (emulated)");
> + return UBI_IO_BAD_HDR_EBADMSG;
> + }
> +#endif
> + return 0;
> }
>
> /**
> @@ -1032,7 +1074,36 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
> return -EINVAL;
> }
>
> - return read_err ? UBI_IO_BITFLIPS : 0;
> + if (read_err)
> + return UBI_IO_BITFLIPS;
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_VID)) {
> + ubi_warn(ubi, "cannot read VID header from PEB %d(emulated)",
> + pnum);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_ff(ubi, MASK_IO_FF_VID)) {
> + ubi_warn(ubi, "bit-all-ff (emulated)\n");
> + return UBI_IO_FF;
> + }
> +
> + if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_VID)) {
> + ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)\n");
> + return UBI_IO_FF_BITFLIPS;
> + }
> +
> + if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_VID)) {
> + ubi_warn(ubi, "bad_hdr (emulated)\n");
> + return UBI_IO_BAD_HDR;
> + }
> +
> + if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_VID)) {
> + ubi_warn(ubi, "bad_hdr with ECC error (emulated)\n");
> + return UBI_IO_BAD_HDR_EBADMSG;
> + }
> +#endif
> + return 0;
> }
>
> /**
> diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
> index 41f57d5717b2..36d46425ed4c 100644
> --- a/drivers/mtd/ubi/ubi.h
> +++ b/drivers/mtd/ubi/ubi.h
> @@ -1117,18 +1117,6 @@ static inline struct ubi_vid_hdr *ubi_get_vid_hdr(struct ubi_vid_io_buf *vidb)
> return vidb->hdr;
> }
>
> -/*
> - * This function is equivalent to 'ubi_io_read()', but @offset is relative to
> - * the beginning of the logical eraseblock, not to the beginning of the
> - * physical eraseblock.
> - */
> -static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
> - int pnum, int offset, int len)
> -{
> - ubi_assert(offset >= 0);
> - return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
> -}
> -
> /*
> * This function is equivalent to 'ubi_io_write()', but @offset is relative to
> * the beginning of the logical eraseblock, not to the beginning of the
> @@ -1154,6 +1142,25 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
> }
> }
>
> +/*
> + * This function is equivalent to 'ubi_io_read()', but @offset is relative to
> + * the beginning of the logical eraseblock, not to the beginning of the
> + * physical eraseblock.
> + */
> +static inline int ubi_io_read_data(struct ubi_device *ubi, void *buf,
> + int pnum, int offset, int len)
I thought you want to modify 'ubi_io_write_data'.
> +{
> + ubi_assert(offset >= 0);
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_power_cut(ubi, MASK_POWER_CUT_DATA)) {
> + ubi_warn(ubi, "XXXXX emulating a power cut when writing data XXXXX");
> + ubi_ro_mode(ubi);
> + return -EROFS;
> + }
> +#endif
> + return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
> +}
> +
> /**
> * vol_id2idx - get table index by volume ID.
> * @ubi: UBI device description object
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 3/5] ubi: Add six fault injection type for testing
2023-07-18 8:51 ` [PATCH V2 3/5] ubi: Add six fault injection type for testing ZhaoLong Wang
2023-07-31 11:57 ` Zhihao Cheng
@ 2023-07-31 12:09 ` Zhihao Cheng
2023-07-31 12:21 ` Zhihao Cheng
2 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 12:09 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> This commit adds six fault injection type for testing to cover the
> abnormal path of the UBI driver.
>
> Inject the following faults when the UBI reads the LEB:
> +----------------------------+-----------------------------------+
> | Interface name | emulate behavior |
> +----------------------------+-----------------------------------+
> | emulate_eccerr | ECC error |
> +----------------------------+-----------------------------------+
> | emulate_read_failure | read failure |
> |----------------------------+-----------------------------------+
> | emulate_io_ff | read content as all FF |
> |----------------------------+-----------------------------------+
> | emulate_io_ff_bitflips | content FF with MTD err reported |
> +----------------------------+-----------------------------------+
> | emulate_bad_hdr | bad leb header |
> |----------------------------+-----------------------------------+
> | emulate_bad_hdr_ebadmsg | bad header with ECC err |
> +----------------------------+-----------------------------------+
>
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> drivers/mtd/ubi/debug.c | 30 +++++++++
> drivers/mtd/ubi/debug.h | 132 ++++++++++++++++++++++++++++++++++++++--
> drivers/mtd/ubi/io.c | 75 ++++++++++++++++++++++-
> drivers/mtd/ubi/ubi.h | 31 ++++++----
> 4 files changed, 248 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 7826bc8166e8..016a861c5029 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -13,10 +13,16 @@
> #include <linux/fault-inject.h>
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +static DECLARE_FAULT_ATTR(fault_eccerr_attr);
> static DECLARE_FAULT_ATTR(fault_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_read_failure_attr);
> static DECLARE_FAULT_ATTR(fault_write_failure_attr);
> static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
> static DECLARE_FAULT_ATTR(fault_power_cut_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_ebadmsg_attr);
>
> #define FAIL_ACTION(name, fault_attr) \
> bool should_fail_##name(void) \
> @@ -24,10 +30,16 @@ bool should_fail_##name(void) \
> return should_fail(&fault_attr, 1); \
> }
>
> +FAIL_ACTION(eccerr, fault_eccerr_attr)
> FAIL_ACTION(bitflips, fault_bitflips_attr)
> +FAIL_ACTION(read_failure, fault_read_failure_attr)
> FAIL_ACTION(write_failure, fault_write_failure_attr)
> FAIL_ACTION(erase_failure, fault_erase_failure_attr)
> FAIL_ACTION(power_cut, fault_power_cut_attr)
> +FAIL_ACTION(io_ff, fault_io_ff_attr)
> +FAIL_ACTION(io_ff_bitflips, fault_io_ff_bitflips_attr)
> +FAIL_ACTION(bad_hdr, fault_bad_hdr_attr)
> +FAIL_ACTION(bad_hdr_ebadmsg, fault_bad_hdr_ebadmsg_attr)
> #endif
>
> /**
> @@ -244,6 +256,12 @@ static void dfs_create_fault_entry(struct dentry *parent)
> return;
> }
>
> + fault_create_debugfs_attr("emulate_eccerr", dir,
> + &fault_eccerr_attr);
> +
> + fault_create_debugfs_attr("emulate_read_failure", dir,
> + &fault_read_failure_attr);
> +
> fault_create_debugfs_attr("emulate_bitflips", dir,
> &fault_bitflips_attr);
>
> @@ -255,6 +273,18 @@ static void dfs_create_fault_entry(struct dentry *parent)
>
> fault_create_debugfs_attr("emulate_power_cut", dir,
> &fault_power_cut_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff", dir,
> + &fault_io_ff_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff_bitflips", dir,
> + &fault_io_ff_bitflips_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr", dir,
> + &fault_bad_hdr_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr_ebadmsg", dir,
> + &fault_bad_hdr_ebadmsg_attr);
> }
> #endif
>
> diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
> index 6bc698b38e35..29fbd971964a 100644
> --- a/drivers/mtd/ubi/debug.h
> +++ b/drivers/mtd/ubi/debug.h
> @@ -85,20 +85,47 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
> * precisely control the type and process of fault injection.
> */
> /* Emulate a power cut when writing EC/VID header */
> -#define MASK_POWER_CUT_EC (1 << 1)
> -#define MASK_POWER_CUT_VID (1 << 2)
> +#define MASK_POWER_CUT_EC (1 << 0)
> +#define MASK_POWER_CUT_VID (1 << 1)
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/* Emulate a power cut when writing data*/
> +#define MASK_POWER_CUT_DATA (1 << 2)
> /* Emulate bit-flips */
> -#define MASK_BITFLIPS (1 << 3)
> -/* Emulates -EIO during write/erase */
> -#define MASK_WRITE_FAILURE (1 << 4)
> -#define MASK_ERASE_FAILURE (1 << 5)
> +#define MASK_BITFLIPS (1 << 3)
> +/* Emulate ecc error */
> +#define MASK_ECCERR (1 << 4)
> +/* Emulates -EIO during data read */
> +#define MASK_READ_FAILURE (1 << 5)
> +#define MASK_READ_FAILURE_EC (1 << 6)
> +#define MASK_READ_FAILURE_VID (1 << 7)
> +/* Emulates -EIO during data write */
> +#define MASK_WRITE_FAILURE (1 << 8)
> +/* Emulates -EIO during erase a PEB*/
> +#define MASK_ERASE_FAILURE (1 << 9)
> +/* Return UBI_IO_FF when reading EC/VID header */
> +#define MASK_IO_FF_EC (1 << 10)
> +#define MASK_IO_FF_VID (1 << 11)
> +/* Return UBI_IO_FF_BITFLIPS when reading EC/VID header */
> +#define MASK_IO_FF_BITFLIPS_EC (1 << 12)
> +#define MASK_IO_FF_BITFLIPS_VID (1 << 13)
> +/* Return UBI_IO_BAD_HDR when reading EC/VID header */
> +#define MASK_BAD_HDR_EC (1 << 14)
> +#define MASK_BAD_HDR_VID (1 << 15)
> +/* Return UBI_IO_BAD_HDR_EBADMSG when reading EC/VID header */
> +#define MASK_BAD_HDR_EBADMSG_EC (1 << 16)
> +#define MASK_BAD_HDR_EBADMSG_VID (1 << 17)
>
> +extern bool should_fail_eccerr(void);
> extern bool should_fail_bitflips(void);
> +extern bool should_fail_read_failure(void);
> extern bool should_fail_write_failure(void);
> extern bool should_fail_erase_failure(void);
> extern bool should_fail_power_cut(void);
> +extern bool should_fail_io_ff(void);
> +extern bool should_fail_io_ff_bitflips(void);
> +extern bool should_fail_bad_hdr(void);
> +extern bool should_fail_bad_hdr_ebadmsg(void);
>
> static inline bool ubi_dbg_fail_bitflip(const struct ubi_device *ubi)
> {
> @@ -192,6 +219,99 @@ static inline bool ubi_dbg_is_erase_failure(const struct ubi_device *ubi)
> return ubi_dbg_fail_erase(ubi);
> }
>
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/**
> + * ubi_dbg_is_eccerr - if it is time to emulate ECC error.
> + * @ubi: UBI device description object
> + *
> + * Returns true if a ECC error should be emulated, otherwise returns false.
> + */
> +static inline bool ubi_dbg_is_eccerr(const struct ubi_device *ubi)
> +{
> + if (ubi->dbg.emulate_failures & MASK_ECCERR)
> + return should_fail_eccerr();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_read_failure - if it is time to emulate a read failure.
> + * @ubi: UBI device description object
> + *
> + * Returns true if a read failure should be emulated, otherwise returns
> + * false.
> + */
> +static inline bool ubi_dbg_is_read_failure(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_read_failure();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_ff - if it is time to emulate that read region is only 0xFF.
> + * @ubi: UBI device description object
> + *
> + * Returns true if read region should be emulated 0xFF, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_ff(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_io_ff();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_ff_bitflips - if it is time to emulate that read region is only 0xFF
> + * with error reported by the MTD driver
> + *
> + * @ubi: UBI device description object
> + *
> + * Returns true if read region should be emulated 0xFF and error
> + * reported by the MTD driver, otherwise returns false.
> + */
> +static inline bool ubi_dbg_is_ff_bitflips(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_io_ff_bitflips();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_bad_hdr - if it is time to emulate a bad header
> + * @ubi: UBI device description object
> + *
> + * Returns true if a bad header error should be emulated, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_bad_hdr(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_bad_hdr();
> + return false;
> +}
> +
> +/**
> + * ubi_dbg_is_bad_hdr_ebadmsg - if it is time to emulate a bad header with
> + * ECC error.
> + *
> + * @ubi: UBI device description object
> + *
> + * Returns true if a bad header with ECC error should be emulated, otherwise
> + * returns false.
> + */
> +static inline bool ubi_dbg_is_bad_hdr_ebadmsg(const struct ubi_device *ubi,
> + unsigned int caller)
> +{
> + if (ubi->dbg.emulate_failures & caller)
> + return should_fail_bad_hdr_ebadmsg();
> + return false;
> +}
> +#endif
> /**
> * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
> * @ubi: UBI device description object
> diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c
> index ffa7bbf27bc2..059032132bdd 100644
> --- a/drivers/mtd/ubi/io.c
> +++ b/drivers/mtd/ubi/io.c
> @@ -197,6 +197,19 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,
> dbg_gen("bit-flip (emulated)");
> err = UBI_IO_BITFLIPS;
return UBI_IO_BITFLIPS;
> }
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE)) {
> + ubi_warn(ubi, "cannot read %d bytes from PEB %d:%d (emulated)",
> + len, pnum, offset);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_eccerr(ubi)) {
> + ubi_warn(ubi, "ECC error (emulated) while reading %d bytes from PEB %d:%d, read %zd bytes",
> + len, pnum, offset, read);
> + return -EBADMSG;
> + }
> +#endif
> }
>
> return err;
> @@ -782,7 +795,36 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum,
> * If there was %-EBADMSG, but the header CRC is still OK, report about
> * a bit-flip to force scrubbing on this PEB.
> */
> - return read_err ? UBI_IO_BITFLIPS : 0;
> + if (read_err)
> + return UBI_IO_BITFLIPS;
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_EC)) {
> + ubi_warn(ubi, "cannot read EC header from PEB %d(emulated)",
> + pnum);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_ff(ubi, MASK_IO_FF_EC)) {
> + ubi_warn(ubi, "bit-all-ff (emulated)");
> + return UBI_IO_FF;
> + }
> +
> + if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_EC)) {
> + ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)");
> + return UBI_IO_FF_BITFLIPS;
> + }
> +
> + if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_EC)) {
> + ubi_warn(ubi, "bad_hdr (emulated)");
> + return UBI_IO_BAD_HDR;
> + }
> +
> + if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_EC)) {
> + ubi_warn(ubi, "bad_hdr with ECC error (emulated)");
> + return UBI_IO_BAD_HDR_EBADMSG;
> + }
> +#endif
> + return 0;
> }
>
> /**
> @@ -1032,7 +1074,36 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum,
> return -EINVAL;
> }
>
> - return read_err ? UBI_IO_BITFLIPS : 0;
> + if (read_err)
> + return UBI_IO_BITFLIPS;
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_is_read_failure(ubi, MASK_READ_FAILURE_VID)) {
> + ubi_warn(ubi, "cannot read VID header from PEB %d(emulated)",
> + pnum);
> + return -EIO;
> + }
> +
> + if (ubi_dbg_is_ff(ubi, MASK_IO_FF_VID)) {
> + ubi_warn(ubi, "bit-all-ff (emulated)\n");
> + return UBI_IO_FF;
> + }
> +
> + if (ubi_dbg_is_ff_bitflips(ubi, MASK_IO_FF_BITFLIPS_VID)) {
> + ubi_warn(ubi, "bit-all-ff with error reported by MTD driver (emulated)\n");
> + return UBI_IO_FF_BITFLIPS;
> + }
> +
> + if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_VID)) {
> + ubi_warn(ubi, "bad_hdr (emulated)\n");
> + return UBI_IO_BAD_HDR;
> + }
> +
> + if (ubi_dbg_is_bad_hdr_ebadmsg(ubi, MASK_BAD_HDR_EBADMSG_VID)) {
> + ubi_warn(ubi, "bad_hdr with ECC error (emulated)\n");
> + return UBI_IO_BAD_HDR_EBADMSG;
> + }
> +#endif
> + return 0;
> }
>
> /**
> diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
> index 41f57d5717b2..36d46425ed4c 100644
> --- a/drivers/mtd/ubi/ubi.h
> +++ b/drivers/mtd/ubi/ubi.h
> @@ -1117,18 +1117,6 @@ static inline struct ubi_vid_hdr *ubi_get_vid_hdr(struct ubi_vid_io_buf *vidb)
> return vidb->hdr;
> }
>
> -/*
> - * This function is equivalent to 'ubi_io_read()', but @offset is relative to
> - * the beginning of the logical eraseblock, not to the beginning of the
> - * physical eraseblock.
> - */
> -static inline int ubi_io_read_data(const struct ubi_device *ubi, void *buf,
> - int pnum, int offset, int len)
> -{
> - ubi_assert(offset >= 0);
> - return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
> -}
> -
> /*
> * This function is equivalent to 'ubi_io_write()', but @offset is relative to
> * the beginning of the logical eraseblock, not to the beginning of the
> @@ -1154,6 +1142,25 @@ static inline void ubi_ro_mode(struct ubi_device *ubi)
> }
> }
>
> +/*
> + * This function is equivalent to 'ubi_io_read()', but @offset is relative to
> + * the beginning of the logical eraseblock, not to the beginning of the
> + * physical eraseblock.
> + */
> +static inline int ubi_io_read_data(struct ubi_device *ubi, void *buf,
> + int pnum, int offset, int len)
> +{
> + ubi_assert(offset >= 0);
> +#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> + if (ubi_dbg_power_cut(ubi, MASK_POWER_CUT_DATA)) {
> + ubi_warn(ubi, "XXXXX emulating a power cut when writing data XXXXX");
> + ubi_ro_mode(ubi);
> + return -EROFS;
> + }
> +#endif
> + return ubi_io_read(ubi, buf, pnum, offset + ubi->leb_start, len);
> +}
> +
> /**
> * vol_id2idx - get table index by volume ID.
> * @ubi: UBI device description object
>
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 3/5] ubi: Add six fault injection type for testing
2023-07-18 8:51 ` [PATCH V2 3/5] ubi: Add six fault injection type for testing ZhaoLong Wang
2023-07-31 11:57 ` Zhihao Cheng
2023-07-31 12:09 ` Zhihao Cheng
@ 2023-07-31 12:21 ` Zhihao Cheng
2 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 12:21 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> This commit adds six fault injection type for testing to cover the
> abnormal path of the UBI driver.
>
> Inject the following faults when the UBI reads the LEB:
> +----------------------------+-----------------------------------+
> | Interface name | emulate behavior |
> +----------------------------+-----------------------------------+
> | emulate_eccerr | ECC error |
> +----------------------------+-----------------------------------+
> | emulate_read_failure | read failure |
> |----------------------------+-----------------------------------+
> | emulate_io_ff | read content as all FF |
> |----------------------------+-----------------------------------+
> | emulate_io_ff_bitflips | content FF with MTD err reported |
> +----------------------------+-----------------------------------+
> | emulate_bad_hdr | bad leb header |
> |----------------------------+-----------------------------------+
> | emulate_bad_hdr_ebadmsg | bad header with ECC err |
> +----------------------------+-----------------------------------+
>
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> drivers/mtd/ubi/debug.c | 30 +++++++++
> drivers/mtd/ubi/debug.h | 132 ++++++++++++++++++++++++++++++++++++++--
> drivers/mtd/ubi/io.c | 75 ++++++++++++++++++++++-
> drivers/mtd/ubi/ubi.h | 31 ++++++----
> 4 files changed, 248 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 7826bc8166e8..016a861c5029 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -13,10 +13,16 @@
> #include <linux/fault-inject.h>
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +static DECLARE_FAULT_ATTR(fault_eccerr_attr);
> static DECLARE_FAULT_ATTR(fault_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_read_failure_attr);
> static DECLARE_FAULT_ATTR(fault_write_failure_attr);
> static DECLARE_FAULT_ATTR(fault_erase_failure_attr);
> static DECLARE_FAULT_ATTR(fault_power_cut_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_attr);
> +static DECLARE_FAULT_ATTR(fault_io_ff_bitflips_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_attr);
> +static DECLARE_FAULT_ATTR(fault_bad_hdr_ebadmsg_attr);
>
> #define FAIL_ACTION(name, fault_attr) \
> bool should_fail_##name(void) \
> @@ -24,10 +30,16 @@ bool should_fail_##name(void) \
> return should_fail(&fault_attr, 1); \
> }
>
> +FAIL_ACTION(eccerr, fault_eccerr_attr)
> FAIL_ACTION(bitflips, fault_bitflips_attr)
> +FAIL_ACTION(read_failure, fault_read_failure_attr)
> FAIL_ACTION(write_failure, fault_write_failure_attr)
> FAIL_ACTION(erase_failure, fault_erase_failure_attr)
> FAIL_ACTION(power_cut, fault_power_cut_attr)
> +FAIL_ACTION(io_ff, fault_io_ff_attr)
> +FAIL_ACTION(io_ff_bitflips, fault_io_ff_bitflips_attr)
> +FAIL_ACTION(bad_hdr, fault_bad_hdr_attr)
> +FAIL_ACTION(bad_hdr_ebadmsg, fault_bad_hdr_ebadmsg_attr)
> #endif
>
> /**
> @@ -244,6 +256,12 @@ static void dfs_create_fault_entry(struct dentry *parent)
> return;
> }
>
> + fault_create_debugfs_attr("emulate_eccerr", dir,
> + &fault_eccerr_attr);
> +
> + fault_create_debugfs_attr("emulate_read_failure", dir,
> + &fault_read_failure_attr);
> +
> fault_create_debugfs_attr("emulate_bitflips", dir,
> &fault_bitflips_attr);
>
> @@ -255,6 +273,18 @@ static void dfs_create_fault_entry(struct dentry *parent)
>
> fault_create_debugfs_attr("emulate_power_cut", dir,
> &fault_power_cut_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff", dir,
> + &fault_io_ff_attr);
> +
> + fault_create_debugfs_attr("emulate_io_ff_bitflips", dir,
> + &fault_io_ff_bitflips_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr", dir,
> + &fault_bad_hdr_attr);
> +
> + fault_create_debugfs_attr("emulate_bad_hdr_ebadmsg", dir,
> + &fault_bad_hdr_ebadmsg_attr);
> }
> #endif
>
> diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h
> index 6bc698b38e35..29fbd971964a 100644
> --- a/drivers/mtd/ubi/debug.h
> +++ b/drivers/mtd/ubi/debug.h
> @@ -85,20 +85,47 @@ static inline int ubi_dbg_erase_failure(const struct ubi_device *ubi)
> * precisely control the type and process of fault injection.
> */
> /* Emulate a power cut when writing EC/VID header */
> -#define MASK_POWER_CUT_EC (1 << 1)
> -#define MASK_POWER_CUT_VID (1 << 2)
> +#define MASK_POWER_CUT_EC (1 << 0)
> +#define MASK_POWER_CUT_VID (1 << 1)
>
> #ifdef CONFIG_MTD_UBI_FAULT_INJECTION
> +/* Emulate a power cut when writing data*/
> +#define MASK_POWER_CUT_DATA (1 << 2)
> /* Emulate bit-flips */
> -#define MASK_BITFLIPS (1 << 3)
> -/* Emulates -EIO during write/erase */
> -#define MASK_WRITE_FAILURE (1 << 4)
> -#define MASK_ERASE_FAILURE (1 << 5)
> +#define MASK_BITFLIPS (1 << 3)
> +/* Emulate ecc error */
> +#define MASK_ECCERR (1 << 4)
> +/* Emulates -EIO during data read */
> +#define MASK_READ_FAILURE (1 << 5)
> +#define MASK_READ_FAILURE_EC (1 << 6)
> +#define MASK_READ_FAILURE_VID (1 << 7)
> +/* Emulates -EIO during data write */
> +#define MASK_WRITE_FAILURE (1 << 8)
> +/* Emulates -EIO during erase a PEB*/
> +#define MASK_ERASE_FAILURE (1 << 9)
> +/* Return UBI_IO_FF when reading EC/VID header */
> +#define MASK_IO_FF_EC (1 << 10)
> +#define MASK_IO_FF_VID (1 << 11)
> +/* Return UBI_IO_FF_BITFLIPS when reading EC/VID header */
> +#define MASK_IO_FF_BITFLIPS_EC (1 << 12)
> +#define MASK_IO_FF_BITFLIPS_VID (1 << 13)
> +/* Return UBI_IO_BAD_HDR when reading EC/VID header */
> +#define MASK_BAD_HDR_EC (1 << 14)
> +#define MASK_BAD_HDR_VID (1 << 15)
> +/* Return UBI_IO_BAD_HDR_EBADMSG when reading EC/VID header */
> +#define MASK_BAD_HDR_EBADMSG_EC (1 << 16)
> +#define MASK_BAD_HDR_EBADMSG_VID (1 << 17)
>
Now, you add many types of fault injections, it's better to make
dfs_file_read display human-readable context for 'd->emulate_failures',
for example:
value:17409
POWER_CUT_EC,MASK_IO_FF_EC,MASK_BAD_HDR_EC
value:0
None
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH V2 4/5] ubi: Reserve sufficient buffer length for the input mask
2023-07-18 8:51 [PATCH V2 0/5] ubi: Enhanced fault injection capability for the UBI driver ZhaoLong Wang
` (2 preceding siblings ...)
2023-07-18 8:51 ` [PATCH V2 3/5] ubi: Add six fault injection type for testing ZhaoLong Wang
@ 2023-07-18 8:51 ` ZhaoLong Wang
2023-07-31 12:13 ` Zhihao Cheng
2023-07-18 8:51 ` [PATCH V2 5/5] mtd: Add several functions to the fail_function list ZhaoLong Wang
4 siblings, 1 reply; 13+ messages in thread
From: ZhaoLong Wang @ 2023-07-18 8:51 UTC (permalink / raw)
To: richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang
Because the mask received by the emulate_failures interface
is a 32-bit unsigned integer, ensure that there is sufficient
buffer length to receive and display this value.
Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
---
V2:
- A 16-byte buffer is reserved, as implemented by other interfaces.
drivers/mtd/ubi/debug.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
index 016a861c5029..1c3f1a2436e5 100644
--- a/drivers/mtd/ubi/debug.c
+++ b/drivers/mtd/ubi/debug.c
@@ -332,7 +332,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
struct dentry *dent = file->f_path.dentry;
struct ubi_device *ubi;
struct ubi_debug_info *d;
- char buf[8];
+ char buf[16];
int val;
ubi = ubi_get_device(ubi_num);
@@ -400,7 +400,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
struct ubi_device *ubi;
struct ubi_debug_info *d;
size_t buf_size;
- char buf[8] = {0};
+ char buf[16] = {0};
int val;
ubi = ubi_get_device(ubi_num);
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 4/5] ubi: Reserve sufficient buffer length for the input mask
2023-07-18 8:51 ` [PATCH V2 4/5] ubi: Reserve sufficient buffer length for the input mask ZhaoLong Wang
@ 2023-07-31 12:13 ` Zhihao Cheng
0 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 12:13 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> Because the mask received by the emulate_failures interface
> is a 32-bit unsigned integer, ensure that there is sufficient
> buffer length to receive and display this value.
>
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> V2:
> - A 16-byte buffer is reserved, as implemented by other interfaces.
>
> drivers/mtd/ubi/debug.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/ubi/debug.c b/drivers/mtd/ubi/debug.c
> index 016a861c5029..1c3f1a2436e5 100644
> --- a/drivers/mtd/ubi/debug.c
> +++ b/drivers/mtd/ubi/debug.c
> @@ -332,7 +332,7 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
> struct dentry *dent = file->f_path.dentry;
> struct ubi_device *ubi;
> struct ubi_debug_info *d;
> - char buf[8];
> + char buf[16];
> int val;
>
> ubi = ubi_get_device(ubi_num);
> @@ -400,7 +400,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *user_buf,
> struct ubi_device *ubi;
> struct ubi_debug_info *d;
> size_t buf_size;
> - char buf[8] = {0};
> + char buf[16] = {0};
> int val;
>
> ubi = ubi_get_device(ubi_num);
>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH V2 5/5] mtd: Add several functions to the fail_function list
2023-07-18 8:51 [PATCH V2 0/5] ubi: Enhanced fault injection capability for the UBI driver ZhaoLong Wang
` (3 preceding siblings ...)
2023-07-18 8:51 ` [PATCH V2 4/5] ubi: Reserve sufficient buffer length for the input mask ZhaoLong Wang
@ 2023-07-18 8:51 ` ZhaoLong Wang
2023-07-31 12:16 ` Zhihao Cheng
4 siblings, 1 reply; 13+ messages in thread
From: ZhaoLong Wang @ 2023-07-18 8:51 UTC (permalink / raw)
To: richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, chengzhihao1, wangzhaolong1, yi.zhang
add mtd_read(), mtd_write(), mtd_erase(), mtd_block_markbad() to
fail_function list for testing purpose
Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
---
drivers/mtd/mtdcore.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index e00b12aa5ec9..ecf1c5e68479 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include <linux/nvmem-provider.h>
#include <linux/root_dev.h>
+#include <linux/error-injection.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
@@ -1396,6 +1397,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
return ret;
}
EXPORT_SYMBOL_GPL(mtd_erase);
+ALLOW_ERROR_INJECTION(mtd_erase, ERRNO);
/*
* This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
@@ -1493,6 +1495,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
return ret;
}
EXPORT_SYMBOL_GPL(mtd_read);
+ALLOW_ERROR_INJECTION(mtd_read, ERRNO);
int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
const u_char *buf)
@@ -1509,6 +1512,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
return ret;
}
EXPORT_SYMBOL_GPL(mtd_write);
+ALLOW_ERROR_INJECTION(mtd_write, ERRNO);
/*
* In blackbox flight recorder like scenarios we want to make successful writes
@@ -2329,7 +2333,7 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
return 0;
}
EXPORT_SYMBOL_GPL(mtd_block_markbad);
-
+ALLOW_ERROR_INJECTION(mtd_block_markbad, ERRNO);
/*
* default_mtd_writev - the default writev method
* @mtd: mtd device description object pointer
--
2.31.1
^ permalink raw reply [flat|nested] 13+ messages in thread* Re: [PATCH V2 5/5] mtd: Add several functions to the fail_function list
2023-07-18 8:51 ` [PATCH V2 5/5] mtd: Add several functions to the fail_function list ZhaoLong Wang
@ 2023-07-31 12:16 ` Zhihao Cheng
0 siblings, 0 replies; 13+ messages in thread
From: Zhihao Cheng @ 2023-07-31 12:16 UTC (permalink / raw)
To: ZhaoLong Wang, richard, miquel.raynal, vigneshr
Cc: linux-mtd, linux-kernel, yi.zhang
在 2023/7/18 16:51, ZhaoLong Wang 写道:
> add mtd_read(), mtd_write(), mtd_erase(), mtd_block_markbad() to
> fail_function list for testing purpose
>
It could be better if you can provide some examples for how to use these
error injection interfaces.
> Signed-off-by: ZhaoLong Wang <wangzhaolong1@huawei.com>
> ---
> drivers/mtd/mtdcore.c | 6 +++++-
> 1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index e00b12aa5ec9..ecf1c5e68479 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -30,6 +30,7 @@
> #include <linux/debugfs.h>
> #include <linux/nvmem-provider.h>
> #include <linux/root_dev.h>
> +#include <linux/error-injection.h>
>
> #include <linux/mtd/mtd.h>
> #include <linux/mtd/partitions.h>
> @@ -1396,6 +1397,7 @@ int mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
> return ret;
> }
> EXPORT_SYMBOL_GPL(mtd_erase);
> +ALLOW_ERROR_INJECTION(mtd_erase, ERRNO);
>
> /*
> * This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
> @@ -1493,6 +1495,7 @@ int mtd_read(struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen,
> return ret;
> }
> EXPORT_SYMBOL_GPL(mtd_read);
> +ALLOW_ERROR_INJECTION(mtd_read, ERRNO);
>
> int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
> const u_char *buf)
> @@ -1509,6 +1512,7 @@ int mtd_write(struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen,
> return ret;
> }
> EXPORT_SYMBOL_GPL(mtd_write);
> +ALLOW_ERROR_INJECTION(mtd_write, ERRNO);
>
> /*
> * In blackbox flight recorder like scenarios we want to make successful writes
> @@ -2329,7 +2333,7 @@ int mtd_block_markbad(struct mtd_info *mtd, loff_t ofs)
> return 0;
> }
> EXPORT_SYMBOL_GPL(mtd_block_markbad);
> -
> +ALLOW_ERROR_INJECTION(mtd_block_markbad, ERRNO);
> /*
> * default_mtd_writev - the default writev method
> * @mtd: mtd device description object pointer
>
^ permalink raw reply [flat|nested] 13+ messages in thread