[PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison
zhouminqiang <[email protected]>
| Newsgroups | gmane.linux.kernel,gmane.linux.drivers.mtd |
|---|---|
| Message-ID | <[email protected]> |
jffs2_verify_write() uses memcmp() to compare the write buffer against data read back from flash. While memcmp() compares byte by byte internally, it only reports equal or not-equal without identifying the mismatch offset. To pinpoint the exact mismatch offset, replace this with the approach used by UBI's self_check_write(): compare byte by byte and, on mismatch, report the first differing offset and dump up to 128 bytes of both the source and read-back data. Signed-off-by: zhouminqiang <[email protected]> --- fs/jffs2/wbuf.c | 53 +++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 7e4608b43a4e..da6da813a4ef 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -231,8 +231,8 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf, uint32_t ofs) { - int ret; - size_t retlen; + int ret = 0; + size_t retlen, i; char *eccstr; void *verify_buf; @@ -246,37 +246,46 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf, ret = mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, verify_buf); if (ret && ret != -EUCLEAN && ret != -EBADMSG) { pr_warn("%s(): Read back of page at %08x failed: %d\n", - __func__, c->wbuf_ofs, ret); + __func__, ofs, ret); goto out_free; } else if (retlen != c->wbuf_pagesize) { - pr_warn("%s(): Read back of page at %08x gave short read: %zd not %d\n", + pr_warn("%s(): Read back of page at %08x gave short read: %zu not %d\n", __func__, ofs, retlen, c->wbuf_pagesize); ret = -EIO; goto out_free; } - if (!memcmp(buf, verify_buf, c->wbuf_pagesize)) { - ret = 0; - goto out_free; - } - if (ret == -EUCLEAN) - eccstr = "corrected"; - else if (ret == -EBADMSG) - eccstr = "correction failed"; - else - eccstr = "OK or unused"; + for (i = 0; i < c->wbuf_pagesize; i++) { + uint8_t c1 = ((uint8_t *)buf)[i]; + uint8_t c2 = ((uint8_t *)verify_buf)[i]; + int dump_len; - pr_warn("Write verify error (ECC %s) at %08x. Wrote:\n", - eccstr, c->wbuf_ofs); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, - c->wbuf, c->wbuf_pagesize, 0); + if (c1 == c2) + continue; - pr_warn("Read back:\n"); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, - verify_buf, c->wbuf_pagesize, 0); + if (ret == -EUCLEAN) + eccstr = "corrected"; + else if (ret == -EBADMSG) + eccstr = "correction failed"; + else + eccstr = "OK or unused"; + + dump_len = min_t(int, 128, c->wbuf_pagesize - i); + pr_warn("Write verify error (ECC %s) at %08x (+%zu/%d). Wrote:\n", + eccstr, ofs, i, c->wbuf_pagesize); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, + buf + i, dump_len, 0); + + pr_warn("Read back:\n"); + print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, + verify_buf + i, dump_len, 0); + + ret = -EIO; + goto out_free; + } vfree(verify_buf); - return -EIO; + return 0; out_free: vfree(verify_buf); -- 2.52.0