Unverified Commit 6f62149a authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!3575 ubi: Enhance fault injection capability for the UBI driver

Merge Pull Request from: @ci-robot 
 
PR sync from: ZhaoLong Wang <wangzhaolong1@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/AMOHM7ETGHOHKMCU3UY3PQPNQDLVY2HH/ 
CONFIG Dependency

CONFIG_MTD=y
CONFIG_MTD_NAND_NANDSIM=m
CONFIG_MTD_UBI=m
CONFIG_FAULT_INJECTION_DEBUG_FS=y
CONFIG_MTD_PARTITIONED_MASTER

The existing fault injection capability of UBI is too simple.
It uses hard-coded fault probability values and lacks other
configurable options. As a result, these interfaces are difficult
to use when digging defects in the abnormal path of code and
reproducing some problems.

The kernel provides a powerful fault injection framework, which
provides rich configurable fault injection attributes during runtime.
So it can be used to improve the fault injection capability of the
UBI driver.

This series of patches refactor the existing fault injection interface
and add some fault injection types to help testers and developers
find potential problems in the code.

This series of patches enhance the existing fault injection interface
and retain the old debugfs interface, and add some fault injection types
to help testers and developers Look for potential problems in the code.

v1 -> v2:
Delete the redundant semicolon of the first patch.

v2 -> v3:
Completely checked and fixed the English syntax errors in the patch.

v3 -> v4:
Fixed code indent error

ZhaoLong Wang (5):
  ubi: Use the fault injection framework to enhance the fault injection
    capability
  ubi: Split io_failures into write_failure and erase_failure
  ubi: Add six fault injection type for testing
  ubi: Reserve sufficient buffer length for the input mask
  mtd: Add several functions to the fail_function list


-- 
2.39.2
 
https://gitee.com/openeuler/kernel/issues/I8QZWQ 
 
Link:https://gitee.com/openeuler/kernel/pulls/3575

 

Reviewed-by: default avatarzhangyi (F) <yi.zhang@huawei.com>
Reviewed-by: default avatarLu Jialin <lujialin4@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parents f5ac4b9b 728c9fa3
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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>
@@ -1411,6 +1412,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.
@@ -1508,6 +1510,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)
@@ -1524,6 +1527,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
@@ -2344,6 +2348,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
+9 −0
Original line number Diff line number Diff line
@@ -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 enables fault-injection support for UBI devices for
	   testing purposes.

	   If in doubt, say "N".
endif # MTD_UBI
+100 −8
Original line number Diff line number Diff line
@@ -10,7 +10,37 @@
#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_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)				\
{							\
	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

/**
 * ubi_dump_flash - dump a region of flash.
@@ -212,6 +242,52 @@ 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_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);

	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);

	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

/**
 * ubi_debugfs_init - create UBI debugfs directory.
 *
@@ -232,6 +308,10 @@ int ubi_debugfs_init(void)
		return err;
	}

#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
	dfs_create_fault_entry(dfs_rootdir);
#endif

	return 0;
}

@@ -252,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);
@@ -272,7 +352,12 @@ static ssize_t dfs_file_read(struct file *file, char __user *user_buf,
		val = d->emulate_bitflips;
	else if (dent == d->dfs_emulate_io_failures)
		val = d->emulate_io_failures;
	else if (dent == d->dfs_emulate_power_cut) {
	else if (dent == d->dfs_emulate_failures) {
		snprintf(buf, sizeof(buf), "0x%04x\n", d->emulate_failures);
		count = simple_read_from_buffer(user_buf, count, ppos,
						buf, strlen(buf));
		goto out;
	} else if (dent == d->dfs_emulate_power_cut) {
		snprintf(buf, sizeof(buf), "%u\n", d->emulate_power_cut);
		count = simple_read_from_buffer(user_buf, count, ppos,
						buf, strlen(buf));
@@ -287,8 +372,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;
	}
@@ -316,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);
@@ -330,7 +414,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 +647,12 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
	debugfs_create_file("detailed_erase_block_info", S_IRUSR, d->dfs_dir,
			    (void *)ubi_num, &eraseblk_count_fops);

#ifdef CONFIG_MTD_UBI_FAULT_INJECTION
	d->dfs_emulate_failures = debugfs_create_file("emulate_failures",
						       mode, d->dfs_dir,
						       (void *)ubi_num,
						       &dfs_fops);
#endif
	return 0;
}

@@ -600,7 +694,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;
}
+281 −23
Original line number Diff line number Diff line
@@ -53,56 +53,315 @@ 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 << 0)
#define MASK_POWER_CUT_VID			(1 << 1)
/* Emulate a power cut when writing data*/
#define MASK_POWER_CUT_DATA			(1 << 2)
/* Emulate bit-flips */
#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)

#ifdef CONFIG_MTD_UBI_FAULT_INJECTION

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)
{
	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_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_ERASE_FAILURE)
		return should_fail_erase_failure();
	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;
}

