Subsequent patches will extend write verification to additional write
paths that may execute concurrently. A shared per-superblock buffer
would require a coarse lock to serialize all verification, hurting
concurrency.

To avoid this contention, remove the wbuf_verify field from
jffs2_sb_info, along with the scattered kmalloc/kfree of wbuf_verify
in jffs2_nand_flash_setup, jffs2_dataflash_setup,
jffs2_nor_wbuf_flash_setup and their corresponding cleanup functions.

Instead, allocate a temporary buffer inside jffs2_verify_write(),
giving each invocation its own buffer and eliminating the shared state.

Signed-off-by: zhouminqiang <[email protected]>
---
 fs/jffs2/jffs2_fs_sb.h |  3 ---
 fs/jffs2/wbuf.c        | 61 ++++++++++++++++--------------------------
 2 files changed, 23 insertions(+), 41 deletions(-)

diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h
index 5a7091746f68..8a75870d3fc8 100644
--- a/fs/jffs2/jffs2_fs_sb.h
+++ b/fs/jffs2/jffs2_fs_sb.h
@@ -124,9 +124,6 @@ struct jffs2_sb_info {
 
        uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       unsigned char *wbuf_verify; /* read-back buffer for verification */
-#endif
 #ifdef CONFIG_JFFS2_FS_WRITEBUFFER
        unsigned char *wbuf; /* Write-behind buffer for NAND flash */
        uint32_t wbuf_ofs;
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 61e3dbd4cd7b..f10be57c5543 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -233,19 +233,31 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, 
unsigned char *buf,
        int ret;
        size_t retlen;
        char *eccstr;
+       void *verify_buf;
+
+       verify_buf = kmalloc(c->wbuf_pagesize, GFP_NOFS);
+       if (!verify_buf) {
+               pr_warn("%s(): verify buffer allocation failed, skipping 
verification\n",
+                       __func__);
+               return 0;
+       }
+
+       ret = mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, verify_buf);
 
-       ret = mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
        if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
                pr_warn("%s(): Read back of page at %08x failed: %d\n",
                        __func__, c->wbuf_ofs, ret);
-               return 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",
                        __func__, ofs, retlen, c->wbuf_pagesize);
-               return -EIO;
+               ret = -EIO;
+               goto out_free;
+       }
+       if (!memcmp(buf, verify_buf, c->wbuf_pagesize)) {
+               ret = 0;
+               goto out_free;
        }
-       if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize))
-               return 0;
 
        if (ret == -EUCLEAN)
                eccstr = "corrected";
@@ -261,9 +273,14 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, 
unsigned char *buf,
 
        pr_warn("Read back:\n");
        print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
-                      c->wbuf_verify, c->wbuf_pagesize, 0);
+                      verify_buf, c->wbuf_pagesize, 0);
 
+       kfree(verify_buf);
        return -EIO;
+
+out_free:
+       kfree(verify_buf);
+       return ret;
 }
 #else
 #define jffs2_verify_write(c,b,o) (0)
@@ -1217,22 +1234,11 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c)
                return -ENOMEM;
        }
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!c->wbuf_verify) {
-               kfree(c->oobbuf);
-               kfree(c->wbuf);
-               return -ENOMEM;
-       }
-#endif
        return 0;
 }
 
 void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c)
 {
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       kfree(c->wbuf_verify);
-#endif
        kfree(c->wbuf);
        kfree(c->oobbuf);
 }
@@ -1272,14 +1278,6 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
        if (!c->wbuf)
                return -ENOMEM;
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!c->wbuf_verify) {
-               kfree(c->wbuf);
-               return -ENOMEM;
-       }
-#endif
-
        pr_info("write-buffering enabled buffer (%d) erasesize (%d)\n",
                c->wbuf_pagesize, c->sector_size);
 
@@ -1287,9 +1285,6 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) {
 }
 
 void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) {
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       kfree(c->wbuf_verify);
-#endif
        kfree(c->wbuf);
 }
 
@@ -1309,20 +1304,10 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) 
{
        if (!c->wbuf)
                return -ENOMEM;
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL);
-       if (!c->wbuf_verify) {
-               kfree(c->wbuf);
-               return -ENOMEM;
-       }
-#endif
        return 0;
 }
 
 void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c) {
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-       kfree(c->wbuf_verify);
-#endif
        kfree(c->wbuf);
 }
 
-- 
2.52.0


Reply via email to