[openwrt/openwrt] kernel: support FIT partition parser on mtdblock devices

LEDE Commits lede-commits at lists.infradead.org
Fri Apr 9 16:05:23 BST 2021


dangole pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/2809d0000744b77d5b6cef20f6d44eed75c35e6a

commit 2809d0000744b77d5b6cef20f6d44eed75c35e6a
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Sat Apr 3 00:41:30 2021 +0100

    kernel: support FIT partition parser on mtdblock devices
    
    Allow using the FIT block-device partition partition parser to work on
    top of mtdblock devices.
    This is more tricky than it sounds as it requires to reorganize the
    procedure of registering mtdblock devices in order to avoid locking
    troubles caused by the block partition parsers then trying to open
    the mtdblock device for reading while locks are still being held.
    Fix that by moving the adding of the disks after the entire device
    has been probed when locks no longer need to be held.
    Also address issue with mtdsuper surfaced when using sub-partitions
    which prevented mounting JFFS2 using the /dev/mtdblock* device.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 target/linux/generic/files/block/partitions/fit.c  |  17 ++--
 ...uper-don-t-reply-on-mtdblock-device-minor.patch |  85 +++++++++++++++++
 ...-blktrans-call-add-disks-after-mtd-device.patch | 103 +++++++++++++++++++++
 ....patch => 410-block-fit-partition-parser.patch} |  48 +++++++++-
 4 files changed, 241 insertions(+), 12 deletions(-)

diff --git a/target/linux/generic/files/block/partitions/fit.c b/target/linux/generic/files/block/partitions/fit.c
index c0d9642505..823ee715de 100644
--- a/target/linux/generic/files/block/partitions/fit.c
+++ b/target/linux/generic/files/block/partitions/fit.c
@@ -112,20 +112,19 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector,
 		dsectors = (dsectors>sectors)?sectors:dsectors;
 
 	dsize = dsectors << SECTOR_SHIFT;
-	printk(KERN_DEBUG "FIT: volume size: %llu sectors (%llu bytes)\n", dsectors, dsize);
 
 	size = fdt_totalsize(init_fit);
-	printk(KERN_DEBUG "FIT: FDT structure size: %u bytes\n", size);
+
+	/* silently skip non-external-data legacy FIT images */
 	if (size > PAGE_SIZE) {
-		printk(KERN_ERR "FIT: FDT structure beyond page boundaries, use 'mkimage -E ...'!\n");
 		put_page(page);
-		return -ENOTSUPP;
+		return 0;
 	}
 
 	if (size >= dsize) {
+		state->access_beyond_eod = 1;
 		put_page(page);
-		state->access_beyond_eod = (size >= dsize);
-		return 0;
+		return -EFBIG;
 	}
 
 	fit = kmemdup(init_fit, size, GFP_KERNEL);
@@ -158,7 +157,7 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector,
 	config_description = fdt_getprop(fit, node, FIT_DESC_PROP, &config_description_len);
 	config_loadables = fdt_getprop(fit, node, FIT_LOADABLE_PROP, &config_loadables_len);
 
