From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout09.his.huawei.com (canpmsgout09.his.huawei.com [113.46.200.224]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 879D237D114 for ; Sat, 29 Aug 2026 06:25:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.224 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984743; cv=none; b=UbyWXQXe4fTOzydXiTZOFeKDQqGdPtuAXSL5JBArzO5+K1J+cOfVA06MqL7rwPjIsCH80lwYIMxf2nQWVuqJvM5882MxX/2HvBlkrKHlz1kdff1qeFJmensrYscOl4Ym7lxsa+jNWBjfB0iA+wMbiFSLSheHwNNjbZ574kdCirI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984743; c=relaxed/simple; bh=a4e2Ye41TqPia6GPTouAiPqNZkYjdM1BOHCVEVc9014=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=uqHQiiZtfaJCG7V1OLnxQHvYaPKwqaguXc7S+c81XhySbNbOeTXBlozQbDWeBMQ5jUp9PrxhkhCJxa0Sf6B7cZUkcKKFDeLVqI6RikhcbwOJG5+arLM1e9mj++JGdcofRde5noC2bQChaDKjRRFLuwhwTDra+9KhOcrfh7iuDxI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=sLIQWxtr; arc=none smtp.client-ip=113.46.200.224 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="sLIQWxtr" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=9NpBB7CEIjqjyGCb4SVckgVeutjU9azjoaZgEVa947o=; b=sLIQWxtrS8w5ERuoFDXmbubInkswYa662b4wJY61Zn7xeDFflLoibLq4MWzVHCe0KOiu45zz/ WsF0/wDXGz+6Irxls6bqJzT51YJ9VpzdmO28F/hdacMD9/6HUBU+B/lIjOaXLBS1rXND9jmd36W gmNkFosl91edLNaX6LjQcZk= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout09.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jH4tCWz1cyPY; Sat, 29 Aug 2026 14:14:43 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 7539A40572; Sat, 29 Aug 2026 14:25:30 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:29 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 1/7] jffs2: wbuf: clear wbuf on recovery failure paths Date: Sat, 29 Aug 2026 14:16:51 +0800 Message-ID: <20260829061658.306854-2-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" Write verification was introduced by commit a6bc432e296d ("[JFFS2] Add support for write-buffer verification.") to detect transport or program-time corruption. When verification fails, jffs2_wbuf_recover() attempts to recover the data: it first calls jffs2_block_refile() to mark the old eraseblock's remaining space as REF_OBSOLETE, then rewrites the old block's data along with the new data still in the wbuf to a new block. However, when the recovery write verification also fails, the function returns without clearing c->wbuf_len, leaving the wbuf still pointing to the refiled old block, which leads to two kinds of bugs. Both cases below are illustrated with a filesystem of erasesize=3D16KB and wbuf_pagesize=3D512B. Case 1: BUG_ON in jffs2_link_node_ref(): User: Two 1KB writes ref0: [A+0, A+1092) (ri:68B + data:1024B) ref1: [A+1092, A+2184) User: append 1KB write ... jffs2_write_dnode jffs2_flash_writev c->wbuf_ofs =3D A+2048, c->wbuf_len =3D 512 __jffs2_flush_wbuf mtd_write -> 0-to-1 bit flip jffs2_verify_write -> verify failed jffs2_wbuf_recover jffs2_block_refile c->nextblock =3D NULL jffs2_link_node_ref -> mark A remaining ref2: [A+2184, A+16384) space REF_OBSOLETE, jeb_A->free_size =3D 0 jffs2_reserve_space_gc jffs2_do_reserve_space jffs2_find_nextblock c->nextblock =3D B start =3D A+1092, end =3D A+2184 end - start >=3D c->wbuf_pagesize -> recover data in A mtd_write jffs2_verify_write -> verify also failed return -> c->wbuf_ofs =3D A+2048 c->wbuf_len =3D 512 retry jffs2_flash_writev if (SECTOR_ADDR(to) !=3D SECTOR_ADDR(c->wbuf_ofs)) -> SECTOR(to) =3D B -> SECTOR(c->wbuf_ofs) =3D A __jffs2_flush_wbuf(c, PAD_NOACCOUNT) -> flush residual wbuf data wbuf_jeb =3D A -> c->wbuf_ofs still points to refiled old block mtd_write -> succeeds via NAND AND jffs2_verify_write -> passed if (pad) jffs2_link_node_ref ref_offset(ref) =3D c->wbuf_ofs + c->wbuf_len =3D A+2560 jeb_A->offset =3D A c->sector_size =3D 16384 jeb_A->free_size =3D 0 ref_offset(ref) !=3D jeb_A->offset + c->sector_size - jeb_A->free_size -> BUG Case 2: deadlock in jffs2_flush_wbuf_pad(): User: 1KB write A_ref0: [A+0, A+1092) (ri:68B + data:1024B) User: append 1K write ... jffs2_write_dnode jffs2_flash_writev c->wbuf_ofs =3D A+1024, c->wbuf_len =3D 512 __jffs2_flush_wbuf mtd_write -> bit flip jffs2_verify_write -> verify failed jffs2_wbuf_recover jffs2_block_refile c->nextblock =3D NULL jffs2_link_node_ref -> mark A remaining A_ref1: [A+1092, A+16384) space as REF_OBSOLETE jffs2_reserve_space_gc jffs2_do_reserve_space jffs2_find_nextblock c->nextblock =3D B start =3D A, end =3D A+1092 end - start >=3D c->wbuf_pagesize -> recover data in A mtd_write jffs2_verify_write -> verify also failed jffs2_add_physical_node_ref -> mark written area in B_ref0: [B+0, B+1536) B as REF_OBSOLETE return -> c->wbuf_ofs =3D A+1024 c->wbuf_len =3D 512 retry jffs2_flash_writev down_write(&c->wbuf_sem) if (SECTOR_ADDR(to) !=3D SECTOR_ADDR(c->wbuf_ofs)) -> SECTOR(to) =3D B -> SECTOR(c->wbuf_ofs) =3D A __jffs2_flush_wbuf(c, PAD_NOACCOUNT) -> flush residual wbuf data wbuf_jeb =3D A -> c->wbuf_ofs still points to refiled old block mtd_write -> bit flip jffs2_verify_write -> verify failed jffs2_wbuf_recover jffs2_block_refile c->nextblock !=3D jeb -> jeb =3D A, nextblock = =3D B jffs2_link_node_ref -> append zero-length ref A_ref2: [A+16384, A+16384) marked REF_OBSOLETE after the existing one end =3D jeb_A->last_node -> inflates to eraseblock tail start =3D A, end =3D A+16384 jffs2_reserve_space_gc minsize =3D end - start =3D 16384 jffs2_do_reserve_space jeb =3D c->nextblock -> points to B jeb_B->free_size =3D 16384 - 1536 minsize > jeb_B->free_size -> first recovery's OBSOLETE ref reduced free_size jffs2_wbuf_dirty(c) jffs2_flush_wbuf_pad(c) down_write(&c->wbuf_sem) -> already held, deadlock Fix this by setting c->wbuf_len =3D 0 when jffs2_verify_write fails in recovery path, and also in the jffs2_reserve_space_gc() and jffs2_prealloc_raw_node_refs() failure paths, ensuring subsequent flushes will not attempt writes on refiled blocks. Signed-off-by: zhouminqiang --- fs/jffs2/wbuf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 3b7803c75d58..61e3dbd4cd7b 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -390,6 +390,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) if (ret) { pr_warn("Failed to allocate space for wbuf recovery. Data loss ensues.\n= "); kfree(buf); + c->wbuf_len =3D 0; return; } =20 @@ -400,6 +401,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) if (ret) { pr_warn("Failed to allocate node refs for wbuf recovery. Data loss ensue= s.\n"); kfree(buf); + c->wbuf_len =3D 0; return; } =20 @@ -431,12 +433,13 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *= c) =20 if (ret || retlen !=3D towrite || jffs2_verify_write(c, rewrite_buf, ofs= )) { /* Argh. We tried. Really we did. */ - pr_crit("Recovery of wbuf failed due to a second write error\n"); + pr_crit("Recovery of wbuf failed due to a second write error. Data loss= ensues.\n"); kfree(buf); =20 if (retlen) jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, = first_raw), NULL); =20 + c->wbuf_len =3D 0; return; } pr_notice("Recovery of wbuf succeeded to %08x\n", ofs); --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F039037E2E2 for ; Sat, 29 Aug 2026 06:25:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984742; cv=none; b=PPCP0k4ajsvsSx8J0+yOyt72lOaCOtnWQsMGTAWzWDqDwUAdyaOR2JkB58MQHQc7O2ESVoWOLwil5E3umN/eYHCpq5c21vBRqytCbv8MyIjGl3NqaoIkwYijotkMnF0nfkI1aNmyfWJl4UpLmTdRpfh/rBeng7chQG9TLy/ciT4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984742; c=relaxed/simple; bh=88LuP5yZdyTSEeWGmG4VxI3o9iCJKLKOvpqSAVnMtP4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=fd8ULBE8E87WTBxW0OLDOEnQbwImFAy8G3zRZtKnhNL8uZDKc/Y/Zl7LUPFM96onXpOuYqGw8AUPsCy0/BBiy7yxTAS5vbZ/pSCsvKaWA91V6JePM5Fnvgn9RVLwUdmT4TcERf0CdQV5btVtE2BxnQkDJho7Eh1LvzpptFQssfM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=kGw3GOQA; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="kGw3GOQA" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=S1yrFP4Pe6B/KX4VlbIF1fox942sBDwMlaUs6T4ODEg=; b=kGw3GOQA7j/ll6HjJ7opjr9yugQSx0srBbftBV0nHJqV0lNwEOmiK55GOyWVY9oQbti8dmf7Y fC4xbX4RXHos2KXMZCje/FHwjDuB0cBw1kirsBique2cBcbiJQ2mXWYVhME5LToy5ot11FKhUtz sEGnHGsHsyS5KN6nFTFNgsI= Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jv5tR9z12LDl; Sat, 29 Aug 2026 14:15:15 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 4728820333; Sat, 29 Aug 2026 14:25:31 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:30 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 2/7] jffs2: replace per-superblock verify buffer with per-write buffer Date: Sat, 29 Aug 2026 14:16:52 +0800 Message-ID: <20260829061658.306854-3-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" 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 --- 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 { =20 uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ =20 -#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 =3D kmalloc(c->wbuf_pagesize, GFP_NOFS); + if (!verify_buf) { + pr_warn("%s(): verify buffer allocation failed, skipping verification\n", + __func__); + return 0; + } + + ret =3D mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, verify_buf); =20 - ret =3D mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify); if (ret && ret !=3D -EUCLEAN && ret !=3D -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 !=3D 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 =3D -EIO; + goto out_free; + } + if (!memcmp(buf, verify_buf, c->wbuf_pagesize)) { + ret =3D 0; + goto out_free; } - if (!memcmp(buf, c->wbuf_verify, c->wbuf_pagesize)) - return 0; =20 if (ret =3D=3D -EUCLEAN) eccstr =3D "corrected"; @@ -261,9 +273,14 @@ static int jffs2_verify_write(struct jffs2_sb_info *c,= unsigned char *buf, =20 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); =20 + 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; } =20 -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - c->wbuf_verify =3D kmalloc(c->wbuf_pagesize, GFP_KERNEL); - if (!c->wbuf_verify) { - kfree(c->oobbuf); - kfree(c->wbuf); - return -ENOMEM; - } -#endif return 0; } =20 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; =20 -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - c->wbuf_verify =3D 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); =20 @@ -1287,9 +1285,6 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { } =20 void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) { -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - kfree(c->wbuf_verify); -#endif kfree(c->wbuf); } =20 @@ -1309,20 +1304,10 @@ int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info= *c) { if (!c->wbuf) return -ENOMEM; =20 -#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY - c->wbuf_verify =3D kmalloc(c->wbuf_pagesize, GFP_KERNEL); - if (!c->wbuf_verify) { - kfree(c->wbuf); - return -ENOMEM; - } -#endif return 0; } =20 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); } =20 --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout08.his.huawei.com (canpmsgout08.his.huawei.com [113.46.200.223]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6839B37F006 for ; Sat, 29 Aug 2026 06:25:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.223 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984742; cv=none; b=XEuigNOK9hmyOheYLVjGhI9EYauEIKzJ3AkFQRXfx1mMPaRKzlJyg4z7r+XNH1nXvB57oYRTnZ7DwnfQtc4ZIzY9FWKBd9tBcJozR66hpS6ovLCi0g20mvVtxEWbam+q/8MxqmFUKDZF0r3/PN/kYG2xUIrvCY0Zr/d3puCrPeY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984742; c=relaxed/simple; bh=JMM884fTlclbOvRfwT1M1d4pL+sGWqXu40JwAGomtUI=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=k5u1biydRYuut+l8CfOvGjlA+gRgFbVKl8Nxw6C7CpMuYjXOd+6DtGyUTE3E7r75jWiuPHub/9gh8pkMq3Je+tKQB9bEwym/Em1acqYjYyZi14pzAvRVpsFKU7mSwjKJ7Rk7bMd6FC3sux4UCYF7uPBOJYrlClQGYpTJV01o3GY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=C7JNq/9n; arc=none smtp.client-ip=113.46.200.223 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="C7JNq/9n" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=ktiYUYsUp5uCXnvJH/BfqE9fq8l5SXsVdqzLvfHOlV4=; b=C7JNq/9nW8O1L4+qB8K+5l2GGzD9N3sj5EVi4EnDL5oF6x+3kjr/TdY9xkttUhd/epZ+ev4bJ 5hgEztLJqonv6F5ys20YZ0BjHoNMDdhG8jwXb6tQTPxKCRn3gSjQig20fZertp3RZEGPOPARqMX 1uaVaJBSLupvQPWZ6L7moek= Received: from mail.maildlp.com (unknown [172.19.163.15]) by canpmsgout08.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jJ3V8WzmVXs; Sat, 29 Aug 2026 14:14:44 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 17D3B40578; Sat, 29 Aug 2026 14:25:32 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:31 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 3/7] jffs2: write verify: add byte-by-byte comparison on mismatch Date: Sat, 29 Aug 2026 14:16:53 +0800 Message-ID: <20260829061658.306854-4-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" jffs2_verify_write() uses memcmp() to compare the write buffer against data read back from flash. On mismatch, the current code dumps the entire source and read-back data, which will become impractical once the verify path is extended to NOR flash where a single write can span PAGE_SIZE. Add a byte-by-byte comparison after the memcmp() mismatch path to locate the exact mismatch offset, reporting the first differing offset and dumping up to 128 bytes of both the source and read-back data. memcmp() remains on the hotpath for successful writes, and the byte-by-byte loop only runs when an error is actually detected. Signed-off-by: zhouminqiang --- fs/jffs2/wbuf.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index f10be57c5543..74e169dedab7 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -231,7 +231,7 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, = unsigned char *buf, uint32_t ofs) { int ret; - size_t retlen; + size_t retlen, i; char *eccstr; void *verify_buf; =20 @@ -246,10 +246,10 @@ static int jffs2_verify_write(struct jffs2_sb_info *c= , unsigned char *buf, =20 if (ret && ret !=3D -EUCLEAN && ret !=3D -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 !=3D 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 =3D -EIO; goto out_free; @@ -259,24 +259,34 @@ static int jffs2_verify_write(struct jffs2_sb_info *c= , unsigned char *buf, goto out_free; } =20 - if (ret =3D=3D -EUCLEAN) - eccstr =3D "corrected"; - else if (ret =3D=3D -EBADMSG) - eccstr =3D "correction failed"; - else - eccstr =3D "OK or unused"; + for (i =3D 0; i < c->wbuf_pagesize; i++) { + uint8_t c1 =3D ((uint8_t *)buf)[i]; + uint8_t c2 =3D ((uint8_t *)verify_buf)[i]; + int dump_len; =20 - 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 =3D=3D c2) + continue; =20 - pr_warn("Read back:\n"); - print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1, - verify_buf, c->wbuf_pagesize, 0); + if (ret =3D=3D -EUCLEAN) + eccstr =3D "corrected"; + else if (ret =3D=3D -EBADMSG) + eccstr =3D "correction failed"; + else + eccstr =3D "OK or unused"; =20 - kfree(verify_buf); - return -EIO; + dump_len =3D 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 =3D -EIO; + goto out_free; + } =20 out_free: kfree(verify_buf); --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout04.his.huawei.com (canpmsgout04.his.huawei.com [113.46.200.219]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA7A21E9919 for ; Sat, 29 Aug 2026 06:25:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.219 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984739; cv=none; b=lFTF3Yq6/3hkJdHOLvz1AdK5nRG9y04XJXABAwAFZL6HAcfCkZ5DaWnRjNrhVqWd/FcMhtNeeupl5RYvkDdG1Cq0rcpR3f5jfS9CdkKcAqoOXtayNFa4gbLMc878jnCBjn3CwnT9EJOXBd70MCuEUUeKGh7Z+ouCSr25AyGjYn8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984739; c=relaxed/simple; bh=Juv8A9FdhXIuadcmVr4eZUZxt9Ri9jlClRN980DboPA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DeM6YvO57JsY2jgJ8skswwU0vHlQViGAXGHPaCQtqJo6WzYigY/UkLb/Yf9Bmq3CQOhf2WbJpCb3jyoDYXsm/YlKL1vr/3HOju4EJI90bosFC8zkhTy43+nd83y8Bb84BcCJeumuM1CnuPhbd4B/oe1XY/Vwi6Y7MA/8WmYJFcE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=REYZhobG; arc=none smtp.client-ip=113.46.200.219 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="REYZhobG" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=74q66HJmMWJN55dn20FZdYOLy1Mwgl/UEzgpiDTNZVM=; b=REYZhobGY6OwtWYxQq2Chhx1HTa/A7qWytRXir4V3heVxGFQNYBNrnYKaQyMWXAkc3i/q+VLZ jEJjJp9Kd7DUqaion7AFqCFvv6soKHNWbfjJbgB2PTyIbVgV+Fi/gdKQqKc8bnFr18jWJP6Wis1 vpWsCTK0V6+bkzxtwYXZoQ4= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout04.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jH4NvBz1prKd; Sat, 29 Aug 2026 14:14:43 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id DC99A40537; Sat, 29 Aug 2026 14:25:32 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:32 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 4/7] jffs2: add write verification to direct page writes in flash_writev Date: Sat, 29 Aug 2026 14:16:54 +0800 Message-ID: <20260829061658.306854-5-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" 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 --- fs/jffs2/wbuf.c | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 74e169dedab7..81f3538ca258 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -228,38 +228,38 @@ static struct jffs2_raw_node_ref **jffs2_incore_repla= ce_raw(struct jffs2_sb_info =20 #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; size_t retlen, i; char *eccstr; void *verify_buf; =20 - verify_buf =3D kmalloc(c->wbuf_pagesize, GFP_NOFS); + verify_buf =3D kmalloc(len, GFP_NOFS); if (!verify_buf) { pr_warn("%s(): verify buffer allocation failed, skipping verification\n", __func__); return 0; } =20 - ret =3D mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, verify_buf); + ret =3D mtd_read(c->mtd, ofs, len, &retlen, verify_buf); =20 if (ret && ret !=3D -EUCLEAN && ret !=3D -EBADMSG) { pr_warn("%s(): Read back of page at %08x failed: %d\n", __func__, ofs, ret); goto out_free; - } else if (retlen !=3D 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 !=3D len) { + pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n", + __func__, ofs, retlen, len); ret =3D -EIO; goto out_free; } - if (!memcmp(buf, verify_buf, c->wbuf_pagesize)) { + if (!memcmp(buf, verify_buf, len)) { ret =3D 0; goto out_free; } =20 - for (i =3D 0; i < c->wbuf_pagesize; i++) { + for (i =3D 0; i < len; i++) { uint8_t c1 =3D ((uint8_t *)buf)[i]; uint8_t c2 =3D ((uint8_t *)verify_buf)[i]; int dump_len; @@ -274,9 +274,9 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, = unsigned char *buf, else eccstr =3D "OK or unused"; =20 - dump_len =3D 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 =3D 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); =20 @@ -293,7 +293,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 =20 /* Recover from failure to write wbuf. Recover the nodes up to the @@ -458,7 +458,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ret =3D mtd_write(c->mtd, ofs, towrite, &retlen, rewrite_buf); =20 - if (ret || retlen !=3D towrite || jffs2_verify_write(c, rewrite_buf, ofs= )) { + if (ret || retlen !=3D 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. Data loss= ensues.\n"); kfree(buf); @@ -676,7 +676,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c,= int pad) retlen, c->wbuf_pagesize); ret =3D -EIO; goto wfail; - } else if ((ret =3D jffs2_verify_write(c, c->wbuf, c->wbuf_ofs))) { + } + + ret =3D jffs2_verify_write(c, c->wbuf, c->wbuf_ofs, c->wbuf_pagesize); + if (ret) { wfail: jffs2_wbuf_recover(c); =20 @@ -908,6 +911,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const = struct kvec *invecs, if (ret < 0 || wbuf_retlen !=3D PAGE_DIV(vlen)) goto outfile; =20 + ret =3D jffs2_verify_write(c, v, outvec_to, PAGE_DIV(vlen)); + if (ret) + goto outfile; + vlen -=3D wbuf_retlen; outvec_to +=3D wbuf_retlen; c->wbuf_ofs =3D outvec_to; --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout10.his.huawei.com (canpmsgout10.his.huawei.com [113.46.200.225]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D4B8D33D503 for ; Sat, 29 Aug 2026 06:25:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.225 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; cv=none; b=QyboIrw+2q4g2cJT+UMeZaPpbosKeyDR5YHBvHA662Z1ou16DaonD0Or9KmJdUeYf6DX+3hbEZstw/qv6T7fxC0zkfe6qTJPU2ZN5xQb7esx1L8YvXrPmZthXT8T1fZ9vMF1/vWvh3u8mV8DIke/x4mmkFg44hxN2Pscs0+bhzE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; c=relaxed/simple; bh=I8Mkf4P1ZRlT1OD2x0FWmt5Ym4BkhW/QXHrxcGJFh2k=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DqklPseh9Zb4L5PQ4ayydqasG6L236k79nMWK0P9Egvse5sTftH9TDA8rL7uRz+DpC68240HIDwKbdYHefv2VSGLtSsWihuddOPK/giPNsvGsU0kELBkFvkWleaZSIhVGQtIIz2s0C24lMpW1cIeJaI8b3Jbs47ethHFlgS9o2s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=dYeGUVwc; arc=none smtp.client-ip=113.46.200.225 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="dYeGUVwc" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=Pn2SmxuVjFwFpqXGdu8OZwKamj1BHEHNT/tHVR/vSTw=; b=dYeGUVwcG1LDa8xv9mPu47y6etjh2IMRAV9Drf7EGVvZKHnrOiJzZOm2ruTqAFBUstbuwQrh2 Jez+frkwp1AVHS4qRmwFzYQlODzEuoODMXTOqsDQe1Js8QxpnK1mfV+L15PYfsSTrmKmx+pS+8K Nk8NutdrLYEa65TYILoJIIo= Received: from mail.maildlp.com (unknown [172.19.163.200]) by canpmsgout10.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jL0gjdz1K9D2; Sat, 29 Aug 2026 14:14:46 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id A9F524055B; Sat, 29 Aug 2026 14:25:33 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:32 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 5/7] jffs2: add write verification to NOR direct write paths Date: Sat, 29 Aug 2026 14:16:55 +0800 Message-ID: <20260829061658.306854-6-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" 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. In jffs2_flash_direct_writev(), move the mtd_writev() call before jffs2_sum_add_kvec() so that *retlen is always set by the MTD layer first. The original ordering let jffs2_sum_add_kvec() return early on error without ever touching *retlen, leaving the caller's retlen check to read an uninitialized value. Keep the same order in jffs2_flash_direct_write(). Signed-off-by: zhouminqiang --- fs/jffs2/os-linux.h | 11 ++++ fs/jffs2/wbuf.c | 70 ------------------------- fs/jffs2/writev.c | 121 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 131 insertions(+), 71 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 l= en, size_t *retlen, const u_char *buf); =20 +#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__ */ =20 =20 diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 81f3538ca258..2f4937951a0c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -226,76 +226,6 @@ static struct jffs2_raw_node_ref **jffs2_incore_replac= e_raw(struct jffs2_sb_info return NULL; } =20 -#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; - size_t retlen, i; - char *eccstr; - void *verify_buf; - - verify_buf =3D kmalloc(len, GFP_NOFS); - if (!verify_buf) { - pr_warn("%s(): verify buffer allocation failed, skipping verification\n", - __func__); - return 0; - } - - ret =3D mtd_read(c->mtd, ofs, len, &retlen, verify_buf); - - if (ret && ret !=3D -EUCLEAN && ret !=3D -EBADMSG) { - pr_warn("%s(): Read back of page at %08x failed: %d\n", - __func__, ofs, ret); - goto out_free; - } else if (retlen !=3D len) { - pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n", - __func__, ofs, retlen, len); - ret =3D -EIO; - goto out_free; - } - if (!memcmp(buf, verify_buf, len)) { - ret =3D 0; - goto out_free; - } - - for (i =3D 0; i < len; i++) { - uint8_t c1 =3D ((uint8_t *)buf)[i]; - uint8_t c2 =3D ((uint8_t *)verify_buf)[i]; - int dump_len; - - if (c1 =3D=3D c2) - continue; - - if (ret =3D=3D -EUCLEAN) - eccstr =3D "corrected"; - else if (ret =3D=3D -EBADMSG) - eccstr =3D "correction failed"; - else - eccstr =3D "OK or unused"; - - dump_len =3D 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 =3D -EIO; - goto out_free; - } - -out_free: - kfree(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. */ =20 diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index a1bda9dab3f8..2cb8cb030ae3 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -10,12 +10,121 @@ */ =20 #include +#include #include #include "nodelist.h" =20 +#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; + size_t retlen, i; + char *eccstr; + void *verify_buf; + + verify_buf =3D kmalloc(len, GFP_NOFS); + if (!verify_buf) { + pr_warn("%s(): verify buffer allocation failed, skipping verification\n", + __func__); + return 0; + } + + ret =3D mtd_read(c->mtd, ofs, len, &retlen, verify_buf); + + if (ret && ret !=3D -EUCLEAN && ret !=3D -EBADMSG) { + pr_warn("%s(): Read back of page at %08x failed: %d\n", + __func__, ofs, ret); + goto out_free; + } else if (retlen !=3D len) { + pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n", + __func__, ofs, retlen, len); + ret =3D -EIO; + goto out_free; + } + if (!memcmp(buf, verify_buf, len)) { + ret =3D 0; + goto out_free; + } + + for (i =3D 0; i < len; i++) { + uint8_t c1 =3D ((uint8_t *)buf)[i]; + uint8_t c2 =3D ((uint8_t *)verify_buf)[i]; + int dump_len; + + if (c1 =3D=3D c2) + continue; + + if (ret =3D=3D -EUCLEAN) + eccstr =3D "corrected"; + else if (ret =3D=3D -EBADMSG) + eccstr =3D "correction failed"; + else + eccstr =3D "OK or unused"; + + dump_len =3D 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 =3D -EIO; + goto out_free; + } + +out_free: + kfree(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 =3D to; + unsigned long i; + int ret; + + for (i =3D 0; i < count; i++) { + if (!vecs[i].iov_len) + continue; + ret =3D jffs2_verify_write(c, vecs[i].iov_base, ofs, + vecs[i].iov_len); + if (ret) + return ret; + ofs +=3D 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; + + ret =3D mtd_writev(c->mtd, vecs, count, to, retlen); + + if (ret) { + pr_warn("%s(): Write failed with %d\n", __func__, ret); + } else { + size_t totlen =3D 0; + unsigned long i; + + for (i =3D 0; i < count; i++) + totlen +=3D vecs[i].iov_len; + if (*retlen !=3D totlen) { + pr_warn("%s(): Write was short: %zu instead of %zu\n", + __func__, *retlen, totlen); + ret =3D -EIO; + } else + ret =3D jffs2_verify_writev(c, vecs, count, to); + } + if (!jffs2_is_writebuffered(c)) { if (jffs2_sum_active()) { int res; @@ -26,15 +135,25 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c,= const struct kvec *vecs, } } =20 - return mtd_writev(c->mtd, vecs, count, to, retlen); + return ret; } =20 int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t l= en, size_t *retlen, const u_char *buf) { int ret; + ret =3D mtd_write(c->mtd, ofs, len, retlen, buf); =20 + if (ret) { + pr_warn("%s(): Write failed with %d\n", __func__, ret); + } else if (*retlen !=3D len) { + pr_warn("%s(): Write was short: %zu instead of %zu\n", + __func__, *retlen, len); + ret =3D -EIO; + } else + ret =3D jffs2_verify_write(c, buf, ofs, len); + if (jffs2_sum_active()) { struct kvec vecs[1]; int res; --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout02.his.huawei.com (canpmsgout02.his.huawei.com [113.46.200.217]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B7A4737FF6A for ; Sat, 29 Aug 2026 06:25:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.217 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; cv=none; b=TrOKsEM1eSlouhuuSj5YjLKYkcLadrIlYUPyNTmPRqoE8Z4UyRTkOhW4JSWihqPZEFmo8ezxED2JzE0AOMRhP0pRNBfmvvjt8VowUOYd6zB9jH4lgSa6BldkOWLU89zQPAaiOCXLtdonKmhszY8G1PB9XemaXLIjFLFZHc2MoXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; c=relaxed/simple; bh=4mkDA3DTJy+F1HmdRVu0rZavlRs/aR2tHpPpt6EMdLk=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=DpDmxwhPePxEZeZQzzDyFeggk9spdjVrXUMv6k4TtT0a27glt+209CYMta7CeOqWoJ2GJa+H2N73UDoq08kWgwMMHHz46A+8ih7zAHVu0mBVb+2BwcRe2QELjQkwf8cuVU4qkSvwqoMrpo0BbKLIlC+kqmTy8LnEPL2+8N9YJbg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=UG3cQnou; arc=none smtp.client-ip=113.46.200.217 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="UG3cQnou" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=osxjT7f1JxWv5xezKwzK5ISq924sZF9A35E3+reEz8Q=; b=UG3cQnouTZYLXE7dXFFi1mNX00e5Uge+R1PKM3c75ZlP+Xd5IOgoqoCncgffXfrxTCDXcHuHu 4bZYSRLh0UczZAljLHJ/3CHV8Gqu+8BDLdGai45CHGaqPYlbQsLlu+sHMSUyVrrNGgvEO/cWLVi r2nyRxkna3kj6EcHJzVU+RM= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jX2rPyzcb3P; Sat, 29 Aug 2026 14:14:56 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 7CF5A4058C; Sat, 29 Aug 2026 14:25:34 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:33 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 6/7] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY Date: Sat, 29 Aug 2026 14:16:56 +0800 Message-ID: <20260829061658.306854-7-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" 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. Update defconfig files that explicitly enabled the old symbol to use the new name, so that platforms which previously relied on this verification continue to have it enabled. Signed-off-by: zhouminqiang --- arch/arm/configs/keystone_defconfig | 2 +- arch/arm/configs/lpc32xx_defconfig | 2 +- arch/arm/configs/pxa3xx_defconfig | 2 +- arch/arm/configs/pxa_defconfig | 2 +- arch/powerpc/configs/44x/fsp2_defconfig | 2 +- fs/jffs2/Kconfig | 23 ++++++++++++++++++----- fs/jffs2/os-linux.h | 2 +- fs/jffs2/writev.c | 4 ++-- 8 files changed, 26 insertions(+), 13 deletions(-) diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keyston= e_defconfig index b0cadd878152..d485b8b0b91d 100644 --- a/arch/arm/configs/keystone_defconfig +++ b/arch/arm/configs/keystone_defconfig @@ -212,7 +212,7 @@ CONFIG_VFAT_FS=3Dy CONFIG_NTFS_FS=3Dy CONFIG_TMPFS=3Dy CONFIG_JFFS2_FS=3Dy -CONFIG_JFFS2_FS_WBUF_VERIFY=3Dy +CONFIG_JFFS2_FS_WRITE_VERIFY=3Dy CONFIG_UBIFS_FS=3Dy CONFIG_CRAMFS=3Dy CONFIG_NFS_FS=3Dy diff --git a/arch/arm/configs/lpc32xx_defconfig b/arch/arm/configs/lpc32xx_= defconfig index b9e2e603cd95..dd0c6db641be 100644 --- a/arch/arm/configs/lpc32xx_defconfig +++ b/arch/arm/configs/lpc32xx_defconfig @@ -164,7 +164,7 @@ CONFIG_MSDOS_FS=3Dy CONFIG_VFAT_FS=3Dy CONFIG_TMPFS=3Dy CONFIG_JFFS2_FS=3Dy -CONFIG_JFFS2_FS_WBUF_VERIFY=3Dy +CONFIG_JFFS2_FS_WRITE_VERIFY=3Dy CONFIG_UBIFS_FS=3Dy CONFIG_CRAMFS=3Dy CONFIG_NFS_FS=3Dy diff --git a/arch/arm/configs/pxa3xx_defconfig b/arch/arm/configs/pxa3xx_de= fconfig index fb272e3a2337..f2121269f7c8 100644 --- a/arch/arm/configs/pxa3xx_defconfig +++ b/arch/arm/configs/pxa3xx_defconfig @@ -84,7 +84,7 @@ CONFIG_LEDS_TRIGGER_BACKLIGHT=3Dm CONFIG_LEDS_TRIGGER_GPIO=3Dm CONFIG_LEDS_TRIGGER_DEFAULT_ON=3Dm CONFIG_JFFS2_FS=3Dy -CONFIG_JFFS2_FS_WBUF_VERIFY=3Dy +CONFIG_JFFS2_FS_WRITE_VERIFY=3Dy CONFIG_JFFS2_COMPRESSION_OPTIONS=3Dy CONFIG_JFFS2_LZO=3Dy CONFIG_JFFS2_RUBIN=3Dy diff --git a/arch/arm/configs/pxa_defconfig b/arch/arm/configs/pxa_defconfig index 66cc149c5ca4..e05cbebb0d8b 100644 --- a/arch/arm/configs/pxa_defconfig +++ b/arch/arm/configs/pxa_defconfig @@ -596,7 +596,7 @@ CONFIG_TMPFS_POSIX_ACL=3Dy CONFIG_CONFIGFS_FS=3Dy CONFIG_JFFS2_FS=3Dm CONFIG_JFFS2_FS_DEBUG=3D1 -CONFIG_JFFS2_FS_WBUF_VERIFY=3Dy +CONFIG_JFFS2_FS_WRITE_VERIFY=3Dy CONFIG_JFFS2_SUMMARY=3Dy CONFIG_JFFS2_FS_XATTR=3Dy CONFIG_JFFS2_COMPRESSION_OPTIONS=3Dy diff --git a/arch/powerpc/configs/44x/fsp2_defconfig b/arch/powerpc/configs= /44x/fsp2_defconfig index b8b21fa15a07..e626dcb98d34 100644 --- a/arch/powerpc/configs/44x/fsp2_defconfig +++ b/arch/powerpc/configs/44x/fsp2_defconfig @@ -97,7 +97,7 @@ CONFIG_EXT4_FS_SECURITY=3Dy CONFIG_PROC_KCORE=3Dy CONFIG_TMPFS=3Dy CONFIG_JFFS2_FS=3Dy -CONFIG_JFFS2_FS_WBUF_VERIFY=3Dy +CONFIG_JFFS2_FS_WRITE_VERIFY=3Dy CONFIG_JFFS2_SUMMARY=3Dy CONFIG_JFFS2_FS_XATTR=3Dy CONFIG_CRAMFS=3Dy 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 =20 -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'. =20 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 l= en, size_t *retlen, const u_char *buf); =20 -#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 2cb8cb030ae3..75b4244e93b8 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -14,7 +14,7 @@ #include #include "nodelist.h" =20 -#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) { @@ -100,7 +100,7 @@ int jffs2_verify_writev(struct jffs2_sb_info *c, } return 0; } -#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */ +#endif /* CONFIG_JFFS2_FS_WRITE_VERIFY */ =20 int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *= vecs, unsigned long count, loff_t to, size_t *retlen) --=20 2.52.0 From nobody Sat Sep 26 22:00:14 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 83AAD348C52 for ; Sat, 29 Aug 2026 06:25:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; cv=none; b=l60CT0+CkPs8c2Q57CKthBT1Sdm95uWFQOU8HowiCUts/zXwKu/Xi+Iwv8Ss+OjBmQoaYZJWAXgHQfNyTWdMOFBH6GGwzl6kPXAnqTMNUqZDZNzRT/PmkKpiWj7RStQia5VpZvwSLGs/mTK31wv9FGr/XrEvJA03U+YPfMs9ehQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787984746; c=relaxed/simple; bh=P2jj/NVenMrYbTc7r2bbQSGyREGvs1wa/tFZKLs1GfU=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=NXUr1JdtKB0lggn5HNto5ZDapYHTA7hd9oBh9Vr+3VUBphhg4KUbe12e0aRAPNLTQX8Fvk9cIlCDpDuE8jhzMV9EoS/2dsEpYfZpXKa6ZolIe+vGhW4IGwu5AGOLdLu3C9uhqmJ+5XZz7FjodqF6x2gyDX1MdZA9wBDMP1iJTN0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=e1y7l4Ph; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="e1y7l4Ph" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=TJPANoRDN+fYMKpdt+JU9S3bLccMRqCiof0MgFwWlzU=; b=e1y7l4PhB4SfaOvwKAgMRqpDb/LHbrOvtd4RRG+s06Bp4xSgq0ZtZIK38odls8nOMy+Pssfhs dIjbctOBeEbXuDyPgy+AkY4UfTzbYxhEcpy+gjZcQ9qv73489a4eDbvWgIWcyRat6z/ITUyOQq+ TAfgjFIDi2aRqlLcXMYK00s= Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4hX4jz5zbRz12LDl; Sat, 29 Aug 2026 14:15:19 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 483714057D; Sat, 29 Aug 2026 14:25:35 +0800 (CST) Received: from huawei.com (10.50.85.155) by dggpemr100018.china.huawei.com (7.185.36.64) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1544.36; Sat, 29 Aug 2026 14:25:34 +0800 From: zhouminqiang To: , , , , , CC: , , , , , , Subject: [PATCH v2 7/7] jffs2: add runtime toggle for write verification Date: Sat, 29 Aug 2026 14:16:57 +0800 Message-ID: <20260829061658.306854-8-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260829061658.306854-1-zhouminqiang2@huawei.com> References: <20260829061658.306854-1-zhouminqiang2@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems100001.china.huawei.com (7.221.188.238) To dggpemr100018.china.huawei.com (7.185.36.64) Content-Type: text/plain; charset="utf-8" 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 --- 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. =20 + 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=3D0|1 is also supported. + If unsure, say 'N'. =20 config JFFS2_SUMMARY diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index 75b4244e93b8..913183329c54 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -9,12 +9,32 @@ * */ =20 +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include +#include #include #include #include "nodelist.h" =20 #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=3D0|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 uns= igned char *buf, char *eccstr; void *verify_buf; =20 + if (!READ_ONCE(jffs2_write_verify)) + return 0; + verify_buf =3D kmalloc(len, GFP_NOFS); if (!verify_buf) { pr_warn("%s(): verify buffer allocation failed, skipping verification\n", --=20 2.52.0