static inline bool ubi_dbg_fail_read(const struct ubi_device *ubi,
				     unsigned int caller)
{
	if (ubi->dbg.emulate_failures & caller)
		return should_fail_read_failure();
	return false;
}

static inline bool ubi_dbg_fail_eccerr(const struct ubi_device *ubi)
{
	if (ubi->dbg.emulate_failures & MASK_ECCERR)
		return should_fail_eccerr();
	return false;
}

static inline bool ubi_dbg_fail_ff(const struct ubi_device *ubi,
				   unsigned int caller)
{
	if (ubi->dbg.emulate_failures & caller)
		return should_fail_io_ff();
	return false;
}

static inline bool ubi_dbg_fail_ff_bitflips(const struct ubi_device *ubi,
					    unsigned int caller)
{
	if (ubi->dbg.emulate_failures & caller)
		return should_fail_io_ff_bitflips();
	return false;
}

static inline bool ubi_dbg_fail_bad_hdr(const struct ubi_device *ubi,
					 unsigned int caller)
{
	if (ubi->dbg.emulate_failures & caller)
		return should_fail_bad_hdr();
	return false;
}

static inline bool ubi_dbg_fail_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;
}
#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
#define ubi_dbg_fail_read(u, c)             false
#define ubi_dbg_fail_eccerr(u)              false
#define ubi_dbg_fail_ff(u, c)               false
#define ubi_dbg_fail_ff_bitflips(u, v)      false
#define ubi_dbg_fail_bad_hdr(u, c)          false
#define ubi_dbg_fail_bad_hdr_ebadmsg(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_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)
{
	return ubi_dbg_fail_eccerr(ubi);
}

/**
 * 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)
{
	return ubi_dbg_fail_read(ubi, caller);
}

/**
 * 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)
{
	return ubi_dbg_fail_ff(ubi, caller);
}

/**
 * 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)
{
	return ubi_dbg_fail_ff_bitflips(ubi, caller);
}

/**
 * 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)
{
	return ubi_dbg_fail_bad_hdr(ubi, caller);
}

/**
 * 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)
{
	return ubi_dbg_fail_bad_hdr_ebadmsg(ubi, caller);
}

/**
 * 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 +384,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__ */
+81 −5
Original line number Diff line number Diff line
@@ -195,7 +195,19 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset,

		if (ubi_dbg_is_bitflip(ubi)) {
			dbg_gen("bit-flip (emulated)");
			err = UBI_IO_BITFLIPS;
			return UBI_IO_BITFLIPS;
		}

		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;
		}
	}

@@ -782,7 +794,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;

	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;
	}

	return 0;
}

/**
@@ -821,8 +862,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, "emulating a power cut when writing EC header");
		ubi_ro_mode(ubi);
		return -EROFS;
	}

	err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize);
	return err;
@@ -1029,7 +1073,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;

	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)");
		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)");
		return UBI_IO_FF_BITFLIPS;
	}

	if (ubi_dbg_is_bad_hdr(ubi, MASK_BAD_HDR_VID)) {
		ubi_warn(ubi, "bad_hdr (emulated)");
		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)");
		return UBI_IO_BAD_HDR_EBADMSG;
	}

	return 0;
}

/**
@@ -1071,8 +1144,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, "emulating a power cut when writing VID header");
		ubi_ro_mode(ubi);
		return -EROFS;
	}

	err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset,
			   ubi->vid_hdr_alsize);
Loading