From: zhouminqiang <zhouminqiang2@huawei.com>
To: <dwmw2@infradead.org>, <richard@nod.at>
Cc: <linux-mtd@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
<chengzhihao1@huawei.com>, <yangerkun@huawei.com>,
<yi.zhang@huawei.com>
Subject: [PATCH 4/6] jffs2: add write verification to NOR direct write paths
Date: Thu, 20 Aug 2026 18:50:00 +0800 [thread overview]
Message-ID: <20260820105003.2525647-5-zhouminqiang2@huawei.com> (raw)
In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com>
NOR Flash and other non-writebuffered devices write directly through
jffs2_flash_direct_writev() and jffs2_flash_direct_write() without
any write-back verification. If mtd_write() succeeds but the readable
medium differs from JFFS2's source buffer, a later node CRC failure
cannot distinguish transport/program-time corruption from post-commit
media damage.
Move jffs2_verify_write() from wbuf.c to writev.c so it can be
shared by both writebuffered and direct write paths. Add
jffs2_verify_writev() to iterate over kvec entries and verify each
one individually. In both direct write functions, add mtd_write()
return value and retlen checks, and invoke verification after
a successful complete write.
Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
fs/jffs2/os-linux.h | 11 ++++
fs/jffs2/wbuf.c | 69 -------------------------
fs/jffs2/writev.c | 122 ++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 130 insertions(+), 72 deletions(-)
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 86ab014a349c..e73ef643fd97 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -192,6 +192,17 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf);
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+ uint32_t ofs, size_t len);
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+ const struct kvec *vecs,
+ unsigned long count, loff_t to);
+#else
+#define jffs2_verify_write(c, b, o, l) (0)
+#define jffs2_verify_writev(c, v, cnt, t) (0)
+#endif
+
#endif /* __JFFS2_OS_LINUX_H__ */
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 3e99587f40e4..493be5765c47 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/crc32.h>
#include <linux/mtd/rawnand.h>
@@ -227,74 +226,6 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
return NULL;
}
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
- uint32_t ofs, size_t len)
-{
- int ret = 0;
- size_t retlen, i;
- char *eccstr;
- void *verify_buf;
-
- verify_buf = __vmalloc(len, GFP_NOFS);
- if (!verify_buf) {
- pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
- __func__);
- return 0;
- }
-
- ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
- if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
- pr_warn("%s(): Read back of page at %08x failed: %d\n",
- __func__, ofs, ret);
- goto out_free;
- } else if (retlen != len) {
- pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
- __func__, ofs, retlen, len);
- ret = -EIO;
- goto out_free;
- }
-
- for (i = 0; i < len; i++) {
- uint8_t c1 = ((uint8_t *)buf)[i];
- uint8_t c2 = ((uint8_t *)verify_buf)[i];
- int dump_len;
-
- if (c1 == c2)
- continue;
-
- if (ret == -EUCLEAN)
- eccstr = "corrected";
- else if (ret == -EBADMSG)
- eccstr = "correction failed";
- else
- eccstr = "OK or unused";
-
- dump_len = min_t(int, 128, len - i);
- pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
- eccstr, ofs, i, len);
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
- buf + i, dump_len, 0);
-
- pr_warn("Read back:\n");
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
- verify_buf + i, dump_len, 0);
-
- ret = -EIO;
- goto out_free;
- }
-
- vfree(verify_buf);
- return 0;
-
-out_free:
- vfree(verify_buf);
- return ret;
-}
-#else
-#define jffs2_verify_write(c,b,o,l) (0)
-#endif
-
/* Recover from failure to write wbuf. Recover the nodes up to the
* wbuf, not the one which we were starting to try to write. */
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index a1bda9dab3f8..39adc15ffd69 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -10,12 +10,100 @@
*/
#include <linux/kernel.h>
+#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include "nodelist.h"
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+ uint32_t ofs, size_t len)
+{
+ int ret = 0;
+ size_t retlen, i;
+ char *eccstr;
+ void *verify_buf;
+
+ verify_buf = __vmalloc(len, GFP_NOFS);
+ if (!verify_buf) {
+ pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
+ __func__);
+ return 0;
+ }
+
+ ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
+ if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
+ pr_warn("%s(): Read back of page at %08x failed: %d\n",
+ __func__, ofs, ret);
+ goto out_free;
+ } else if (retlen != len) {
+ pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
+ __func__, ofs, retlen, len);
+ ret = -EIO;
+ goto out_free;
+ }
+
+ for (i = 0; i < len; i++) {
+ uint8_t c1 = ((uint8_t *)buf)[i];
+ uint8_t c2 = ((uint8_t *)verify_buf)[i];
+ int dump_len;
+
+ if (c1 == c2)
+ continue;
+
+ if (ret == -EUCLEAN)
+ eccstr = "corrected";
+ else if (ret == -EBADMSG)
+ eccstr = "correction failed";
+ else
+ eccstr = "OK or unused";
+
+ dump_len = min_t(int, 128, len - i);
+ pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
+ eccstr, ofs, i, len);
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ buf + i, dump_len, 0);
+
+ pr_warn("Read back:\n");
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ verify_buf + i, dump_len, 0);
+
+ ret = -EIO;
+ goto out_free;
+ }
+
+ vfree(verify_buf);
+ return 0;
+
+out_free:
+ vfree(verify_buf);
+ return ret;
+}
+
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+ const struct kvec *vecs,
+ unsigned long count, loff_t to)
+{
+ loff_t ofs = to;
+ unsigned long i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ if (!vecs[i].iov_len)
+ continue;
+ ret = jffs2_verify_write(c, vecs[i].iov_base, ofs,
+ vecs[i].iov_len);
+ if (ret)
+ return ret;
+ ofs += vecs[i].iov_len;
+ }
+ return 0;
+}
+#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */
+
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen)
{
+ int ret;
if (!jffs2_is_writebuffered(c)) {
if (jffs2_sum_active()) {
int res;
@@ -26,15 +114,31 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
}
}
- return mtd_writev(c->mtd, vecs, count, to, retlen);
+ ret = mtd_writev(c->mtd, vecs, count, to, retlen);
+
+ if (ret) {
+ pr_warn("%s(): Write failed with %d\n", __func__, ret);
+ } else {
+ size_t totlen = 0;
+ unsigned long i;
+
+ for (i = 0; i < count; i++)
+ totlen += vecs[i].iov_len;
+ if (*retlen != totlen) {
+ pr_warn("%s(): Write was short: %zu instead of %zu\n",
+ __func__, *retlen, totlen);
+ ret = -EIO;
+ } else
+ ret = jffs2_verify_writev(c, vecs, count, to);
+ }
+
+ return ret;
}
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf)
{
int ret;
- ret = mtd_write(c->mtd, ofs, len, retlen, buf);
-
if (jffs2_sum_active()) {
struct kvec vecs[1];
int res;
@@ -47,5 +151,17 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
return res;
}
}
+
+ ret = mtd_write(c->mtd, ofs, len, retlen, buf);
+
+ if (ret) {
+ pr_warn("%s(): Write failed with %d\n", __func__, ret);
+ } else if (*retlen != len) {
+ pr_warn("%s(): Write was short: %zu instead of %zu\n",
+ __func__, *retlen, len);
+ ret = -EIO;
+ } else
+ ret = jffs2_verify_write(c, buf, ofs, len);
+
return ret;
}
--
2.52.0
WARNING: multiple messages have this Message-ID (diff)
From: zhouminqiang <zhouminqiang2@huawei.com>
To: <dwmw2@infradead.org>, <richard@nod.at>
Cc: <linux-mtd@lists.infradead.org>, <linux-kernel@vger.kernel.org>,
<chengzhihao1@huawei.com>, <yangerkun@huawei.com>,
<yi.zhang@huawei.com>
Subject: [PATCH 4/6] jffs2: add write verification to NOR direct write paths
Date: Thu, 20 Aug 2026 18:50:00 +0800 [thread overview]
Message-ID: <20260820105003.2525647-5-zhouminqiang2@huawei.com> (raw)
In-Reply-To: <20260820105003.2525647-1-zhouminqiang2@huawei.com>
NOR Flash and other non-writebuffered devices write directly through
jffs2_flash_direct_writev() and jffs2_flash_direct_write() without
any write-back verification. If mtd_write() succeeds but the readable
medium differs from JFFS2's source buffer, a later node CRC failure
cannot distinguish transport/program-time corruption from post-commit
media damage.
Move jffs2_verify_write() from wbuf.c to writev.c so it can be
shared by both writebuffered and direct write paths. Add
jffs2_verify_writev() to iterate over kvec entries and verify each
one individually. In both direct write functions, add mtd_write()
return value and retlen checks, and invoke verification after
a successful complete write.
Signed-off-by: zhouminqiang <zhouminqiang2@huawei.com>
---
fs/jffs2/os-linux.h | 11 ++++
fs/jffs2/wbuf.c | 69 -------------------------
fs/jffs2/writev.c | 122 ++++++++++++++++++++++++++++++++++++++++++--
3 files changed, 130 insertions(+), 72 deletions(-)
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h
index 86ab014a349c..e73ef643fd97 100644
--- a/fs/jffs2/os-linux.h
+++ b/fs/jffs2/os-linux.h
@@ -192,6 +192,17 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf);
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+ uint32_t ofs, size_t len);
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+ const struct kvec *vecs,
+ unsigned long count, loff_t to);
+#else
+#define jffs2_verify_write(c, b, o, l) (0)
+#define jffs2_verify_writev(c, v, cnt, t) (0)
+#endif
+
#endif /* __JFFS2_OS_LINUX_H__ */
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 3e99587f40e4..493be5765c47 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -15,7 +15,6 @@
#include <linux/kernel.h>
#include <linux/slab.h>
-#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include <linux/crc32.h>
#include <linux/mtd/rawnand.h>
@@ -227,74 +226,6 @@ static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info
return NULL;
}
-#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
-static int jffs2_verify_write(struct jffs2_sb_info *c, unsigned char *buf,
- uint32_t ofs, size_t len)
-{
- int ret = 0;
- size_t retlen, i;
- char *eccstr;
- void *verify_buf;
-
- verify_buf = __vmalloc(len, GFP_NOFS);
- if (!verify_buf) {
- pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
- __func__);
- return 0;
- }
-
- ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
- if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
- pr_warn("%s(): Read back of page at %08x failed: %d\n",
- __func__, ofs, ret);
- goto out_free;
- } else if (retlen != len) {
- pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
- __func__, ofs, retlen, len);
- ret = -EIO;
- goto out_free;
- }
-
- for (i = 0; i < len; i++) {
- uint8_t c1 = ((uint8_t *)buf)[i];
- uint8_t c2 = ((uint8_t *)verify_buf)[i];
- int dump_len;
-
- if (c1 == c2)
- continue;
-
- if (ret == -EUCLEAN)
- eccstr = "corrected";
- else if (ret == -EBADMSG)
- eccstr = "correction failed";
- else
- eccstr = "OK or unused";
-
- dump_len = min_t(int, 128, len - i);
- pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
- eccstr, ofs, i, len);
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
- buf + i, dump_len, 0);
-
- pr_warn("Read back:\n");
- print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
- verify_buf + i, dump_len, 0);
-
- ret = -EIO;
- goto out_free;
- }
-
- vfree(verify_buf);
- return 0;
-
-out_free:
- vfree(verify_buf);
- return ret;
-}
-#else
-#define jffs2_verify_write(c,b,o,l) (0)
-#endif
-
/* Recover from failure to write wbuf. Recover the nodes up to the
* wbuf, not the one which we were starting to try to write. */
diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c
index a1bda9dab3f8..39adc15ffd69 100644
--- a/fs/jffs2/writev.c
+++ b/fs/jffs2/writev.c
@@ -10,12 +10,100 @@
*/
#include <linux/kernel.h>
+#include <linux/vmalloc.h>
#include <linux/mtd/mtd.h>
#include "nodelist.h"
+#ifdef CONFIG_JFFS2_FS_WBUF_VERIFY
+int jffs2_verify_write(struct jffs2_sb_info *c, const unsigned char *buf,
+ uint32_t ofs, size_t len)
+{
+ int ret = 0;
+ size_t retlen, i;
+ char *eccstr;
+ void *verify_buf;
+
+ verify_buf = __vmalloc(len, GFP_NOFS);
+ if (!verify_buf) {
+ pr_warn("%s(): verify buffer allocation failed, skipping verification\n",
+ __func__);
+ return 0;
+ }
+
+ ret = mtd_read(c->mtd, ofs, len, &retlen, verify_buf);
+ if (ret && ret != -EUCLEAN && ret != -EBADMSG) {
+ pr_warn("%s(): Read back of page at %08x failed: %d\n",
+ __func__, ofs, ret);
+ goto out_free;
+ } else if (retlen != len) {
+ pr_warn("%s(): Read back of page at %08x gave short read: %zu not %zu\n",
+ __func__, ofs, retlen, len);
+ ret = -EIO;
+ goto out_free;
+ }
+
+ for (i = 0; i < len; i++) {
+ uint8_t c1 = ((uint8_t *)buf)[i];
+ uint8_t c2 = ((uint8_t *)verify_buf)[i];
+ int dump_len;
+
+ if (c1 == c2)
+ continue;
+
+ if (ret == -EUCLEAN)
+ eccstr = "corrected";
+ else if (ret == -EBADMSG)
+ eccstr = "correction failed";
+ else
+ eccstr = "OK or unused";
+
+ dump_len = min_t(int, 128, len - i);
+ pr_warn("Write verify error (ECC %s) at %08x (+%zu/%zu). Wrote:\n",
+ eccstr, ofs, i, len);
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ buf + i, dump_len, 0);
+
+ pr_warn("Read back:\n");
+ print_hex_dump(KERN_WARNING, "", DUMP_PREFIX_OFFSET, 16, 1,
+ verify_buf + i, dump_len, 0);
+
+ ret = -EIO;
+ goto out_free;
+ }
+
+ vfree(verify_buf);
+ return 0;
+
+out_free:
+ vfree(verify_buf);
+ return ret;
+}
+
+int jffs2_verify_writev(struct jffs2_sb_info *c,
+ const struct kvec *vecs,
+ unsigned long count, loff_t to)
+{
+ loff_t ofs = to;
+ unsigned long i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ if (!vecs[i].iov_len)
+ continue;
+ ret = jffs2_verify_write(c, vecs[i].iov_base, ofs,
+ vecs[i].iov_len);
+ if (ret)
+ return ret;
+ ofs += vecs[i].iov_len;
+ }
+ return 0;
+}
+#endif /* CONFIG_JFFS2_FS_WBUF_VERIFY */
+
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen)
{
+ int ret;
if (!jffs2_is_writebuffered(c)) {
if (jffs2_sum_active()) {
int res;
@@ -26,15 +114,31 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs,
}
}
- return mtd_writev(c->mtd, vecs, count, to, retlen);
+ ret = mtd_writev(c->mtd, vecs, count, to, retlen);
+
+ if (ret) {
+ pr_warn("%s(): Write failed with %d\n", __func__, ret);
+ } else {
+ size_t totlen = 0;
+ unsigned long i;
+
+ for (i = 0; i < count; i++)
+ totlen += vecs[i].iov_len;
+ if (*retlen != totlen) {
+ pr_warn("%s(): Write was short: %zu instead of %zu\n",
+ __func__, *retlen, totlen);
+ ret = -EIO;
+ } else
+ ret = jffs2_verify_writev(c, vecs, count, to);
+ }
+
+ return ret;
}
int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
size_t *retlen, const u_char *buf)
{
int ret;
- ret = mtd_write(c->mtd, ofs, len, retlen, buf);
-
if (jffs2_sum_active()) {
struct kvec vecs[1];
int res;
@@ -47,5 +151,17 @@ int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len,
return res;
}
}
+
+ ret = mtd_write(c->mtd, ofs, len, retlen, buf);
+
+ if (ret) {
+ pr_warn("%s(): Write failed with %d\n", __func__, ret);
+ } else if (*retlen != len) {
+ pr_warn("%s(): Write was short: %zu instead of %zu\n",
+ __func__, *retlen, len);
+ ret = -EIO;
+ } else
+ ret = jffs2_verify_write(c, buf, ofs, len);
+
return ret;
}
--
2.52.0
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2026-08-20 10:57 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-20 10:49 [PATCH 0/6] jffs2: extend write verification to all write paths zhouminqiang
2026-08-20 10:49 ` zhouminqiang
2026-08-20 10:49 ` [PATCH 1/6] jffs2: replace per-superblock verify buffer with per-write buffer zhouminqiang
2026-08-20 10:49 ` zhouminqiang
2026-08-20 10:49 ` [PATCH 2/6] jffs2: write verify: replace memcmp with byte-by-byte comparison zhouminqiang
2026-08-20 10:49 ` zhouminqiang
2026-08-20 10:49 ` [PATCH 3/6] jffs2: add write verification to direct page writes in flash_writev zhouminqiang
2026-08-20 10:49 ` zhouminqiang
2026-08-20 10:50 ` zhouminqiang [this message]
2026-08-20 10:50 ` [PATCH 4/6] jffs2: add write verification to NOR direct write paths zhouminqiang
2026-08-20 10:50 ` [PATCH 5/6] jffs2: rename CONFIG_JFFS2_FS_WBUF_VERIFY to CONFIG_JFFS2_FS_WRITE_VERIFY zhouminqiang
2026-08-20 10:50 ` zhouminqiang
2026-08-20 10:50 ` [PATCH 6/6] jffs2: add runtime toggle for write verification zhouminqiang
2026-08-20 10:50 ` zhouminqiang
2026-08-20 18:58 ` [PATCH 0/6] jffs2: extend write verification to all write paths Richard Weinberger
2026-08-20 18:58 ` Richard Weinberger
2026-08-20 20:46 ` David Woodhouse
2026-08-20 20:46 ` David Woodhouse
2026-08-21 3:37 ` zhouminqiang
2026-08-21 3:37 ` zhouminqiang
2026-08-21 6:31 ` Richard Weinberger
2026-08-21 6:31 ` Richard Weinberger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260820105003.2525647-5-zhouminqiang2@huawei.com \
--to=zhouminqiang2@huawei.com \
--cc=chengzhihao1@huawei.com \
--cc=dwmw2@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=richard@nod.at \
--cc=yangerkun@huawei.com \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.