The Linux Kernel Mailing List
 help / color / mirror / Atom feed
* [PATCH 0/6] jffs2: extend write verification to all write paths
@ 2026-08-20 10:49 zhouminqiang
  2026-08-20 10:49 ` [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer zhouminqiang
                   ` (6 more replies)
  0 siblings, 7 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:49 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

When JFFS2 writes data to flash, it first calculates a node CRC, and
the NAND controller calculates ECC as the data is programmed. If
corruption occurs between these two points, the possible causes are
RAM failures or bus transfer errors before the data reaches the flash,
or bit flips on the flash medium itself. To distinguish whether the
corruption happened during the write transfer or after commit to the
medium, commit a6bc432e296d ("[JFFS2] Add support for write-buffer
verification") introduced CONFIG_JFFS2_FS_WBUF_VERIFY: reading the
data back immediately after a successful write and comparing it with
the in-memory source buffer provides the missing observation point
for that diagnosis.

However, the current implementation only performs read-back verification
on write-buffer flush paths. Two scenarios remain uncovered:

  1. When the write data length exceeds wbuf_pagesize, the excess data
  bypasses the write buffer and is written directly to flash via
  mtd_write() in jffs2_flash_writev(), with no verification.
  2. NOR Flash and other non-writebuffered devices write directly through
  jffs2_flash_direct_write() and jffs2_flash_direct_writev(), with no
  equivalent check.

In both cases, if MTD reports a successful write but the readable medium
differs from JFFS2's source buffer, a later node CRC failure cannot
distinguish transport/program-time corruption from post-commit media
damage, defeating the original diagnostic intent.

This series covers both scenarios with the following changes.

Replace the pre-allocated per-superblock wbuf_verify buffer with
on-demand allocation inside jffs2_verify_write(). This allows
concurrent verification calls to proceed independently without
contending for a shared buffer. Additionally, memcmp() is replaced
with a byte-by-byte comparison that pinpoints the exact mismatch
offset, rather than merely reporting equal or not-equal.

Add verification calls in jffs2_flash_writev() for direct page
writes, and in jffs2_flash_direct_write() and
jffs2_flash_direct_writev() for NOR and other non-writebuffered
devices.

Since verification now covers all write paths rather than only the
write-buffer path, rename CONFIG_JFFS2_FS_WBUF_VERIFY to
CONFIG_JFFS2_FS_WRITE_VERIFY and remove the Kconfig dependency on
CONFIG_JFFS2_FS_WRITEBUFFER.

Add a module parameter write_verify (default off, 0644) to allow
dynamic enable/disable of write verification at runtime, so kernels
can carry the diagnostic facility without read-back overhead until
fault isolation is required. The parameter can be accessed through:

    /sys/module/jffs2/parameters/write_verify

This remains an optional diagnostic aid; node CRCs continue to provide
JFFS2's normal on-media integrity check.

zhouminqiang (6):
  jffs2: replace per-superblock verify buffer with per-write buffer
  jffs2: write verify: replace memcmp with byte-by-byte comparison
  jffs2: add write verification to direct page writes in flash_writev
  jffs2: add write verification to NOR direct write paths
  jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to
    CONFIG_JFFS2_FS_WRITE_VERIFY
  jffs2: add runtime toggle for write verification

 fs/jffs2/Kconfig       |  31 +++++++--
 fs/jffs2/jffs2_fs_sb.h |   3 -
 fs/jffs2/os-linux.h    |  11 ++++
 fs/jffs2/wbuf.c        |  86 +++---------------------
 fs/jffs2/writev.c      | 145 ++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 188 insertions(+), 88 deletions(-)

-- 
2.52.0


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
@ 2026-08-20 10:49 ` zhouminqiang
  2026-08-20 10:49 ` [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison zhouminqiang
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:49 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

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 <zhouminqiang2@huawei.com>
---
 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 3b7803c75d58..7e4608b43a4e 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include <linux/crc32.h>
 #include <linux/mtd/rawnand.h>
@@ -233,19 +234,30 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
 	int ret;
 	size_t retlen;
 	char *eccstr;
+	void *verify_buf;
 
-	ret = mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify);
+	verify_buf = __vmalloc(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);
 	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);
 
