From nobody Mon Sep 28 15:34:27 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 0BF0B414DD3 for ; Thu, 20 Aug 2026 10:57:05 +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=1787223428; cv=none; b=ZNRH3xDZV8VRG1SUgdfgnBU1mftAifIYv4J41UFQFzqwl3Z/msBr+M2W6YkvAlonQ6PJJlSW5zFGd05q/ZN5LVmkDuXEKDSnToH1aDIyilPnXb4NP4f7kn2jgvtqngVVnzuGkAvFrRUMdz3bOFSzvSNMa+zQtSuOBfMzvHoUX30= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223428; c=relaxed/simple; bh=LdiBfwokbgp0kmpUdpQ0ABPigU7aFMaB8G0KE4qGnSs=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Z6gkkBvQ9TfFJj0MP37cMtL8410LmSSzvgSp2UWvqo2LyZi/sGhggp4G/XSf2DllTPqaZykj3H5QbGk6Cm2n8tziTUD1y6nz0PSJpnne8WuiFRQR7LdoLiyeAH9GtunFLTYHEBitK24Rw1v4Zhn+4VkQSt+BjG6RhNCk+K+qT1Q= 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=XgLrhPFO; 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="XgLrhPFO" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=quF9NbDt4UT4axTaHFsmKw/ynG1LA3xITgMxyw7ruVA=; b=XgLrhPFOqBO51eUXgJ2ZLYpR5MUCQHvTRv5ZV/N/JfHQrMP4M4HuhTd/mMpb89J5qwdxo5qfu CfGyN4d5XHND6gkPA+6Gy0vENi5FKeD4vnBYk+nff0WAU4cyAE6ngqnJR00/CKZ2BG1TuwUbR7d e+7thHf81upk5wfVFsCoIsU= Received: from mail.maildlp.com (unknown [172.19.163.127]) by canpmsgout10.his.huawei.com (SkyGuard) with ESMTPS id 4hQg8l5PCkz1K96b; Thu, 20 Aug 2026 18:46:15 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id D27AB40572; Thu, 20 Aug 2026 18:56:57 +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; Thu, 20 Aug 2026 18:56:57 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer Date: Thu, 20 Aug 2026 18:49:57 +0800 Message-ID: <20260820105003.2525647-2-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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 3b7803c75d58..7e4608b43a4e 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -15,6 +15,7 @@ =20 #include #include +#include #include #include #include @@ -233,19 +234,30 @@ static int jffs2_verify_write(struct jffs2_sb_info *c= , unsigned char *buf, int ret; size_t retlen; char *eccstr; + void *verify_buf; =20 - ret =3D mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, c->wbuf_verify); + verify_buf =3D __vmalloc(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); 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 + vfree(verify_buf); return -EIO; + +out_free: + vfree(verify_buf); + return ret; } #else #define jffs2_verify_write(c,b,o) (0) @@ -1214,22 +1231,11 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) return -ENOMEM; } =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); } @@ -1269,14 +1275,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 @@ -1284,9 +1282,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 @@ -1306,20 +1301,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 Mon Sep 28 15:34:27 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (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 45CA1418A22 for ; Thu, 20 Aug 2026 10:57:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223429; cv=none; b=cnNn5pZIOJy3W+gU7RoDoDf1aQ+U+i0Lx2xwIdV/0ksEM+Ueqmhp3DBJUFaBjPFY1CBgcGQTTun8w0IK3EcHamkCbX9DkAtxIWlIjrJOFsy1jLrb3TPMxeU9iI6HJFDkeg6KkSBO9TGDCYg6Z2+QfDlY3LC9MatNWRvFvzXYaIY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223429; c=relaxed/simple; bh=eHENmoZvaqXm0RQxAw595OSPeWY8yCsoBEmrdF6LTzM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Hj83WtP2xnuVmW0msNO/PBjRU7UQ0z8+sdXQWwCSdOwwNro0anvw1dEA8thxLwLbrdkxNNjArqQiG+A3djClVATQ/LMCbsicHGfiE7NTCtmZAk2lN+j5vdSSamsesCCHgRR2CvRVBruOraRiyJ3dBoyc/3n59Wmo8Ony8zpqfSc= 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=pHfltcAG; arc=none smtp.client-ip=113.46.200.218 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="pHfltcAG" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=7L0QcGcokJqrXi4agQNPP9tmzIEptjTM0q6SvndD1xI=; b=pHfltcAGC4jhg9CRuD5NTSdjGSwvr7m0U0qeMEKuhHmPA4rJdwmYjLx28zCVRigj7CEgL13qt JkmgJWQycskn3HiaQS6AFEd9uZl0K9xFg8L/bbON1Fq3mD1pnYRXcCGeXVP5wQumjXnxWQ7K3QL Y+CmAjmW47XhV20DoENuay0= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4hQg8S3fKhzpT0s; Thu, 20 Aug 2026 18:46:00 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 687724057F; Thu, 20 Aug 2026 18:56:58 +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; Thu, 20 Aug 2026 18:56:57 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison Date: Thu, 20 Aug 2026 18:49:58 +0800 Message-ID: <20260820105003.2525647-3-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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. While memcmp() compares byte by byte internally, it only reports equal or not-equal without identifying the mismatch offset. To pinpoint the exact mismatch offset, replace this with the approach used by UBI's self_check_write(): compare byte by byte and, on mismatch, report the first differing offset and dump up to 128 bytes of both the source and read-back data. Signed-off-by: zhouminqiang --- fs/jffs2/wbuf.c | 53 +++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 7e4608b43a4e..da6da813a4ef 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -231,8 +231,8 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace= _raw(struct jffs2_sb_info static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf, uint32_t ofs) { - int ret; - size_t retlen; + int ret =3D 0; + size_t retlen, i; char *eccstr; void *verify_buf; =20 @@ -246,37 +246,46 @@ static int jffs2_verify_write(struct jffs2_sb_info *c= , unsigned char *buf, ret =3D mtd_read(c->mtd, ofs, c->wbuf_pagesize, &retlen, verify_buf); 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; } - if (!memcmp(buf, verify_buf, c->wbuf_pagesize)) { - ret =3D 0; - 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"; + + 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 vfree(verify_buf); - return -EIO; + return 0; =20 out_free: vfree(verify_buf); --=20 2.52.0 From nobody Mon Sep 28 15:34:27 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 568BA418A54 for ; Thu, 20 Aug 2026 10:57:07 +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=1787223430; cv=none; b=MMxLZb2k/ux6CPndJ7VCVGGSXuaDV6yehy4q85iP2XkbVfDYBJOxN4sUBeNSiV9POpPzo/SUAGaDaojw+gzJi0yPvowjnvKQSo+LITsDMjshXgyidP6Fq3YY24kZiyk5tvi6qKDusoZk6ikx0jCmzwinluMq3kcRGy8jYjzCpwk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223430; c=relaxed/simple; bh=cmSuT8jA/uj5eeRS4o7NBRgmaydHr1PZ2chaAErybtM=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=PFw74ZfHDfsExlemwWNTuEJk5ZbNwIEtBk1M6SJiADQqRtU+hLM1UhUwicYendX2Qw40v24guvPpKjjy1Si4+rzRkO0kHRJ4nIcK4xSeHvAAn6vQfRP5mcuamGBGmpv0Qrna99cxvQzK0Z6haZ/dou+HyBaqoz5Co35Qu6hI3VQ= 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=vpAivaB1; 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="vpAivaB1" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=oVvANMbS+pKKFKvKgNIn7+GZynnIjYMHabFNZQ7LCTE=; b=vpAivaB1O9LfNH8j6JFpkFICL+Joxel+lCeddz4BTALGy5uBfJiERXzB2pPd8EzfTHMnSsuhA TBUXhtniPVIRjqQPxWdJBHuHDiLMe6zB9Z3ODafsJJjfzqzbwnC0XLysIsOHPgwkicFEPGDmZRY 2eQfmUUby3Sv7YNln4y8H34= Received: from mail.maildlp.com (unknown [172.19.162.223]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4hQg990NYhzcb0T; Thu, 20 Aug 2026 18:46:37 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 0106640561; Thu, 20 Aug 2026 18:56:59 +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; Thu, 20 Aug 2026 18:56:58 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev Date: Thu, 20 Aug 2026 18:49:59 +0800 Message-ID: <20260820105003.2525647-4-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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 | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index da6da813a4ef..3e99587f40e4 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -229,33 +229,33 @@ static struct jffs2_raw_node_ref **jffs2_incore_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 =3D 0; size_t retlen, i; char *eccstr; void *verify_buf; =20 - verify_buf =3D __vmalloc(c->wbuf_pagesize, GFP_NOFS); + verify_buf =3D __vmalloc(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); 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; } =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; @@ -270,9 +270,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 @@ -292,7 +292,7 @@ static int jffs2_verify_write(struct jffs2_sb_info *c, = unsigned char *buf, return ret; } #else -#define jffs2_verify_write(c,b,o) (0) +#define jffs2_verify_write(c,b,o,l) (0) #endif =20 /* Recover from failure to write wbuf. Recover the nodes up to the @@ -455,7 +455,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ret =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\n"); kfree(buf); @@ -672,7 +672,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 @@ -904,6 +907,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 Mon Sep 28 15:34:27 2026 Received: from canpmsgout12.his.huawei.com (canpmsgout12.his.huawei.com [113.46.200.227]) (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 EFF8C4156E6 for ; Thu, 20 Aug 2026 10:57:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.227 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223428; cv=none; b=ZVqqr4oqm9jH+TPACNJQvrX38YFEKJIVE5cX2hsDCD1IJa0VCqB2mUfAyl2pfrR1JsbsRROHxBbmflzaulXbn9Adcyyqmfw2CmDIf1/IhVqbHEhYSLFhr8IXeGkRQNymmY8GiEvqK8yTwnGbSW38fdh/5bM3/ux3jK8qBotGLXY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223428; c=relaxed/simple; bh=uqBusC/7DdAJ30MGwOLerR9RwJo6zRnOhw9P+Ab1qdg=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=shIpKREQt9LGMBimeziGHDxXQanGrRmD3Jr7NMTNYopXVQRo8KFaoLSNNqZJdexcFHrq9MDXj3a0xfOd5nsscfByFlLn6IpA/zQDgtcAAht4sR9IitpNf2qVz5qVSphEuTYd47xTTgAFV2SQcPSIUBUBFKvpUcwra6Z1jCPj1QQ= 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=29kIScDF; arc=none smtp.client-ip=113.46.200.227 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="29kIScDF" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=qm8fKtYZiI5YPRB/KYaBj55w3BQ38qaKiejE53UxzIg=; b=29kIScDFsvD4rJOEgQYOVB22ZfF5TK2nQ7o0w7xEHGmEo6M7nuNA+h+sLhHJf5t5rYx1PFdhC FCPmXFcPyDHJWBOmTveu1lfiTNYR7e3jxFi9kfgLKIpzSinEJcREhK3/zQLOf+igzRiwjs3hu25 FBAwG2/K+9wdARSthkjnziM= Received: from mail.maildlp.com (unknown [172.19.163.163]) by canpmsgout12.his.huawei.com (SkyGuard) with ESMTPS id 4hQg9F4kwpznTVd; Thu, 20 Aug 2026 18:46:41 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 89C7A4048B; Thu, 20 Aug 2026 18:56:59 +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; Thu, 20 Aug 2026 18:56:58 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 4/6] jffs2: add write verification to NOR direct write paths Date: Thu, 20 Aug 2026 18:50:00 +0800 Message-ID: <20260820105003.2525647-5-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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. Signed-off-by: zhouminqiang --- fs/jffs2/os-linux.h | 11 ++++ fs/jffs2/wbuf.c | 69 ------------------------- fs/jffs2/writev.c | 122 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 130 insertions(+), 72 deletions(-) diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 86ab014a349c..e73ef643fd97 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -192,6 +192,17 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c,= const struct kvec *vecs, int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t 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 3e99587f40e4..493be5765c47 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -15,7 +15,6 @@ =20 #include #include -#include #include #include #include @@ -227,74 +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 =3D 0; - size_t retlen, i; - char *eccstr; - void *verify_buf; - - verify_buf =3D __vmalloc(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; - } - - 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; - } - - vfree(verify_buf); - return 0; - -out_free: - vfree(verify_buf); - return ret; -} -#else -#define jffs2_verify_write(c,b,o,l) (0) -#endif - /* Recover from failure to write wbuf. Recover the nodes up to the * wbuf, not the one which we were starting to try to write. */ =20 diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index a1bda9dab3f8..39adc15ffd69 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -10,12 +10,100 @@ */ =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 =3D 0; + size_t retlen, i; + char *eccstr; + void *verify_buf; + + verify_buf =3D __vmalloc(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; + } + + 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; + } + + vfree(verify_buf); + return 0; + +out_free: + vfree(verify_buf); + return ret; +} + +int jffs2_verify_writev(struct jffs2_sb_info *c, + const struct kvec *vecs, + unsigned long count, loff_t to) +{ + loff_t ofs =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; if (!jffs2_is_writebuffered(c)) { if (jffs2_sum_active()) { int res; @@ -26,15 +114,31 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c,= const struct kvec *vecs, } } =20 - return mtd_writev(c->mtd, vecs, count, to, retlen); + 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); + } + + 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); - if (jffs2_sum_active()) { struct kvec vecs[1]; int res; @@ -47,5 +151,17 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, l= off_t ofs, size_t len, return res; } } + + ret =3D mtd_write(c->mtd, ofs, len, retlen, buf); + + 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); + return ret; } --=20 2.52.0 From nobody Mon Sep 28 15:34:27 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 D1417411FB4 for ; Thu, 20 Aug 2026 10:57:02 +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=1787223426; cv=none; b=V1iS5JwAqDBLCVuCoDfUryUoZiaUpbtX8q+npFrAuRW42WcyqRT3Y5+OdxuGNh09IuVm25o3f2tFMliESs3icfdLb/aT6dAhf5xOLiJLqhxcRBHAGLduYJ1/GYbLaAJj9RLmUHecJ4TMEPMYnipRvnwr2jwA+kh439R+6EAmAHk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223426; c=relaxed/simple; bh=+9KM5ggydkGsvD45gIlFT59zrdrhiIHnFHkifBCTkl4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=jFvASaRJ0TOYljHST40XKm8PumuhDA4wLvF7K9LLgPpHRxFeD2TCoyaDTNdSF/XYnYHdsmyJnQTYbw5k24rhoggszlJTGb/KcV0IUUbpntTcawBGvXWSVPAj2aDot6oQsmMoTxzHBB87RhZak/1vmiEGArYDfSgBjvnpVjnZ79Q= 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=wqHoJPYK; 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="wqHoJPYK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=6jIEgeBx8wgQoM1im7wbkSvNvmKimKnfj2DovqjaFlI=; b=wqHoJPYK2sGROKMjrESU3EJZCuvwy6BK9BUGyC4JS2BIyGJq9Rs+E0DYmMH7xLDQStAfFP1ow 77LOs/OzVxBX5VLS8gNKv+85bMWOLxbBeNoYy+abzoonlwxm23qDECNx62h526rYJq6OnYctfg6 3eqYFMDiOFdXcXBXH7ASzEw= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4hQg9C49Ddz12LDl; Thu, 20 Aug 2026 18:46:39 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id 1E0224057F; Thu, 20 Aug 2026 18:57:00 +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; Thu, 20 Aug 2026 18:56:59 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY Date: Thu, 20 Aug 2026 18:50:01 +0800 Message-ID: <20260820105003.2525647-6-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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. Signed-off-by: zhouminqiang --- fs/jffs2/Kconfig | 23 ++++++++++++++++++----- fs/jffs2/os-linux.h | 2 +- fs/jffs2/writev.c | 4 ++-- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/fs/jffs2/Kconfig b/fs/jffs2/Kconfig index 560187d61562..556025a5d438 100644 --- a/fs/jffs2/Kconfig +++ b/fs/jffs2/Kconfig @@ -42,13 +42,26 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash =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 39adc15ffd69..fc1eae60c476 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) { @@ -98,7 +98,7 @@ int jffs2_verify_writev(struct jffs2_sb_info *c, } return 0; } -#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */ +#endif /* CONFIG_JFFS2_FS_WRITE_VERIFY */ =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 Mon Sep 28 15:34:27 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (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 36521389111 for ; Thu, 20 Aug 2026 10:57:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223431; cv=none; b=DEs+Cxzqzm8VaXp1TCC63lbq/FqP++GpYevtcQ4YYvGhYHJZIukusvtfPH1UZzfk6BCw7y9KVXRt6tQuCRlemQSiptwdNVqTRJiLOwaB5eenURfxS7Zz7yWFTvFCkaKem7wrr9uwvLvkO+++FG9ybj2dOY6qOdhwX5UhOGKtZkw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787223431; c=relaxed/simple; bh=Nttx8T1xym36MBGXKOwvnJ3Uz/oMRm+BKEOkbjf8XU4=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=RojN438kT1JYMp+KfMvaVuNXWt3HavDnzaZ7obch5LRFf0KcvCSn6erfmAUVTB0gADjn29fXlTWMcqW5iw+HeGz6ZJcn1Y17YSdyDHCjiXcYbovoZNZOySfmahb2uJkZ2oQrTagmNKsIi4AqDvqRchhM2ShJphmslKY9sy8ZbUE= 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=OCmxK7oK; arc=none smtp.client-ip=113.46.200.218 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="OCmxK7oK" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=/TR7Ya244Vuybsce9gxyOWbUCBZRN+8PiB8fEOS0TpA=; b=OCmxK7oK1lKSypL7S2R3CRyhSzYLf6NKFdvk0RBtIlmmppUlvH6DjZNaXOgSgIibsUwMSWfQ1 Gzc5iPZy0BKX/L0IX7MAN8OcE3pa+Radhgr63up+ETDpC3z+1E1mo3e/1ycML37LOJMTpyKWegp HLbFl+94PULGVNjr5kSiluQ= Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4hQg8V5WhlzpT1J; Thu, 20 Aug 2026 18:46:02 +0800 (CST) Received: from dggpemr100018.china.huawei.com (unknown [7.185.36.64]) by mail.maildlp.com (Postfix) with ESMTPS id A628D40537; Thu, 20 Aug 2026 18:57:00 +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; Thu, 20 Aug 2026 18:57:00 +0800 From: zhouminqiang To: , CC: , , , , Subject: [PATCH 6/6] jffs2: add runtime toggle for write verification Date: Thu, 20 Aug 2026 18:50:02 +0800 Message-ID: <20260820105003.2525647-7-zhouminqiang2@huawei.com> X-Mailer: git-send-email 2.52.0 In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com> References: <20260820105003.2525647-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: kwepems200002.china.huawei.com (7.221.188.68) 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 fc1eae60c476..b32eb07747f4 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 __vmalloc(len, GFP_NOFS); if (!verify_buf) { pr_warn("%s(): verify buffer allocation failed, skipping verification\n", --=20 2.52.0