[PATCH v4] mtd: super: don't rely on mtdblock device minor
Daniel Golle
daniel at makrotopia.org
Mon May 10 15:21:17 PDT 2021
For blktrans devices with partitions (ie. part_bits != 0) the
assumption that the minor number of the mtdblock device matches
the mtdnum doesn't hold true.
Properly resolve mtd device from blktrans layer instead.
Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
v4: rebase on v5.13-rc1, improve error handling
v3: fix typo in patch description
v2: remove BUG() calls as requested by Miquel Raynal
drivers/mtd/mtdsuper.c | 32 +++++++++++++++++++++++++-------
1 file changed, 25 insertions(+), 7 deletions(-)
diff --git a/drivers/mtd/mtdsuper.c b/drivers/mtd/mtdsuper.c
index 38b6aa849c638..40bb63e7bc7f6 100644
--- a/drivers/mtd/mtdsuper.c
+++ b/drivers/mtd/mtdsuper.c
@@ -9,6 +9,7 @@
*/
#include <linux/mtd/super.h>
+#include <linux/mtd/blktrans.h>
#include <linux/namei.h>
#include <linux/export.h>
#include <linux/ctype.h>
@@ -120,8 +121,9 @@ int get_tree_mtd(struct fs_context *fc,
struct fs_context *fc))
{
#ifdef CONFIG_BLOCK
- dev_t dev;
- int ret;
+ struct block_device *bdev;
+ struct mtd_blktrans_dev *blktrans_dev;
+ int ret, part_bits;
#endif
int mtdnr;
@@ -169,16 +171,32 @@ int get_tree_mtd(struct fs_context *fc,
/* try the old way - the hack where we allowed users to mount
* /dev/mtdblock$(n) but didn't actually _use_ the blockdev
*/
- ret = lookup_bdev(fc->source, &dev);
- if (ret) {
+ bdev = blkdev_get_by_path(fc->source, FMODE_READ, NULL);
+ if (IS_ERR(bdev)) {
+ ret = PTR_ERR(bdev);
errorf(fc, "MTD: Couldn't look up '%s': %d", fc->source, ret);
return ret;
}
- pr_debug("MTDSB: lookup_bdev() returned 0\n");
+ pr_debug("MTDSB: blkdev_get_by_path() returned 0\n");
+
+ if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
+ if (!bdev->bd_disk)
+ goto error_mtdblock;
- if (MAJOR(dev) == MTD_BLOCK_MAJOR)
- return mtd_get_sb_by_nr(fc, MINOR(dev), fill_super);
+ blktrans_dev = (struct mtd_blktrans_dev *)(bdev->bd_disk->private_data);
+ if (!blktrans_dev || !blktrans_dev->tr)
+ goto error_mtdblock;
+ mtdnr = blktrans_dev->devnum;
+ part_bits = blktrans_dev->tr->part_bits;
+ if (MINOR(bdev->bd_dev) != (mtdnr << part_bits))
+ goto error_mtdblock;
+
+ blkdev_put(bdev, FMODE_READ);
+ return mtd_get_sb_by_nr(fc, mtdnr, fill_super);
+ }
+error_mtdblock:
+ blkdev_put(bdev, FMODE_READ);
#endif /* CONFIG_BLOCK */
if (!(fc->sb_flags & SB_SILENT))
--
2.31.1
More information about the linux-mtd
mailing list