+	vfree(verify_buf);
 	return -EIO;
+
+out_free:
+	vfree(verify_buf);
+	return ret;
 }
 #else
 #define jffs2_verify_write(c,b,o) (0)
@@ -1214,22 +1231,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);
 }
@@ -1269,14 +1275,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);
 
@@ -1284,9 +1282,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);
 }
 
@@ -1306,20 +1301,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


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
  2026-08-20 10:49 ` [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer zhouminqiang
@ 2026-08-20 10:49 ` zhouminqiang
  2026-08-20 10:49 ` [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev zhouminqiang
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:49 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

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 <zhouminqiang2@huawei.com>
---
 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


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
  2026-08-20 10:49 ` [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer zhouminqiang
  2026-08-20 10:49 ` [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison zhouminqiang
@ 2026-08-20 10:49 ` zhouminqiang
  2026-08-20 10:50 ` [PATCH 4/6] jffs2: add write verification to NOR direct write paths zhouminqiang
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:49 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

jffs2_flash_writev() performs writes in three phases: phase 1 fills
the write buffer and flushes it when full, phase 2 writes full pages
directly via mtd_write() bypassing the buffer, and phase 3 fills the
remaining data into the write buffer.

Phases 1 and 3 both invoke __jffs2_flush_wbuf() when the buffer is
full, which includes write-back verification when
CONFIG_JFFS2_FS_WBUF_VERIFY is enabled. However phase 2, which
handles the bulk of the write data, calls mtd_write() directly
without any verification.

Phase 2 direct writes may span multiple wbuf_pagesize pages. Extend
jffs2_verify_write() with a len parameter to specify the data length
to verify, and add the verification call after the phase 2
mtd_write() to cover this gap.

Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
 fs/jffs2/wbuf.c | 33 ++++++++++++++++++++-------------
 1 file changed, 20 insertions(+), 13 deletions(-)

diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index da6da813a4ef..3e99587f40e4 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -229,33 +229,33 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
 
 #ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
 static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
-			      uint32_t ofs)
+			      uint32_t ofs, size_t len)
 {
 	int ret = 0;
 	size_t retlen, i;
 	char *eccstr;
 	void *verify_buf;
 
-	verify_buf = __vmalloc(c->wbuf_pagesize, GFP_NOFS);
+	verify_buf = __vmalloc(len, 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, len, &retlen, verify_buf);
 	if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
 		pr_warn("%s(): Read back of page at %08x failed: %d\n",
 			__func__, ofs, ret);
 		goto out_free;
-	} else if (retlen != c->wbuf_pagesize) {
-		pr_warn("%s(): Read back of page at %08x gave short read: %zu not %d\n",
-			__func__, ofs, retlen, c->wbuf_pagesize);
+	} else if (retlen != len) {
+		pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
+			__func__, ofs, retlen, len);
 		ret = -EIO;
 		goto out_free;
 	}
 
-	for (i = 0; i < c->wbuf_pagesize; i++) {
+	for (i = 0; i < len; i++) {
 		uint8_t c1 = ((uint8_t *)buf)[i];
 		uint8_t c2 = ((uint8_t *)verify_buf)[i];
 		int dump_len;
@@ -270,9 +270,9 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
 		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);
+		dump_len = min_t(int, 128, len - i);
+		pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
+			eccstr, ofs, i, len);
 		print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
 			       buf + i, dump_len, 0);
 
@@ -292,7 +292,7 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
 	return ret;
 }
 #else
-#define jffs2_verify_write(c,b,o) (0)
+#define jffs2_verify_write(c,b,o,l) (0)
 #endif
 
 /* Recover from failure to write wbuf. Recover the nodes up to the
@@ -455,7 +455,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c)
 			ret = mtd_write(c->mtd, ofs, towrite, &retlen,
 					rewrite_buf);
 
-		if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs)) {
+		if (ret || retlen != towrite || jffs2_verify_write(c, rewrite_buf, ofs, towrite)) {
 			/* Argh. We tried. Really we did. */
 			pr_crit("Recovery of wbuf failed due to a second write error\n");
 			kfree(buf);
@@ -672,7 +672,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 			retlen, c->wbuf_pagesize);
 		ret = -EIO;
 		goto wfail;
-	} else if ((ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) {
+	}
+
+	ret = jffs2_verify_write(c, c->wbuf, c->wbuf_ofs, c->wbuf_pagesize);
+	if (ret) {
 	wfail:
 		jffs2_wbuf_recover(c);
 
@@ -904,6 +907,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs,
 			if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen))
 				goto outfile;
 
+			ret = jffs2_verify_write(c, v, outvec_to, PAGE_DIV(vlen));
+			if (ret)
+				goto outfile;
+
 			vlen -= wbuf_retlen;
 			outvec_to += wbuf_retlen;
 			c->wbuf_ofs = outvec_to;
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 4/6] jffs2: add write verification to NOR direct write paths
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
                   ` (2 preceding siblings ...)
  2026-08-20 10:49 ` [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev zhouminqiang
@ 2026-08-20 10:50 ` zhouminqiang
  2026-08-20 10:50 ` [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY zhouminqiang
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:50 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

NOR Flash and other non-writebuffered devices write directly through
jffs2_flash_direct_writev() and jffs2_flash_direct_write() without
any write-back verification. If mtd_write() succeeds but the readable
medium differs from JFFS2's source buffer, a later node CRC failure
cannot distinguish transport/program-time corruption from post-commit
media damage.

Move jffs2_verify_write() from wbuf.c to writev.c so it can be
shared by both writebuffered and direct write paths. Add
jffs2_verify_writev() to iterate over kvec entries and verify each
one individually. In both direct write functions, add mtd_write()
return value and retlen checks, and invoke verification after
a successful complete write.

Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
 fs/jffs2/os-linux.h |  11 ++++
 fs/jffs2/wbuf.c     |  69 -------------------------
 fs/jffs2/writev.c   | 122 ++++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 130 insertions(+), 72 deletions(-)

diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 86ab014a349c..e73ef643fd97 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -192,6 +192,17 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
 int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
 			size_t *retlen, const u_char *buf);
 
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+		       uint32_t ofs, size_t len);
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+		       const struct kvec *vecs,
+		       unsigned long count, loff_t to);
+#else
+#define jffs2_verify_write(c, b, o, l) (0)
+#define jffs2_verify_writev(c, v, cnt, t) (0)
+#endif
+
 #endif /* __JFFS2_OS_LINUX_H__ */
 
 
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 3e99587f40e4..493be5765c47 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -15,7 +15,6 @@
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include <linux/crc32.h>
 #include <linux/mtd/rawnand.h>
@@ -227,74 +226,6 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
 	return NULL;
 }
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
-			      uint32_t ofs, size_t len)
-{
-	int ret = 0;
-	size_t retlen, i;
-	char *eccstr;
-	void *verify_buf;
-
-	verify_buf = __vmalloc(len, GFP_NOFS);
-	if (!verify_buf) {
-		pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
-			__func__);
-		return 0;
-	}
-
-	ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
-	if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
-		pr_warn("%s(): Read back of page at %08x failed: %d\n",
-			__func__, ofs, ret);
-		goto out_free;
-	} else if (retlen != len) {
-		pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
-			__func__, ofs, retlen, len);
-		ret = -EIO;
-		goto out_free;
-	}
-
-	for (i = 0; i < len; i++) {
-		uint8_t c1 = ((uint8_t *)buf)[i];
-		uint8_t c2 = ((uint8_t *)verify_buf)[i];
-		int dump_len;
-
-		if (c1 == c2)
-			continue;
-
-		if (ret == -EUCLEAN)
-			eccstr = "corrected";
-		else if (ret == -EBADMSG)
-			eccstr = "correction failed";
-		else
-			eccstr = "OK or unused";
-
-		dump_len = min_t(int, 128, len - i);
-		pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
-			eccstr, ofs, i, len);
-		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 0;
-
-out_free:
-	vfree(verify_buf);
-	return ret;
-}
-#else
-#define jffs2_verify_write(c,b,o,l) (0)
-#endif
-
 /* Recover from failure to write wbuf. Recover the nodes up to the
  * wbuf, not the one which we were starting to try to write. */
 
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index a1bda9dab3f8..39adc15ffd69 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -10,12 +10,100 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+			      uint32_t ofs, size_t len)
+{
+	int ret = 0;
+	size_t retlen, i;
+	char *eccstr;
+	void *verify_buf;
+
+	verify_buf = __vmalloc(len, GFP_NOFS);
+	if (!verify_buf) {
+		pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
+			__func__);
+		return 0;
+	}
+
+	ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
+	if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
+		pr_warn("%s(): Read back of page at %08x failed: %d\n",
+			__func__, ofs, ret);
+		goto out_free;
+	} else if (retlen != len) {
+		pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
+			__func__, ofs, retlen, len);
+		ret = -EIO;
+		goto out_free;
+	}
+
+	for (i = 0; i < len; i++) {
+		uint8_t c1 = ((uint8_t *)buf)[i];
+		uint8_t c2 = ((uint8_t *)verify_buf)[i];
+		int dump_len;
+
+		if (c1 == c2)
+			continue;
+
+		if (ret == -EUCLEAN)
+			eccstr = "corrected";
+		else if (ret == -EBADMSG)
+			eccstr = "correction failed";
+		else
+			eccstr = "OK or unused";
+
+		dump_len = min_t(int, 128, len - i);
+		pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
+			eccstr, ofs, i, len);
+		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 0;
+
+out_free:
+	vfree(verify_buf);
+	return ret;
+}
+
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+			const struct kvec *vecs,
+			unsigned long count, loff_t to)
+{
+	loff_t ofs = to;
+	unsigned long i;
+	int ret;
+
+	for (i = 0; i < count; i++) {
+		if (!vecs[i].iov_len)
+			continue;
+		ret = jffs2_verify_write(c, vecs[i].iov_base, ofs,
+					 vecs[i].iov_len);
+		if (ret)
+			return ret;
+		ofs += vecs[i].iov_len;
+	}
+	return 0;
+}
+#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */
+
 int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
 			      unsigned long count, loff_t to, size_t *retlen)
 {
+	int ret;
 	if (!jffs2_is_writebuffered(c)) {
 		if (jffs2_sum_active()) {
 			int res;
@@ -26,15 +114,31 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
 		}
 	}
 
-	return mtd_writev(c->mtd, vecs, count, to, retlen);
+	ret = mtd_writev(c->mtd, vecs, count, to, retlen);
+
+	if (ret) {
+		pr_warn("%s(): Write failed with %d\n", __func__, ret);
+	} else {
+		size_t totlen = 0;
+		unsigned long i;
+
+		for (i = 0; i < count; i++)
+			totlen += vecs[i].iov_len;
+		if (*retlen != totlen) {
+			pr_warn("%s(): Write was short: %zu instead of %zu\n",
+				__func__, *retlen, totlen);
+			ret = -EIO;
+		} else
+			ret = jffs2_verify_writev(c, vecs, count, to);
+	}
+
+	return ret;
 }
 
 int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
 			size_t *retlen, const u_char *buf)
 {
 	int ret;
-	ret = mtd_write(c->mtd, ofs, len, retlen, buf);
-
 	if (jffs2_sum_active()) {
 		struct kvec vecs[1];
 		int res;
@@ -47,5 +151,17 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
 			return res;
 		}
 	}
+
+	ret = mtd_write(c->mtd, ofs, len, retlen, buf);
+
+	if (ret) {
+		pr_warn("%s(): Write failed with %d\n", __func__, ret);
+	} else if (*retlen != len) {
+		pr_warn("%s(): Write was short: %zu instead of %zu\n",
+			__func__, *retlen, len);
+		ret = -EIO;
+	} else
+		ret = jffs2_verify_write(c, buf, ofs, len);
+
 	return ret;
 }
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
                   ` (3 preceding siblings ...)
  2026-08-20 10:50 ` [PATCH 4/6] jffs2: add write verification to NOR direct write paths zhouminqiang
@ 2026-08-20 10:50 ` zhouminqiang
  2026-08-20 10:50 ` [PATCH 6/6] jffs2: add runtime toggle for write verification zhouminqiang
  2026-08-20 18:58 ` [PATCH 0/6] jffs2: extend write verification to all write paths Richard Weinberger
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:50 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

Write verification now covers all write paths including NOR direct
writes and write-buffer direct page writes, not just the write-buffer
flush path. The Kconfig option also no longer depends on
CONFIG_JFFS2_FS_WRITEBUFFER.

Rename the option from CONFIG_JFFS2_FS_WBUF_VERIFY to
CONFIG_JFFS2_FS_WRITE_VERIFY to reflect its broader scope and
independence from the write-buffer configuration.

Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
 fs/jffs2/Kconfig    | 23 ++++++++++++++++++-----
 fs/jffs2/os-linux.h |  2 +-
 fs/jffs2/writev.c   |  4 ++--
 3 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
index 560187d61562..556025a5d438 100644
--- a/fs/jffs2/Kconfig
+++ b/fs/jffs2/Kconfig
@@ -42,13 +42,26 @@ config JFFS2_FS_WRITEBUFFER
 	    - NOR flash with transparent ECC
 	    - DataFlash
 
-config JFFS2_FS_WBUF_VERIFY
-	bool "Verify JFFS2 write-buffer reads"
-	depends on JFFS2_FS_WRITEBUFFER
+config JFFS2_FS_WRITE_VERIFY
+	bool "Verify JFFS2 writes"
+	depends on JFFS2_FS
 	default n
 	help
-	  This causes JFFS2 to read back every page written through the
-	  write-buffer, and check for errors.
+	  Read back data immediately after flash writes and compare it
+	  with the in-memory image that was written. This covers both
+	  write-buffer flushes and direct writes to non-writebuffered
+	  devices.
+
+	  This may catch corruption introduced after node CRCs are
+	  calculated but before/while data is transferred to the flash
+	  controller (e.g. RAM or DMA), where mtd_write() may succeed
+	  while the medium does not match what JFFS2 intended.
+
+	  Without an immediate read-back, a later node CRC failure cannot
+	  tell transport/program-time corruption from post-commit media
+	  damage.
+
+	  If unsure, say 'N'.
 
 config JFFS2_SUMMARY
 	bool "JFFS2 summary support"
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index e73ef643fd97..65604a6f8148 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -192,7 +192,7 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
 int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
 			size_t *retlen, const u_char *buf);
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+#ifdef CONFIG_JFFS2_FS_WRITE_VERIFY
 int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
 		       uint32_t ofs, size_t len);
 int jffs2_verify_writev(struct jffs2_sb_info *c,
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index 39adc15ffd69..fc1eae60c476 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -14,7 +14,7 @@
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+#ifdef CONFIG_JFFS2_FS_WRITE_VERIFY
 int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
 			      uint32_t ofs, size_t len)
 {
@@ -98,7 +98,7 @@ int jffs2_verify_writev(struct jffs2_sb_info *c,
 	}
 	return 0;
 }
