[PATCH] UBI: block: Add option for dynamic minor number
Dan Ehrenberg
dehrenberg at chromium.org
Mon Mar 16 13:55:15 PDT 2015
This patch adds a new config option, MTD_UBI_BLOCK_DYNAMIC_MINOR, which
makes minor numbers dynamically allocated for ubiblock devices, starting
at 0.
>From the new Kconfig:
This option makes ubiblock devices have minor numbers beginning from
0, allocated dynamically independently of the ubi device/volume
number. For users who don't refer to an ubiblock device directly by
the major:minor number (e.g., with udev and/or devtmpfs), this option
is useful if the device number is rather high (>1) and when executing
on a 32-bit platform without LFS enabled in all userspace binaries.
While enabling LFS is clearly a nicer solution, it's often difficult to turn
on in practice globally as many widely distributed packages don't work with
LFS on. While dev_t is 32-bit even without LFS, stat will return -EOVERFLOW
with a minor number which doesn't fit in 8 bits for ABI compatability reasons.
Other storage systems have their own workarounds, with SCSI making multiple
device majors and MMC having a config option for the number of partitions
per device. A completely dynamic minor numbering is simpler than these and
suitable for the majority of ubiblock users who don't depend on a minor
numbering (the major is dynamic anyway).
Signed-off-by: Dan Ehrenberg <dehrenberg at chromium.org>
---
drivers/mtd/ubi/Kconfig | 11 +++++++++++
drivers/mtd/ubi/block.c | 34 +++++++++++++++++++++++++++++++++-
2 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index f0855ce..c0e9a73 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -103,4 +103,15 @@ config MTD_UBI_BLOCK
If in doubt, say "N".
+config MTD_UBI_BLOCK_DYNAMIC_MINOR
+ bool "Dynamically allocate minor numbers for ubiblock"
+ default n
+ help
+ This option makes ubiblock devices have minor numbers beginning from
+ 0, allocated dynamically independently of the ubi device/volume
+ number. For users who don't refer to an ubiblock device directly by
+ the major:minor number (e.g., with udev and/or devtmpfs), this option
+ is useful if the device number is rather high (>1) and when executing
+ on a 32-bit platform without LFS.
+
endif # MTD_UBI
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index db2c05b..bcd164d 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -48,6 +48,7 @@
#include <linux/blk-mq.h>
#include <linux/hdreg.h>
#include <linux/scatterlist.h>
+#include <linux/idr.h>
#include <asm/div64.h>
#include "ubi-media.h"
@@ -351,6 +352,20 @@ static struct blk_mq_ops ubiblock_mq_ops = {
.map_queue = blk_mq_map_queue,
};
+#ifdef CONFIG_MTD_UBI_BLOCK_DYNAMIC_MINOR
+static DEFINE_IDR(ubiblock_minor_idr);
+
+static int ubiblock_alloc_minor(struct ubiblock *dev)
+{
+ return idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL);
+}
+
+static void ubiblock_remove_minor(int minor)
+{
+ idr_remove(&ubiblock_minor_idr, minor);
+}
+#endif
+
int ubiblock_create(struct ubi_volume_info *vi)
{
struct ubiblock *dev;
@@ -388,7 +403,17 @@ int ubiblock_create(struct ubi_volume_info *vi)
gd->fops = &ubiblock_ops;
gd->major = ubiblock_major;
+#ifdef CONFIG_MTD_UBI_BLOCK_DYNAMIC_MINOR
+ gd->first_minor = ubiblock_alloc_minor(dev);
+ if (gd->first_minor < 0) {
+ dev_err(disk_to_dev(gd),
+ "block: dynamic minor allocation failed");
+ ret = -ENODEV;
+ goto out_put_disk;
+ }
+#else
gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+#endif
gd->private_data = dev;
sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id);
set_capacity(gd, disk_capacity);
@@ -405,7 +430,7 @@ int ubiblock_create(struct ubi_volume_info *vi)
ret = blk_mq_alloc_tag_set(&dev->tag_set);
if (ret) {
dev_err(disk_to_dev(dev->gd), "blk_mq_alloc_tag_set failed");
- goto out_put_disk;
+ goto out_remove_minor;
}
dev->rq = blk_mq_init_queue(&dev->tag_set);
@@ -443,6 +468,10 @@ out_free_queue:
blk_cleanup_queue(dev->rq);
out_free_tags:
blk_mq_free_tag_set(&dev->tag_set);
+out_remove_minor:
+#ifdef CONFIG_MTD_UBI_BLOCK_DYNAMIC_MINOR
+ ubiblock_remove_minor(gd->first_minor);
+#endif
out_put_disk:
put_disk(dev->gd);
out_free_dev:
@@ -461,6 +490,9 @@ static void ubiblock_cleanup(struct ubiblock *dev)
blk_cleanup_queue(dev->rq);
blk_mq_free_tag_set(&dev->tag_set);
dev_info(disk_to_dev(dev->gd), "released");
+#ifdef CONFIG_MTD_UBI_BLOCK_DYNAMIC_MINOR
+ ubiblock_remove_minor(dev->gd->first_minor);
+#endif
put_disk(dev->gd);
}
--
2.2.0.rc0.207.ga3a616c
More information about the linux-mtd
mailing list