-	printk(KERN_DEBUG "FIT: Default configuration: %s%s%s%s\n", config_default,
+	printk(KERN_DEBUG "FIT: Default configuration: \"%s\"%s%s%s\n", config_default,
 		config_description?" (":"", config_description?:"", config_description?")":"");
 
 	images = fdt_path_offset(fit, FIT_IMAGES_PATH);
@@ -190,7 +189,7 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector,
 
 		image_description = fdt_getprop(fit, node, FIT_DESC_PROP, &image_description_len);
 
-		printk(KERN_DEBUG "FIT: %16s sub-image 0x%08x - 0x%08x '%s' %s%s%s\n",
+		printk(KERN_DEBUG "FIT: %16s sub-image 0x%08x - 0x%08x \"%s\" %s%s%s\n",
 			image_type, image_pos, image_pos + image_len, image_name,
 			image_description?"(":"", image_description?:"", image_description?") ":"");
 
@@ -230,7 +229,7 @@ int parse_fit_partitions(struct parsed_partitions *state, u64 fit_start_sector,
 		state->parts[*slot].has_info = true;
 
 		if (config_loadables && !strcmp(image_name, config_loadables)) {
-			printk(KERN_DEBUG "FIT: selecting configured loadable %s to be root filesystem\n", image_name);
+			printk(KERN_DEBUG "FIT: selecting configured loadable \"%s\" to be root filesystem\n", image_name);
 			state->parts[*slot].flags |= ADDPART_FLAG_ROOTDEV;
 		}
 	}
diff --git a/target/linux/generic/hack-5.10/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch b/target/linux/generic/hack-5.10/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch
new file mode 100644
index 0000000000..04cf52b096
--- /dev/null
+++ b/target/linux/generic/hack-5.10/401-mtd-super-don-t-reply-on-mtdblock-device-minor.patch
@@ -0,0 +1,85 @@
+From f9760b158f610b1792a222cc924073724c061bfb Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Wed, 7 Apr 2021 22:37:57 +0100
+Subject: [PATCH 1/2] mtd: super: don't reply on mtdblock device minor
+To: linux-mtd at lists.infradead.org
+Cc: Vignesh Raghavendra <vigneshr at ti.com>,
+    Richard Weinberger <richard at nod.at>,
+    Miquel Raynal <miquel.raynal at bootlin.com>,
+    David Woodhouse <dwmw2 at infradead.org>
+
+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>
+---
+ drivers/mtd/mtdsuper.c | 33 ++++++++++++++++++++++++++-------
+ 1 file changed, 26 insertions(+), 7 deletions(-)
+
+--- 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>
+@@ -121,7 +122,8 @@ int get_tree_mtd(struct fs_context *fc,
+ {
+ #ifdef CONFIG_BLOCK
+ 	struct block_device *bdev;
+-	int ret, major;
++	struct mtd_blktrans_dev *blktrans_dev;
++	int ret, major, part_bits;
+ #endif
+ 	int mtdnr;
+ 
+@@ -169,21 +171,38 @@ 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
+ 	 */
+-	bdev = lookup_bdev(fc->source);
++	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");
+ 
+ 	major = MAJOR(bdev->bd_dev);
+-	mtdnr = MINOR(bdev->bd_dev);
+-	bdput(bdev);
+ 
+-	if (major == MTD_BLOCK_MAJOR)
+-		return mtd_get_sb_by_nr(fc, mtdnr, fill_super);
++	if (major == MTD_BLOCK_MAJOR) {
++		if (!bdev->bd_disk) {
++			blkdev_put(bdev, FMODE_READ);
++			BUG();
++			return -EINVAL;
++		}
++
++		blktrans_dev = (struct mtd_blktrans_dev *)(bdev->bd_disk->private_data);
++		if (!blktrans_dev || !blktrans_dev->tr) {
++			blkdev_put(bdev, FMODE_READ);
++			BUG();
++			return -EINVAL;
++		}
++		mtdnr = blktrans_dev->devnum;
++		part_bits = blktrans_dev->tr->part_bits;
++		blkdev_put(bdev, FMODE_READ);
++		if (MINOR(bdev->bd_dev) != (mtdnr << part_bits))
++			return -EINVAL;
+ 
++		return mtd_get_sb_by_nr(fc, mtdnr, fill_super);
++	}
++	blkdev_put(bdev, FMODE_READ);
+ #endif /* CONFIG_BLOCK */
+ 
+ 	if (!(fc->sb_flags & SB_SILENT))
diff --git a/target/linux/generic/hack-5.10/402-mtd-blktrans-call-add-disks-after-mtd-device.patch b/target/linux/generic/hack-5.10/402-mtd-blktrans-call-add-disks-after-mtd-device.patch
new file mode 100644
index 0000000000..bc9e84cac1
--- /dev/null
+++ b/target/linux/generic/hack-5.10/402-mtd-blktrans-call-add-disks-after-mtd-device.patch
@@ -0,0 +1,103 @@
+From 0bccc3722bdd88e8ae995e77ef9f7b77ee4cbdee Mon Sep 17 00:00:00 2001
+From: Daniel Golle <daniel at makrotopia.org>
+Date: Wed, 7 Apr 2021 22:45:54 +0100
+Subject: [PATCH 2/2] mtd: blktrans: call add disks after mtd device
+To: linux-mtd at lists.infradead.org
+Cc: Vignesh Raghavendra <vigneshr at ti.com>,
+    Richard Weinberger <richard at nod.at>,
+    Miquel Raynal <miquel.raynal at bootlin.com>,
+    David Woodhouse <dwmw2 at infradead.org>
+
+Calling device_add_disk while holding mtd_table_mutex leads
+to deadlock in case part_bits!=0 as block partition parsers
+will try to open the newly created disks, trying to acquire
+mutex once again.
+Move device_add_disk to additional function called after
+add partitions of an MTD device have been added and locks
+have been released.
+
+Signed-off-by: Daniel Golle <daniel at makrotopia.org>
+---
+ drivers/mtd/mtd_blkdevs.c    | 33 ++++++++++++++++++++++++++-------
+ drivers/mtd/mtdcore.c        |  3 +++
+ include/linux/mtd/blktrans.h |  1 +
+ 3 files changed, 30 insertions(+), 7 deletions(-)
+
+--- a/drivers/mtd/mtd_blkdevs.c
++++ b/drivers/mtd/mtd_blkdevs.c
+@@ -457,13 +457,6 @@ int add_mtd_blktrans_dev(struct mtd_blkt
+ 	if (new->readonly)
+ 		set_disk_ro(gd, 1);
+ 
+-	device_add_disk(&new->mtd->dev, gd, NULL);
+-
+-	if (new->disk_attributes) {
+-		ret = sysfs_create_group(&disk_to_dev(gd)->kobj,
+-					new->disk_attributes);
+-		WARN_ON(ret);
+-	}
+ 	return 0;
+ error4:
+ 	kfree(new->tag_set);
+@@ -475,6 +468,32 @@ error1:
+ 	return ret;
+ }
+ 
++void register_mtd_blktrans_devs(struct mtd_info *mtd)
++{
++	struct mtd_blktrans_ops *tr;
++	struct mtd_blktrans_dev *dev, *next;
++	struct mtd_info *top_mtd;
++	int ret;
++
++	list_for_each_entry(tr, &blktrans_majors, list) {
++		list_for_each_entry_safe(dev, next, &tr->devs, list) {
++			top_mtd = dev->mtd;
++			while (top_mtd->parent)
++				top_mtd = top_mtd->parent;
++
++			if (mtd->index != top_mtd->index)
++				continue;
++
++			device_add_disk(&dev->mtd->dev, dev->disk, NULL);
++			if (dev->disk_attributes) {
++				ret = sysfs_create_group(&disk_to_dev(dev->disk)->kobj,
++							dev->disk_attributes);
++				WARN_ON(ret);
++			}
++		}
++	}
++}
++
+ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old)
+ {
+ 	unsigned long flags;
+--- a/drivers/mtd/mtdcore.c
++++ b/drivers/mtd/mtdcore.c
+@@ -32,6 +32,7 @@
+ 
+ #include <linux/mtd/mtd.h>
+ #include <linux/mtd/partitions.h>
++#include <linux/mtd/blktrans.h>
+ 
+ #include "mtdcore.h"
+ 
+@@ -858,6 +859,8 @@ int mtd_device_parse_register(struct mtd
+ 		register_reboot_notifier(&mtd->reboot_notifier);
+ 	}
+ 
++	register_mtd_blktrans_devs(mtd);
++
+ out:
+ 	if (ret && device_is_registered(&mtd->dev))
+ 		del_mtd_device(mtd);
+--- a/include/linux/mtd/blktrans.h
++++ b/include/linux/mtd/blktrans.h
+@@ -76,6 +76,7 @@ extern int deregister_mtd_blktrans(struc
+ extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+ extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev);
+ extern int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev);
++extern void register_mtd_blktrans_devs(struct mtd_info *mtd);
+ 
+ 
+ #endif /* __MTD_TRANS_H__ */
diff --git a/target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch b/target/linux/generic/hack-5.10/410-block-fit-partition-parser.patch
similarity index 81%
rename from target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch
rename to target/linux/generic/hack-5.10/410-block-fit-partition-parser.patch
index a414be6e84..2528f3afa1 100644
--- a/target/linux/generic/hack-5.10/400-block-fit-partition-parser.patch
+++ b/target/linux/generic/hack-5.10/410-block-fit-partition-parser.patch
@@ -122,20 +122,25 @@
  
 --- a/drivers/mtd/ubi/block.c
 +++ b/drivers/mtd/ubi/block.c
-@@ -396,7 +396,7 @@ int ubiblock_create(struct ubi_volume_in
+@@ -396,7 +396,11 @@ int ubiblock_create(struct ubi_volume_in
  	dev->leb_size = vi->usable_leb_size;
  
  	/* Initialize the gendisk of this ubiblock device */
--	gd = alloc_disk(1);
++#ifdef CONFIG_FIT_PARTITION
 +	gd = alloc_disk(0);
++#else
+ 	gd = alloc_disk(1);
++#endif
  	if (!gd) {
  		pr_err("UBI: block: alloc_disk failed\n");
  		ret = -ENODEV;
-@@ -413,6 +413,7 @@ int ubiblock_create(struct ubi_volume_in
+@@ -413,6 +417,9 @@ int ubiblock_create(struct ubi_volume_in
  		goto out_put_disk;
  	}
  	gd->private_data = dev;
++#ifdef CONFIG_FIT_PARTITION
 +	gd->flags |= GENHD_FL_EXT_DEVT;
++#endif
  	sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
  	set_capacity(gd, disk_capacity);
  	dev->gd = gd;
@@ -175,3 +180,40 @@
  
  typedef struct _gpt_header {
  	__le64 signature;
+--- a/drivers/mtd/mtdblock.c
++++ b/drivers/mtd/mtdblock.c
+@@ -334,7 +334,11 @@ static void mtdblock_remove_dev(struct m
+ static struct mtd_blktrans_ops mtdblock_tr = {
+ 	.name		= "mtdblock",
+ 	.major		= MTD_BLOCK_MAJOR,
++#ifdef CONFIG_FIT_PARTITION
++	.part_bits	= 1,
++#else
+ 	.part_bits	= 0,
++#endif
+ 	.blksize 	= 512,
+ 	.open		= mtdblock_open,
+ 	.flush		= mtdblock_flush,
+--- a/drivers/mtd/mtd_blkdevs.c
++++ b/drivers/mtd/mtd_blkdevs.c
+@@ -407,18 +407,8 @@ int add_mtd_blktrans_dev(struct mtd_blkt
+ 	gd->first_minor = (new->devnum) << tr->part_bits;
+ 	gd->fops = &mtd_block_ops;
+ 
+-	if (tr->part_bits)
+-		if (new->devnum < 26)
+-			snprintf(gd->disk_name, sizeof(gd->disk_name),
+-				 "%s%c", tr->name, 'a' + new->devnum);
+-		else
+-			snprintf(gd->disk_name, sizeof(gd->disk_name),
+-				 "%s%c%c", tr->name,
+-				 'a' - 1 + new->devnum / 26,
+-				 'a' + new->devnum % 26);
+-	else
+-		snprintf(gd->disk_name, sizeof(gd->disk_name),
+-			 "%s%d", tr->name, new->devnum);
++	snprintf(gd->disk_name, sizeof(gd->disk_name),
++		 "%s%d", tr->name, new->devnum);
+ 
+ 	set_capacity(gd, ((u64)new->size * tr->blksize) >> 9);
+ 



More information about the lede-commits mailing list