LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v2 0/2] mtd: mtdconcat: Fix callback functions check
@ 2021-08-17 11:48 Zhihao Cheng
2021-08-17 11:48 ` [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master Zhihao Cheng
2021-08-17 11:48 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read,_write callbacks existence before assignment Zhihao Cheng
0 siblings, 2 replies; 5+ messages in thread
From: Zhihao Cheng @ 2021-08-17 11:48 UTC (permalink / raw)
To: miquel.raynal, richard, vigneshr, bbrezillon
Cc: linux-mtd, linux-kernel, chengzhihao1, yukuai3
Patch 1: Check subdev's master mtd device's callback function while
making concatenated device.
Patch 2: Check existence of _read|_write callback before assigning
them to concatenated device.
v1->v2:
Shorten two commit titles.
Patch 1: Add comment to explain why datamember checks for subdev
but callbacks checks for master device
Patch 1: Fix misspelled word, "comnoine fail" -> "combine failed"
Patch 2: Fix wrong commit message, "Since ... time. We should"
Patch 2: Check against the existence of _read|_read_oob callbacks
by master, no removing concat_{read|write}_oob.
Zhihao Cheng (2):
mtd: mtdconcat: Judge callback existence based on the master
mtd: mtdconcat: Check _read,_write callbacks existence before
assignment
drivers/mtd/mtdconcat.c | 33 +++++++++++++++++++++++----------
1 file changed, 23 insertions(+), 10 deletions(-)
--
2.31.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master
2021-08-17 11:48 [PATCH v2 0/2] mtd: mtdconcat: Fix callback functions check Zhihao Cheng
@ 2021-08-17 11:48 ` Zhihao Cheng
2021-08-17 16:49 ` Miquel Raynal
2021-08-17 11:48 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read,_write callbacks existence before assignment Zhihao Cheng
1 sibling, 1 reply; 5+ messages in thread
From: Zhihao Cheng @ 2021-08-17 11:48 UTC (permalink / raw)
To: miquel.raynal, richard, vigneshr, bbrezillon
Cc: linux-mtd, linux-kernel, chengzhihao1, yukuai3
Since commit 46b5889cc2c5("mtd: implement proper partition handling")
applied, mtd partition device won't hold some callback functions, such
as _block_isbad, _block_markbad, etc. Besides, function mtd_block_isbad()
will get mtd device's master mtd device, then invokes master mtd device's
callback function. So, following process may result mtd_block_isbad()
always return 0, even though mtd device has bad blocks:
1. Split a mtd device into 3 partitions: PA, PB, PC
[ Each mtd partition device won't has callback function _block_isbad(). ]
2. Concatenate PA and PB as a new mtd device PN
[ mtd_concat_create() finds out each subdev has no callback function
_block_isbad(), so PN won't be assigned callback function
concat_block_isbad(). ]
Then, mtd_block_isbad() checks "!master->_block_isbad" is true, will
always return 0.
Reproducer:
// reproduce.c
static int __init init_diy_module(void)
{
struct mtd_info *mtd[2];
struct mtd_info *mtd_combine = NULL;
mtd[0] = get_mtd_device_nm("NAND simulator partition 0");
if (!mtd[0]) {
pr_err("cannot find mtd1\n");
return -EINVAL;
}
mtd[1] = get_mtd_device_nm("NAND simulator partition 1");
if (!mtd[1]) {
pr_err("cannot find mtd2\n");
return -EINVAL;
}
put_mtd_device(mtd[0]);
put_mtd_device(mtd[1]);
mtd_combine = mtd_concat_create(mtd, 2, "Combine mtd");
if (mtd_combine == NULL) {
pr_err("combine failed\n");
return -EINVAL;
}
mtd_device_register(mtd_combine, NULL, 0);
pr_info("Combine success\n");
return 0;
}
1. ID="0x20,0xac,0x00,0x15"
2. modprobe nandsim id_bytes=$ID parts=50,100 badblocks=100
3. insmod reproduce.ko
4. flash_erase /dev/mtd3 0 0
libmtd: error!: MEMERASE64 ioctl failed for eraseblock 100 (mtd3)
error 5 (Input/output error)
// Should be "flash_erase: Skipping bad block at 00c80000"
Fixes: 46b5889cc2c54bac ("mtd: implement proper partition handling")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
drivers/mtd/mtdconcat.c | 27 +++++++++++++++++++--------
1 file changed, 19 insertions(+), 8 deletions(-)
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index 6e4d0017c0bd..af51eee6b5e8 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -641,6 +641,7 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
int i;
size_t size;
struct mtd_concat *concat;
+ struct mtd_info *subdev_master = NULL;
uint32_t max_erasesize, curr_erasesize;
int num_erase_region;
int max_writebufsize = 0;
@@ -679,17 +680,19 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.subpage_sft = subdev[0]->subpage_sft;
concat->mtd.oobsize = subdev[0]->oobsize;
concat->mtd.oobavail = subdev[0]->oobavail;
- if (subdev[0]->_writev)
+
+ subdev_master = mtd_get_master(subdev[0]);
+ if (subdev_master->_writev)
concat->mtd._writev = concat_writev;
- if (subdev[0]->_read_oob)
+ if (subdev_master->_read_oob)
concat->mtd._read_oob = concat_read_oob;
- if (subdev[0]->_write_oob)
+ if (subdev_master->_write_oob)
concat->mtd._write_oob = concat_write_oob;
- if (subdev[0]->_block_isbad)
+ if (subdev_master->_block_isbad)
concat->mtd._block_isbad = concat_block_isbad;
- if (subdev[0]->_block_markbad)
+ if (subdev_master->_block_markbad)
concat->mtd._block_markbad = concat_block_markbad;
- if (subdev[0]->_panic_write)
+ if (subdev_master->_panic_write)
concat->mtd._panic_write = concat_panic_write;
concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
@@ -721,14 +724,22 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
subdev[i]->flags & MTD_WRITEABLE;
}
+ subdev_master = mtd_get_master(subdev[i]);
concat->mtd.size += subdev[i]->size;
concat->mtd.ecc_stats.badblocks +=
subdev[i]->ecc_stats.badblocks;
if (concat->mtd.writesize != subdev[i]->writesize ||
concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
concat->mtd.oobsize != subdev[i]->oobsize ||
- !concat->mtd._read_oob != !subdev[i]->_read_oob ||
- !concat->mtd._write_oob != !subdev[i]->_write_oob) {
+ !concat->mtd._read_oob != !subdev_master->_read_oob ||
+ !concat->mtd._write_oob != !subdev_master->_write_oob) {
+ /*
+ * Check against subdev[i] for data members, because
+ * subdev's attributes may be different from master
+ * mtd device. Check against subdev's master mtd
+ * device for callbacks, because the existence of
+ * subdev's callbacks is decided by master mtd device.
+ */
kfree(concat);
printk("Incompatible OOB or ECC data on \"%s\"\n",
subdev[i]->name);
--
2.31.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] mtd: mtdconcat: Check _read,_write callbacks existence before assignment
2021-08-17 11:48 [PATCH v2 0/2] mtd: mtdconcat: Fix callback functions check Zhihao Cheng
2021-08-17 11:48 ` [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master Zhihao Cheng
@ 2021-08-17 11:48 ` Zhihao Cheng
2021-08-17 16:49 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read, _write " Miquel Raynal
1 sibling, 1 reply; 5+ messages in thread
From: Zhihao Cheng @ 2021-08-17 11:48 UTC (permalink / raw)
To: miquel.raynal, richard, vigneshr, bbrezillon
Cc: linux-mtd, linux-kernel, chengzhihao1, yukuai3
Since 2431c4f5b46c3 ("mtd: Implement mtd_{read,write}() as wrappers
around mtd_{read,write}_oob()") don't allow _write|_read and
_write_oob|_read_oob existing at the same time, we should check the
existence of callbacks "_read and _write" from subdev's master device
(We can trust master device since it has been registered) before
assigning, otherwise following warning occurs while making
concatenated device:
WARNING: CPU: 2 PID: 6728 at drivers/mtd/mtdcore.c:595
add_mtd_device+0x7f/0x7b0
Fixes: 2431c4f5b46c3 ("mtd: Implement mtd_{read,write}() around ...")
Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
---
drivers/mtd/mtdconcat.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
index af51eee6b5e8..f685a581df48 100644
--- a/drivers/mtd/mtdconcat.c
+++ b/drivers/mtd/mtdconcat.c
@@ -694,6 +694,10 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd._block_markbad = concat_block_markbad;
if (subdev_master->_panic_write)
concat->mtd._panic_write = concat_panic_write;
+ if (subdev_master->_read)
+ concat->mtd._read = concat_read;
+ if (subdev_master->_write)
+ concat->mtd._write = concat_write;
concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
@@ -755,8 +759,6 @@ struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to c
concat->mtd.name = name;
concat->mtd._erase = concat_erase;
- concat->mtd._read = concat_read;
- concat->mtd._write = concat_write;
concat->mtd._sync = concat_sync;
concat->mtd._lock = concat_lock;
concat->mtd._unlock = concat_unlock;
--
2.31.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] mtd: mtdconcat: Check _read, _write callbacks existence before assignment
2021-08-17 11:48 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read,_write callbacks existence before assignment Zhihao Cheng
@ 2021-08-17 16:49 ` Miquel Raynal
0 siblings, 0 replies; 5+ messages in thread
From: Miquel Raynal @ 2021-08-17 16:49 UTC (permalink / raw)
To: Zhihao Cheng, miquel.raynal, richard, vigneshr, bbrezillon
Cc: linux-mtd, linux-kernel, yukuai3
On Tue, 2021-08-17 at 11:48:57 UTC, Zhihao Cheng wrote:
> Since 2431c4f5b46c3 ("mtd: Implement mtd_{read,write}() as wrappers
> around mtd_{read,write}_oob()") don't allow _write|_read and
> _write_oob|_read_oob existing at the same time, we should check the
> existence of callbacks "_read and _write" from subdev's master device
> (We can trust master device since it has been registered) before
> assigning, otherwise following warning occurs while making
> concatenated device:
>
> WARNING: CPU: 2 PID: 6728 at drivers/mtd/mtdcore.c:595
> add_mtd_device+0x7f/0x7b0
>
> Fixes: 2431c4f5b46c3 ("mtd: Implement mtd_{read,write}() around ...")
> Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.
Miquel
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master
2021-08-17 11:48 ` [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master Zhihao Cheng
@ 2021-08-17 16:49 ` Miquel Raynal
0 siblings, 0 replies; 5+ messages in thread
From: Miquel Raynal @ 2021-08-17 16:49 UTC (permalink / raw)
To: Zhihao Cheng, miquel.raynal, richard, vigneshr, bbrezillon
Cc: linux-mtd, linux-kernel, yukuai3
On Tue, 2021-08-17 at 11:48:56 UTC, Zhihao Cheng wrote:
> Since commit 46b5889cc2c5("mtd: implement proper partition handling")
> applied, mtd partition device won't hold some callback functions, such
> as _block_isbad, _block_markbad, etc. Besides, function mtd_block_isbad()
> will get mtd device's master mtd device, then invokes master mtd device's
> callback function. So, following process may result mtd_block_isbad()
> always return 0, even though mtd device has bad blocks:
>
> 1. Split a mtd device into 3 partitions: PA, PB, PC
> [ Each mtd partition device won't has callback function _block_isbad(). ]
> 2. Concatenate PA and PB as a new mtd device PN
> [ mtd_concat_create() finds out each subdev has no callback function
> _block_isbad(), so PN won't be assigned callback function
> concat_block_isbad(). ]
> Then, mtd_block_isbad() checks "!master->_block_isbad" is true, will
> always return 0.
>
> Reproducer:
> // reproduce.c
> static int __init init_diy_module(void)
> {
> struct mtd_info *mtd[2];
> struct mtd_info *mtd_combine = NULL;
>
> mtd[0] = get_mtd_device_nm("NAND simulator partition 0");
> if (!mtd[0]) {
> pr_err("cannot find mtd1\n");
> return -EINVAL;
> }
> mtd[1] = get_mtd_device_nm("NAND simulator partition 1");
> if (!mtd[1]) {
> pr_err("cannot find mtd2\n");
> return -EINVAL;
> }
>
> put_mtd_device(mtd[0]);
> put_mtd_device(mtd[1]);
>
> mtd_combine = mtd_concat_create(mtd, 2, "Combine mtd");
> if (mtd_combine == NULL) {
> pr_err("combine failed\n");
> return -EINVAL;
> }
>
> mtd_device_register(mtd_combine, NULL, 0);
> pr_info("Combine success\n");
>
> return 0;
> }
>
> 1. ID="0x20,0xac,0x00,0x15"
> 2. modprobe nandsim id_bytes=$ID parts=50,100 badblocks=100
> 3. insmod reproduce.ko
> 4. flash_erase /dev/mtd3 0 0
> libmtd: error!: MEMERASE64 ioctl failed for eraseblock 100 (mtd3)
> error 5 (Input/output error)
> // Should be "flash_erase: Skipping bad block at 00c80000"
>
> Fixes: 46b5889cc2c54bac ("mtd: implement proper partition handling")
> Signed-off-by: Zhihao Cheng <chengzhihao1@huawei.com>
Applied to https://git.kernel.org/pub/scm/linux/kernel/git/mtd/linux.git mtd/next, thanks.
Miquel
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2021-08-17 16:49 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-17 11:48 [PATCH v2 0/2] mtd: mtdconcat: Fix callback functions check Zhihao Cheng
2021-08-17 11:48 ` [PATCH v2 1/2] mtd: mtdconcat: Judge callback existence based on the master Zhihao Cheng
2021-08-17 16:49 ` Miquel Raynal
2021-08-17 11:48 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read,_write callbacks existence before assignment Zhihao Cheng
2021-08-17 16:49 ` [PATCH v2 2/2] mtd: mtdconcat: Check _read, _write " Miquel Raynal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).