-#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */
+#endif /* CONFIG_JFFS2_FS_WRITE_VERIFY */
 
 int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
 			      unsigned long count, loff_t to, size_t *retlen)
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH 6/6] jffs2: add runtime toggle for write verification
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
                   ` (4 preceding siblings ...)
  2026-08-20 10:50 ` [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY zhouminqiang
@ 2026-08-20 10:50 ` zhouminqiang
  2026-08-20 18:58 ` [PATCH 0/6] jffs2: extend write verification to all write paths Richard Weinberger
  6 siblings, 0 replies; 9+ messages in thread
From: zhouminqiang @ 2026-08-20 10:50 UTC (permalink / raw)
  To: dwmw2, richard; +Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi.zhang

Write verification is a diagnostic facility that adds read-back
overhead to every write. In production, this overhead is undesirable
unless fault isolation is required.

Add a module parameter jffs2.write_verify (bool, 0644) that defaults
to off when CONFIG_JFFS2_FS_WRITE_VERIFY is enabled. The verification
entry checks READ_ONCE(jffs2_write_verify) and returns immediately
when disabled, avoiding any overhead. The parameter can be toggled at
runtime via /sys/module/jffs2/parameters/write_verify or set at
boot/modprobe time.

Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
 fs/jffs2/Kconfig  |  8 ++++++++
 fs/jffs2/writev.c | 23 +++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig
index 556025a5d438..03dadbd003cd 100644
--- a/fs/jffs2/Kconfig
+++ b/fs/jffs2/Kconfig
@@ -61,6 +61,14 @@ config JFFS2_FS_WRITE_VERIFY
 	  tell transport/program-time corruption from post-commit media
 	  damage.
 
+	  Verification defaults to off when this option is selected and can
+	  be enabled at runtime via sysfs:
+
+	    /sys/module/jffs2/parameters/write_verify
+
+	  Write 0 to disable, 1 to enable.  Boot/modprobe parameter
+	  jffs2.write_verify=0|1 is also supported.
+
 	  If unsure, say 'N'.
 
 config JFFS2_SUMMARY
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index fc1eae60c476..b32eb07747f4 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -9,12 +9,32 @@
  *
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/vmalloc.h>
 #include <linux/mtd/mtd.h>
 #include "nodelist.h"
 
 #ifdef CONFIG_JFFS2_FS_WRITE_VERIFY
+/*
+ * Optional read-back after writes.
+ *
+ * Catch cases where data is corrupted after node CRCs are calculated but
+ * before it is correctly programmed -- e.g. in RAM or during DMA/bus
+ * transfer to the flash controller -- so mtd_write() succeeds while the
+ * medium does not match the in-memory image.
+ *
+ * Runtime toggle: /sys/module/jffs2/parameters/write_verify
+ * (also boot/modprobe: jffs2.write_verify=0|1)
+ */
+static bool jffs2_write_verify;
+module_param_named(write_verify, jffs2_write_verify, bool, 0644);
+MODULE_PARM_DESC(write_verify,
+		 "Verify flash writes by reading back (default: N)");
+
+
 int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
 			      uint32_t ofs, size_t len)
 {
@@ -23,6 +43,9 @@ int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
 	char *eccstr;
 	void *verify_buf;
 
+	if (!READ_ONCE(jffs2_write_verify))
+		return 0;
+
 	verify_buf = __vmalloc(len, GFP_NOFS);
 	if (!verify_buf) {
 		pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
-- 
2.52.0


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6] jffs2: extend write verification to all write paths
  2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
                   ` (5 preceding siblings ...)
  2026-08-20 10:50 ` [PATCH 6/6] jffs2: add runtime toggle for write verification zhouminqiang
@ 2026-08-20 18:58 ` Richard Weinberger
  2026-08-20 20:46   ` David Woodhouse
  6 siblings, 1 reply; 9+ messages in thread
From: Richard Weinberger @ 2026-08-20 18:58 UTC (permalink / raw)
  To: zhouminqiang
  Cc: David Woodhouse, linux-mtd, linux-kernel, chengzhihao1, yangerkun,
	yi zhang

----- Ursprüngliche Mail -----
> Von: "zhouminqiang" <zhouminqiang2@huawei.com>
> An: "David Woodhouse" <dwmw2@infradead.org>, "richard" <richard@nod.at>
> CC: "linux-mtd" <linux-mtd@lists.infradead.org>, "linux-kernel" <linux-kernel@vger.kernel.org>, "chengzhihao1"
> <chengzhihao1@huawei.com>, "yangerkun" <yangerkun@huawei.com>, "yi zhang" <yi.zhang@huawei.com>
> Gesendet: Donnerstag, 20. August 2026 12:49:56
> Betreff: [PATCH 0/6] jffs2: extend write verification to all write paths

> When JFFS2 writes data to flash, it first calculates a node CRC, and
> the NAND controller calculates ECC as the data is programmed. If

Why would one use JFFS2 in 2026 on NAND flash?

> corruption occurs between these two points, the possible causes are
> RAM failures or bus transfer errors before the data reaches the flash,
> or bit flips on the flash medium itself. To distinguish whether the
> corruption happened during the write transfer or after commit to the
> medium, commit a6bc432e296d ("[JFFS2] Add support for write-buffer
> verification") introduced CONFIG_JFFS2_FS_WBUF_VERIFY: reading the
> data back immediately after a successful write and comparing it with
> the in-memory source buffer provides the missing observation point
> for that diagnosis.
> 
> However, the current implementation only performs read-back verification
> on write-buffer flush paths. Two scenarios remain uncovered:
> 
>  1. When the write data length exceeds wbuf_pagesize, the excess data
>  bypasses the write buffer and is written directly to flash via
>  mtd_write() in jffs2_flash_writev(), with no verification.
>  2. NOR Flash and other non-writebuffered devices write directly through
>  jffs2_flash_direct_write() and jffs2_flash_direct_writev(), with no
>  equivalent check.
> 
> In both cases, if MTD reports a successful write but the readable medium
> differs from JFFS2's source buffer, a later node CRC failure cannot
> distinguish transport/program-time corruption from post-commit media
> damage, defeating the original diagnostic intent.
> 
> This series covers both scenarios with the following changes.
> 
> Replace the pre-allocated per-superblock wbuf_verify buffer with
> on-demand allocation inside jffs2_verify_write(). This allows
> concurrent verification calls to proceed independently without
> contending for a shared buffer. Additionally, memcmp() is replaced
> with a byte-by-byte comparison that pinpoints the exact mismatch
> offset, rather than merely reporting equal or not-equal.
> 
> Add verification calls in jffs2_flash_writev() for direct page
> writes, and in jffs2_flash_direct_write() and
> jffs2_flash_direct_writev() for NOR and other non-writebuffered
> devices.
> 
> Since verification now covers all write paths rather than only the
> write-buffer path, rename CONFIG_JFFS2_FS_WBUF_VERIFY to
> CONFIG_JFFS2_FS_WRITE_VERIFY and remove the Kconfig dependency on
> CONFIG_JFFS2_FS_WRITEBUFFER.
> 
> Add a module parameter write_verify (default off, 0644) to allow
> dynamic enable/disable of write verification at runtime, so kernels
> can carry the diagnostic facility without read-back overhead until
> fault isolation is required. The parameter can be accessed through:
> 
>    /sys/module/jffs2/parameters/write_verify
> 
> This remains an optional diagnostic aid; node CRCs continue to provide
> JFFS2's normal on-media integrity check.

Please explain why this is needed.
JFFS2 is in "Odd fixes" maintenance mode.
It never worked well for NAND flash, that's why UBIFS (JFFS3) was born.

Thanks,
//richard

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH 0/6] jffs2: extend write verification to all write paths
  2026-08-20 18:58 ` [PATCH 0/6] jffs2: extend write verification to all write paths Richard Weinberger
@ 2026-08-20 20:46   ` David Woodhouse
  0 siblings, 0 replies; 9+ messages in thread
From: David Woodhouse @ 2026-08-20 20:46 UTC (permalink / raw)
  To: Richard Weinberger, zhouminqiang
  Cc: linux-mtd, linux-kernel, chengzhihao1, yangerkun, yi zhang

[-- Attachment #1: Type: text/plain, Size: 490 bytes --]

On Thu, 2026-08-20 at 20:58 +0200, Richard Weinberger wrote:
> 
> Please explain why this is needed.
> JFFS2 is in "Odd fixes" maintenance mode.
> It never worked well for NAND flash, that's why UBIFS (JFFS3) was
> born.

JFFS2 works OK for NAND flash. We got it running with up to 1GiB of
NAND for OLPC.

It doesn't scale well past that, with both memory usage and mount time,
but it's still in active use on NAND in a bunch of embedded platforms
(including OpenWRT routers).

[-- Attachment #2: smime.p7s --]
[-- Type: application/pkcs7-signature, Size: 6179 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2026-08-20 20:47 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
2026-08-20 10:49 ` [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer zhouminqiang
2026-08-20 10:49 ` [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison zhouminqiang
2026-08-20 10:49 ` [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev zhouminqiang
2026-08-20 10:50 ` [PATCH 4/6] jffs2: add write verification to NOR direct write paths zhouminqiang
2026-08-20 10:50 ` [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY zhouminqiang
2026-08-20 10:50 ` [PATCH 6/6] jffs2: add runtime toggle for write verification zhouminqiang
2026-08-20 18:58 ` [PATCH 0/6] jffs2: extend write verification to all write paths Richard Weinberger
2026-08-20 20:46   ` David Woodhouse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox