From nobody Sat Sep 26 01:55:03 2026 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (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 A29F4261B8D for ; Sun, 6 Sep 2026 03:12:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664362; cv=none; b=nuAMOAQHxCOOwhssrx5rr26mP5jnpYCblYEe1lp9qGFNt+nDmzo14/7IKCFG8zDPiCkn2iYqQkdNjvQyQlOJLa4bbcWC7sGXVfKu7dvMBkQrFjfNqE0OmtQUkKbeE9DmGUIO9aOwaWpev2z6SlW6Odqym/RN32GGmZsO21IFuUY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664362; c=relaxed/simple; bh=zzQBKTVEHs1nUCLb0YOR4hoNiqaUR8Zp8D6eGEpc/tw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jBnSUP51Czd+qD9LgFJyCAGqDCmOBVG3rrz1+7Yn/ojl+wkHdd9R7wCMuTRE4zSbYYwSu6K/EOwsCPNSlZDUTEi2r/bm8KWUeKK3DVQ4cvoYHn9EFPjsF11OWlS6UjYjxrn1DRGABERUO8HCDrFyJmRiF76qaDEl9d9C75Wc6to= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.198]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGX1hN9zYQtqq for ; Sun, 6 Sep 2026 11:11:48 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 9536640574 for ; Sun, 6 Sep 2026 11:12:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S5; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 1/8] jffs2: wbuf: clear wbuf on recovery failure paths Date: Sun, 6 Sep 2026 11:03:37 +0800 Message-ID: <20260906030344.2448622-2-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S5 X-Coremail-Antispam: 1UD129KBjvJXoW3AF4UWw17Gw4DKF47try3XFb_yoW7CrW3pr ZIyF13Ar45Kr1xJFs5tF15XrW8u3y8Gr1IgrWruw1xXF4vqr1aganaqFy8uFW0yrZ2qa10 kwsYk3y7Xr1jy3DanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUGw A2048vs2IY020Ec7CjxVAFwI0_Gr0_Xr1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVW8ZVWrXwCF04k20xvY0x0EwIxGrwCF04k20xvEw4C26cxK6c8Ij28IcwCFx2IqxVCF s4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r 1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8 JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxUV0PfDUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 01:55:03 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (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 985F237C109 for ; Sun, 6 Sep 2026 03:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; cv=none; b=C27nSrtWllgp8EcLQ90L770j3zU3zDXotqMPFtbtdiu/B+q3tn/3Os+3ehuLTPke+06wgCCKpVXHHtNBdue4NcjfEbZQwnFoWn8tB2Fp1bfuTIAPd/IG7buqlQ+6NWiw5xx6l3PaEzSJ6W8fbeOrKl1rp3Mf/JSXkR7EpUJEhy4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; c=relaxed/simple; bh=TQezh0hqv5prCDqGuEwD/nlwl56ncMzmc6vfExSKnAo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gD9iRbMLd2SZUMTOwVMVC3tzrd1mABBI0ZonFSl+HVFIfXRwT7ev1pZe8AwWQWxXqVHWcgq2xZvHnK81Jf1kWQvmHFtYS0zvG+kZDTklXQfd4OlyYQkEC0ysG2cWK490IPQRhoEkPuz9cF5+J9vmK54+ML21T+gc9H4vVsa3CvA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.170]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGK5fHrzKHMRY for ; Sun, 6 Sep 2026 11:11:37 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id B3E324056F for ; Sun, 6 Sep 2026 11:12:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S6; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 2/8] jffs2: wbuf: fix OBSOLETE under-coverage on recovery failure Date: Sun, 6 Sep 2026 11:03:38 +0800 Message-ID: <20260906030344.2448622-3-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S6 X-Coremail-Antispam: 1UD129KBjvJXoWxArW3ZrykJry3Jw1kWrWruFg_yoW5Jw1Dpr yfAry3Gr1DGFyrWFnrAFy5t345Cr4rGrWIqayfJryxX3ZYvr1Sga4qgFnYvry8A3yvqr4j 9r4UtFyUGF1UGFJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmlb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUXw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV WxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVCY1x0267AK xVWxJr0_GcWle2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2 WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE7xkE bVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262kKe7 AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCF04k20xvEw4C26cxK6c8Ij28IcwCFx2IqxVCF s4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r106r 1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AKxVW8 JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Cr0_Gr1UMIIF0xvE42xK8VAvwI8IcIk0rV WUJVWUCwCI42IY6I8E87Iv67AKxVW8JVWxJwCI42IY6I8E87Iv6xkF7I0E14v26r4j6r4U JbIYCTnIWIevJa73UjIFyTuYvjxUo8nYUUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang In jffs2_wbuf_recover(), when the recovery write to the new erase block also fails, the code marks the already-written portion as REF_OBSOLETE via jffs2_add_physical_node_ref(). However, the length passed is ref_totlen(c, jeb, first_raw), which is the length of a single node on the old block, rather than the full range of data that was attempted to be written to the new block. On the recovery target block the layout is: ref_totlen(first_raw) |<------------->| ofs +---------------+-------+-------+ +--------+ | node 1 |node 2 |node 3 | ... |erased | +---------------+-------+-------+ +--------+ | OBSOLETE | | |<-towrite (page-aligned)->| | |<-------- end - start -------->| | |<-truly free->| When the recovery buffer contains multiple nodes, ref_totlen only accounts for the first node's length, which can be much smaller than the total range. This under-deducts free_size, so the next write lands at the start of node 2, which is already programmed on NAND, and the AND operation corrupts both the old and new data. With towrite as the OBSOLETE length, the next write lands right after towrite in truly free space. However, node 3's header has been written within the towrite region while its data extends beyond it due to page-alignment truncation. On remount, the scanner finds node 3's header, validates its CRC, and trusts its totlen -- skipping PAD(totlen_node3) bytes. This skip extends past towrite into the area where the subsequent write was placed, creating a shadow zone that causes the newly written data to be silently lost. Use end - start as the OBSOLETE length, which covers the full range of data that was attempted to be written to the new block, so that neither the NAND AND corruption nor the scanner shadow zone can occur. Fixes: b64335f2b740 ("[JFFS2] Add length argument to jffs2_add_physical_nod= e_ref().") Signed-off-by: zhouminqiang --- fs/jffs2/wbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 61e3dbd4cd7b..ab247117ec77 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -437,7 +437,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) kfree(buf); =20 if (retlen) - jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, = first_raw), NULL); + jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, end-start, NULL); =20 c->wbuf_len =3D 0; return; --=20 2.52.0 From nobody Sat Sep 26 01:55:03 2026 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (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 A2A77305E1F for ; Sun, 6 Sep 2026 03:12:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664361; cv=none; b=DWocpWfRB1vIaz811e4Idy+KM9BB61lchn330UF8KliUeFn5yFb9ZkVrGOCYXpeROY1Cr6wRNJKJhn9MmW/2JkqLCbFgbAFcoJo32bbSagXysjuUn75DY0peGbu21IaU9eppq10Bj/SO6XxKh+vOgtuLdGZzU2K7wP7cyM1HOTI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664361; c=relaxed/simple; bh=/KxzRM0SUSyBhBLAvdxlLLzFbeAWmoVTd6ZZkeL/5mM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ZtWwiRa/LTl7KBCGl6XXAUPBKc+IRb52pBF4K9/Jpg5ITuJKLPSdMIFiNgLm8SZJnW07wJNa/Y+KIX0l2rnevKVH/7KvtjE8lim9/4+Vz23o6rsZOQsC5AmiXEfArqKATUJNh+zzFkpygtpIvnNCf3sjVI1AXy/29uYJA6RkcbA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.198]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGX3DybzYQtqc for ; Sun, 6 Sep 2026 11:11:48 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id CAD3240574 for ; Sun, 6 Sep 2026 11:12:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S7; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 3/8] jffs2: replace per-superblock verify buffer with per-write buffer Date: Sun, 6 Sep 2026 11:03:39 +0800 Message-ID: <20260906030344.2448622-4-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S7 X-Coremail-Antispam: 1UD129KBjvJXoWxCr4UKry8KFyrGr45tr13Arb_yoWrtw45pF sayF13Ar48JryxWrs5tFn5Cw15KrW8Gr1Igr47C348Xa18tr1Iqa4rtFy8ZrWrArZ7Wr1S ka9Ikw1rXF1UX37anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmGb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUWw A2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0rcxS w2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267AKxV W8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F40Ex7 xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC6x0Y z7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxVAaw2 AFwI0_Jw0_GFyl42xK82IYc2Ij64vIr41l42xK82IY64kExVAvwVAq07x20xyl4I8I3I0E 4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGV WUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_ Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj4 0_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8 JrUvcSsGvfC2KfnxnUUI43ZEXa7IUbdMaUUUUUU== Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 ab247117ec77..7e52241de457 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 01:55:03 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (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 984F1305E1F for ; Sun, 6 Sep 2026 03:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664368; cv=none; b=kT5PW1S/rCDj5/Pf+VFYE3KzLuGTTeHBf4FUY9ZYqlDZ8irQfxVfybSDUaWx9cy3B9FDoBisN/0WOI9akcn4/m82HCwM+FMVTd27iGh01OhoVSSbC7SqKwrJBetaXoDC2EOywQVxQqHw0kemBIP0TFVpt0+kkpwkBoF5GnBUXGQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664368; c=relaxed/simple; bh=es2SAREtlwpipJhOBild8lxyo8UddtY/8yaG6OMAt9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=PxKJSwWOoZV19kEUsN5nexIFxXnP9bJFDCq9fxr/3msBYqhhTYagcIBAlXEPROHuviUFjYOVh/1KwwKOPYgDr2N4YFWN68XUwE1weNWi1AVxxtagULGI1qt7pEUrW/VtMaLSp+W4e5sk4jiMPl4wyzoLaHGM3KWhj1p0fwUr9ys= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.170]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGK72xczKHMS6 for ; Sun, 6 Sep 2026 11:11:37 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id E1FB44056B for ; Sun, 6 Sep 2026 11:12:35 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S8; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 4/8] jffs2: write verify: add byte-by-byte comparison on mismatch Date: Sun, 6 Sep 2026 11:03:40 +0800 Message-ID: <20260906030344.2448622-5-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S8 X-Coremail-Antispam: 1UD129KBjvJXoWxXFyxtF18ZFykZF4xXF1fWFg_yoW5Cw1kpr say34ayF48Jry7WrsIkFs5C3W3J3y8Gr4xKrW3A34fZa18Z34IgayFqF17ArWFyFZ7X3Wj 9FZ0kr1rGFn8tFDanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQ0b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l42xK82IY64kExVAvwVAq07x20xyl4I8I 3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxV WUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAF wI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2 IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxF4iUUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 7e52241de457..b2ce642e9bc5 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 01:55:03 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (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 9880237C91E for ; Sun, 6 Sep 2026 03:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664368; cv=none; b=QYGYuBBMXNFYAMKORDIH42ZXo1mQB3R9bXs9fS4rS7saf/EL57hmgE9rO1rTPBNo2SGH1u9mTQIqRNk1Tr+/+MzTbeGduRgR3uI/68A45HCKIEhfSkxFJUvuIfvZg/ii0zxUhIARES1Ktt62hJeleVeMH03yseUsMQm0ot9crb4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664368; c=relaxed/simple; bh=+zeYXutgmwm2Am71pplb9PeZRp+bqoDl0FySunjeoTo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=cfkbvfr/dVb2Y5eRwUCFmCm3MMUwd0GWuHj/y9dLayCIVX1yaZnfFS8Yfyvlfmt75zDVn8ORhxx2Nesx1udAJyZs9PILzTuIh2BZaAw/EYu5b9UHDc0KyGc64fKLrWj9lvuV5C3xsfW1RmNcRpEvtabGBowhQ4CSWSUABN0KiGE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.170]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGL0h5xzKHMSB for ; Sun, 6 Sep 2026 11:11:38 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 090194056B for ; Sun, 6 Sep 2026 11:12:36 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S9; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 5/8] jffs2: add write verification to direct page writes in flash_writev Date: Sun, 6 Sep 2026 11:03:41 +0800 Message-ID: <20260906030344.2448622-6-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S9 X-Coremail-Antispam: 1UD129KBjvJXoWxCrWfKry8WryfWr48Cr4rZrb_yoWrtFW5pr ZIkr15Ar4fKryfGFsayFs8Z343Kay8Gr1Igr43C348Xa1Fvr17KayYgFy8ArWrArZ7Xw40 krsak345Jr1Yq3DanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQ0b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l42xK82IY64kExVAvwVAq07x20xyl4I8I 3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxV WUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAF wI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2 IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxF4iUUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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. Also add __GFP_NOWARN to the kmalloc in jffs2_verify_write() to suppress high-order allocation warnings when verifying summary writes on large-erasesize NAND. 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 b2ce642e9bc5..c146ece15660 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 | __GFP_NOWARN); 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 01:55:03 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (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 9682637C0FE for ; Sun, 6 Sep 2026 03:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; cv=none; b=qB8f78P5Z+sSXMTUyHb+iFWCnxQPfORTZ5FnW80YtFrAN/hNtjvhE2JuFDUbN8Pnt9FeiFVpkuv4JY+gSqopnBQXl4v56KkKEWODDyvEj2IATjScleM4QJc6mj6qmP/qWsvW1JLUxNCn+zGIyFvil1giIyzu9E7lJqxYSBzEloA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; c=relaxed/simple; bh=0w+uqFwhgEOXs036zodQj+TKyMMKaPHj1V5wvSfK8IQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=RGbbJF6w3hhCx9c3UWkSUOKpzroQRD8xKZos+29OSHfzHS7LEWnxiEe2XQA+8/ATlk8wwL3vVKoJ8+r3+0auHJfe7S1qP9S5r6U8cjhaSTt6XNJQn/lP4sy0yQ+ffjXKM9Hc/jQ+vVEQwTFZzqMQNVvrQj5R2qlxYZwbOUc9gT4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.177]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGL16FZzKHMS4 for ; Sun, 6 Sep 2026 11:11:38 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 153F04058C for ; Sun, 6 Sep 2026 11:12:36 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S10; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 6/8] jffs2: add write verification to NOR direct write paths Date: Sun, 6 Sep 2026 11:03:42 +0800 Message-ID: <20260906030344.2448622-7-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S10 X-Coremail-Antispam: 1UD129KBjvJXoWxKrWkJFWUKr4DZryUZw17trb_yoW3CryDpF Z0y3sxtrWrG3WxGrnIyFs8X3W5K3yUGr1IgrW3Cw13Za1Fvr1qga90g34jyryrJrZ7Zryj gFZY9a45JF15trJanT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQ0b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l42xK82IY64kExVAvwVAq07x20xyl4I8I 3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxV WUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAF wI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2 IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxF4iUUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 c146ece15660..6ad1459fc664 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 | __GFP_NOWARN); - 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..e96f10566fe1 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 | __GFP_NOWARN); + 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 01:55:03 2026 Received: from dggsgout11.his.huawei.com (dggsgout11.his.huawei.com [45.249.212.51]) (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 A282D12F585 for ; Sun, 6 Sep 2026 03:12:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.51 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664363; cv=none; b=sl9bmCAsg0BjOARxkA0hIewKhKOPEovnBz0FkrJYl5/tHj6ZbKzgI+mtnSmGbqaYEXMxCGlxEciT0dON63sjYFIPfhK88BDgit3d1uaESUPA50Nwi0vgDP4T9QC4Wk3gJAgka9aNw33+W4x1xDDenx8kRFzUzqhH/nS1EzXwB8g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664363; c=relaxed/simple; bh=RoOzhksC5UxUJkAMLtcAc2dDIKJ9fClhlaTw5AEAMl4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tp1CU1x2yz0bQI6kMb7UAYZU0tqpoZal/hjpJDQ7OFQvrzLG8vPxOwI5eUiFX2knClT2yhqeMIUmFXdeklTYU4V/coctCXcP48jq+2NhJjOfPwD4E7WwrOOcQ8XcRo2R3Re2xSFzCEeWCjACJnW+1to+w5BtNa1W0rJtLQ0g3v0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.51 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.198]) by dggsgout11.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGX5svtzYQtqP for ; Sun, 6 Sep 2026 11:11:48 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 2F91240574 for ; Sun, 6 Sep 2026 11:12:36 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S11; Sun, 06 Sep 2026 11:12:35 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 7/8] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY Date: Sun, 6 Sep 2026 11:03:43 +0800 Message-ID: <20260906030344.2448622-8-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S11 X-Coremail-Antispam: 1UD129KBjvJXoWxKFyUAFWfGF1kJFW7ury3Arb_yoWxGry5pF n5AwsxJF4kGF1YqrZrAFyvga98tFnrZrWjgr47Cw1UuF95Z342va4qyrnxAr48XrZrKr40 9a9a9FyfKr1xJ37anT9S1TB71UUUUUDqnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQ0b4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_Cr1j6rxdM2AIxVAIcxkEcVAq07x20xvEncxIr21l5I8CrVACY4xI64kE6c02F4 0Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AKxVWUJVW8JwAm72CE4IkC 6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41lFIxGxcIEc7CjxVA2Y2ka0xkIwI1lc7CjxV Aaw2AFwI0_GFv_Wryl42xK82IYc2Ij64vIr41l42xK82IY64kExVAvwVAq07x20xyl4I8I 3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxV WUGVWUWwC2zVAF1VAY17CE14v26r1q6r43MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAF wI0_Gr0_Xr1lIxAIcVC0I7IYx2IY6xkF7I0E14v26r4UJVWxJr1lIxAIcVCF04k26cxKx2 IYs7xG6r1j6r1xMIIF0xvEx4A2jsIE14v26r4j6F4UMIIF0xvEx4A2jsIEc7CjxVAFwI0_ Gr1j6F4UJbIYCTnIWIevJa73UjIFyTuYvjxUxF4iUUUUU Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 e96f10566fe1..604a14bb5710 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 01:55:03 2026 Received: from dggsgout12.his.huawei.com (dggsgout12.his.huawei.com [45.249.212.56]) (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 D4CCC37DE99 for ; Sun, 6 Sep 2026 03:12:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=45.249.212.56 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; cv=none; b=fCKndH8kGsnfzQ05IjCdResikxNRWbuNNsLDmSoUVTqc6iUpVnOUPFIBQOo+vzzYkcmFR4YDQhV5eIJNfdSTzRkwAyfIbQDG9DO7E2JCpkgA0R6q97ajPPaMv8Y3GEJJTb8Eb+ZtSGtPNqu17LRoAY7DTgZP3tLOtrrv7pRRH94= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788664367; c=relaxed/simple; bh=N4ai5MWz7UE3k9+4zS+T8ZgNPL6OPRqg43X5h4FP6ac=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jI24927DX4dI5k9m2ePCPclxDfr5v6pfSwSjJtCXU9qQBLcomcF2mN0iK9Ti+BzE9GGxVl9uhQTIFetLej1qE6GObFH9eI5mtDDbYp7KeAFrXDi/azbMCi13KGKnh17shJ8SSsiwz1XGNPZFdsuytpmTYTpv/8xafXXVj1BJTyw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huaweicloud.com; arc=none smtp.client-ip=45.249.212.56 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huaweicloud.com Received: from mail.maildlp.com (unknown [172.19.163.177]) by dggsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hcwGL2Xj3zKHMSN for ; Sun, 6 Sep 2026 11:11:38 +0800 (CST) Received: from mail02.huawei.com (unknown [10.116.40.112]) by mail.maildlp.com (Postfix) with ESMTP id 479AE4058C for ; Sun, 6 Sep 2026 11:12:36 +0800 (CST) Received: from huaweicloud.com (unknown [10.50.85.155]) by APP1 (Coremail) with UTF8SMTPSA id cCh0CgBnUAsW2pxqmzytAw--.18069S12; Sun, 06 Sep 2026 11:12:36 +0800 (CST) From: Zhou Minqiang To: linux@armlinux.org.uk, vz@mleia.com, piotr.wojtaszczyk@timesys.com, maddy@linux.ibm.com, dwmw2@infradead.org, richard@nod.at Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mtd@lists.infradead.org, chengzhihao1@huawei.com, yangerkun@huawei.com, yi.zhang@huawei.com, zhouminqiang Subject: [PATCH v4 8/8] jffs2: add runtime toggle for write verification Date: Sun, 6 Sep 2026 11:03:44 +0800 Message-ID: <20260906030344.2448622-9-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260906030344.2448622-1-zhouminqiang2@huawei.com> References: <20260906030344.2448622-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-CM-TRANSID: cCh0CgBnUAsW2pxqmzytAw--.18069S12 X-Coremail-Antispam: 1UD129KBjvJXoWxAF1rtr1kGw47GryUWr1kuFg_yoW5Ww1xpF ZYvFnxK3sxtr12yrsxA3WFga45KaykGryIqrW3uw17X3WrK34qyFy8t345CF48XrWkKFyj gF4Sk343Gr17JrJanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUQjb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I20VC2zVCF04k2 6cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI8067AKxVWUAV Cq3wA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF64kEwVA0 rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW5JVW7JwA2z4x0Y4vE2Ix0cI8IcVCY1x0267 AKxVW8Jr0_Cr1UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7Cj xVAFwI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I8CrV C2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r1j6r4UMcvjeVCFs4IE 7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x0262 kKe7AKxVWUtVW8ZwCF04k20xvY0x0EwIxGrwCF04k20xvEw4C26cxK6c8Ij28IcwCFx2Iq xVCFs4IE7xkEbVWUJVW8JwC20s026c02F40E14v26r1j6r18MI8I3I0E7480Y4vE14v26r 106r1rMI8E67AF67kF1VAFwI0_Jw0_GFylIxkGc2Ij64vIr41lIxAIcVC0I7IYx2IY67AK xVW8JVW5JwCI42IY6xIIjxv20xvEc7CjxVAFwI0_Gr1j6F4UJwCI42IY6xAIw20EY4v20x vaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Gr0_Cr1lIxAIcVC2z280aVCY1x0267AKxVW8 Jr0_Cr1UYxBIdaVFxhVjvjDU0xZFpf9x07UdCzZUUUUU= Sender: zhouminqiang@huaweicloud.com X-CM-SenderInfo: 52kr3z5lqtxttqj6x35dzhxuhorxvhhfrp/ Content-Type: text/plain; charset="utf-8" From: zhouminqiang 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 604a14bb5710..342c413be95c 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 | __GFP_NOWARN); if (!verify_buf) { pr_warn("%s(): verify buffer allocation failed, skipping verification\n", --=20 2.52.0