From adbf05e3ec6ea380ba145b6fa89d9125ed76eb98 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Wed, 20 Jan 2010 10:28:58 +0200 Subject: UBI: simplify debugging return codes UBI debugging functions were a little bit over-engineered and returned more error codes than needed, and the callers had to do useless checks. Simplify the return codes. Impact: only debugging code is affected, which means that for non-developers this is a no-op patch. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/io.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers/mtd/ubi/io.c') diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 8aa51e7a6a7..a2501299a67 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -143,7 +143,7 @@ int ubi_io_read(const struct ubi_device *ubi, void *buf, int pnum, int offset, err = paranoid_check_not_bad(ubi, pnum); if (err) - return err > 0 ? -EINVAL : err; + return err; addr = (loff_t)pnum * ubi->peb_size + offset; retry: @@ -236,12 +236,12 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, err = paranoid_check_not_bad(ubi, pnum); if (err) - return err > 0 ? -EINVAL : err; + return err; /* The area we are writing to has to contain all 0xFF bytes */ err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); if (err) - return err > 0 ? -EINVAL : err; + return err; if (offset >= ubi->leb_start) { /* @@ -250,10 +250,10 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, */ err = paranoid_check_peb_ec_hdr(ubi, pnum); if (err) - return err > 0 ? -EINVAL : err; + return err; err = paranoid_check_peb_vid_hdr(ubi, pnum); if (err) - return err > 0 ? -EINVAL : err; + return err; } if (ubi_dbg_is_write_failure()) { @@ -348,7 +348,7 @@ retry: err = ubi_dbg_check_all_ff(ubi, pnum, 0, ubi->peb_size); if (err) - return err > 0 ? -EINVAL : err; + return err; if (ubi_dbg_is_erase_failure() && !err) { dbg_err("cannot erase PEB %d (emulated)", pnum); @@ -542,7 +542,7 @@ int ubi_io_sync_erase(struct ubi_device *ubi, int pnum, int torture) err = paranoid_check_not_bad(ubi, pnum); if (err != 0) - return err > 0 ? -EINVAL : err; + return err; if (ubi->ro_mode) { ubi_err("read-only mode"); @@ -819,7 +819,7 @@ int ubi_io_write_ec_hdr(struct ubi_device *ubi, int pnum, err = paranoid_check_ec_hdr(ubi, pnum, ec_hdr); if (err) - return -EINVAL; + return err; err = ubi_io_write(ubi, ec_hdr, pnum, 0, ubi->ec_hdr_alsize); return err; @@ -1083,7 +1083,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, err = paranoid_check_peb_ec_hdr(ubi, pnum); if (err) - return err > 0 ? -EINVAL : err; + return err; vid_hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC); vid_hdr->version = UBI_VERSION; @@ -1092,7 +1092,7 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, err = paranoid_check_vid_hdr(ubi, pnum, vid_hdr); if (err) - return -EINVAL; + return err; p = (char *)vid_hdr - ubi->vid_hdr_shift; err = ubi_io_write(ubi, p, pnum, ubi->vid_hdr_aloffset, @@ -1107,8 +1107,8 @@ int ubi_io_write_vid_hdr(struct ubi_device *ubi, int pnum, * @ubi: UBI device description object * @pnum: physical eraseblock number to check * - * This function returns zero if the physical eraseblock is good, a positive - * number if it is bad and a negative error code if an error occurred. + * This function returns zero if the physical eraseblock is good, %-EINVAL if + * it is bad and a negative error code if an error occurred. */ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) { @@ -1120,7 +1120,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_stack(); - return err; + return err > 0 ? -EINVAL : err; } /** @@ -1130,7 +1130,7 @@ static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum) * @ec_hdr: the erase counter header to check * * This function returns zero if the erase counter header contains valid - * values, and %1 if not. + * values, and %-EINVAL if not. */ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_ec_hdr *ec_hdr) @@ -1156,7 +1156,7 @@ static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum, fail: ubi_dbg_dump_ec_hdr(ec_hdr); ubi_dbg_dump_stack(); - return 1; + return -EINVAL; } /** @@ -1164,8 +1164,8 @@ fail: * @ubi: UBI device description object * @pnum: the physical eraseblock number to check * - * This function returns zero if the erase counter header is all right, %1 if - * not, and a negative error code if an error occurred. + * This function returns zero if the erase counter header is all right and and + * a negative error code if not or if an error occurred. */ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) { @@ -1188,7 +1188,7 @@ static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum) ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_ec_hdr(ec_hdr); ubi_dbg_dump_stack(); - err = 1; + err = -EINVAL; goto exit; } @@ -1206,7 +1206,7 @@ exit: * @vid_hdr: the volume identifier header to check * * This function returns zero if the volume identifier header is all right, and - * %1 if not. + * %-EINVAL if not. */ static int paranoid_check_vid_hdr(const struct ubi_device *ubi, int pnum, const struct ubi_vid_hdr *vid_hdr) @@ -1233,7 +1233,7 @@ fail: ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_stack(); - return 1; + return -EINVAL; } @@ -1243,7 +1243,7 @@ fail: * @pnum: the physical eraseblock number to check * * This function returns zero if the volume identifier header is all right, - * %1 if not, and a negative error code if an error occurred. + * and a negative error code if not or if an error occurred. */ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) { @@ -1270,7 +1270,7 @@ static int paranoid_check_peb_vid_hdr(const struct ubi_device *ubi, int pnum) ubi_err("paranoid check failed for PEB %d", pnum); ubi_dbg_dump_vid_hdr(vid_hdr); ubi_dbg_dump_stack(); - err = 1; + err = -EINVAL; goto exit; } @@ -1289,8 +1289,8 @@ exit: * @len: the length of the region to check * * This function returns zero if only 0xFF bytes are present at offset - * @offset of the physical eraseblock @pnum, %1 if not, and a negative error - * code if an error occurred. + * @offset of the physical eraseblock @pnum, and a negative error code if not + * or if an error occurred. */ int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len) { @@ -1321,7 +1321,7 @@ fail: ubi_msg("hex dump of the %d-%d region", offset, offset + len); print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, ubi->dbg_peb_buf, len, 1); - err = 1; + err = -EINVAL; error: ubi_dbg_dump_stack(); mutex_unlock(&ubi->dbg_buf_mutex); -- cgit v1.2.3-70-g09d2 From 6e9065d756df5dac6dc02b94b82b4f5dbbf38caf Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Mon, 25 Jan 2010 17:09:30 +0200 Subject: UBI: add write checking Add an extra debugging check function which validates writes. After every write it reads the data back, compares it with the original data, and complains if they mismatch. Useful for debugging. No-op if extra debugging checks are disabled. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/debug.h | 4 +++ drivers/mtd/ubi/io.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+) (limited to 'drivers/mtd/ubi/io.c') diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index f30bcb372c0..17a10712972 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h @@ -96,8 +96,11 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); +int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, + int offset, int len); #else #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 +#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 #endif #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT @@ -176,6 +179,7 @@ static inline int ubi_dbg_is_erase_failure(void) #define ubi_dbg_is_write_failure() 0 #define ubi_dbg_is_erase_failure() 0 #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 +#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 #endif /* !CONFIG_MTD_UBI_DEBUG */ #endif /* !__UBI_DEBUG_H__ */ diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index a2501299a67..b4ecc84c754 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -273,6 +273,21 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, } else ubi_assert(written == len); + if (!err) { + err = ubi_dbg_check_write(ubi, buf, pnum, offset, len); + if (err) + return err; + + /* + * Since we always write sequentially, the rest of the PEB has + * to contain only 0xFF bytes. + */ + offset += len; + len = ubi->peb_size - offset; + if (len) + err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); + } + return err; } @@ -1281,6 +1296,61 @@ exit: return err; } +/** + * ubi_dbg_check_write - make sure write succeeded. + * @ubi: UBI device description object + * @buf: buffer with data which were written + * @pnum: physical eraseblock number the data were written to + * @offset: offset within the physical eraseblock the data were written to + * @len: how many bytes were written + * + * This functions reads data which were recently written and compares it with + * the original data buffer - the data have to match. Returns zero if the data + * match and a negative error code if not or in case of failure. + */ +int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, + int offset, int len) +{ + int err, i; + + mutex_lock(&ubi->dbg_buf_mutex); + err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len); + if (err) + goto out_unlock; + + for (i = 0; i < len; i++) { + uint8_t c = ((uint8_t *)buf)[i]; + uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i]; + int dump_len; + + if (c == c1) + continue; + + ubi_err("paranoid check failed for PEB %d:%d, len %d", + pnum, offset, len); + ubi_msg("data differ at position %d", i); + dump_len = max_t(int, 128, len - i); + ubi_msg("hex dump of the original buffer from %d to %d", + i, i + dump_len); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, + buf + i, dump_len, 1); + ubi_msg("hex dump of the read buffer from %d to %d", + i, i + dump_len); + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, + ubi->dbg_peb_buf + i, dump_len, 1); + ubi_dbg_dump_stack(); + err = -EINVAL; + goto out_unlock; + } + mutex_unlock(&ubi->dbg_buf_mutex); + + return 0; + +out_unlock: + mutex_unlock(&ubi->dbg_buf_mutex); + return err; +} + /** * ubi_dbg_check_all_ff - check that a region of flash is empty. * @ubi: UBI device description object -- cgit v1.2.3-70-g09d2