diff options
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/ubi/block.c | 16 |
1 files changed, 14 insertions, 2 deletions
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c index c9eb78f10a0d..1a92d30689e7 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" @@ -353,6 +354,8 @@ static struct blk_mq_ops ubiblock_mq_ops = { .map_queue = blk_mq_map_queue, }; +static DEFINE_IDR(ubiblock_minor_idr); + int ubiblock_create(struct ubi_volume_info *vi) { struct ubiblock *dev; @@ -390,7 +393,13 @@ int ubiblock_create(struct ubi_volume_info *vi) gd->fops = &ubiblock_ops; gd->major = ubiblock_major; - gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id; + gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); + if (gd->first_minor < 0) { + dev_err(disk_to_dev(gd), + "block: dynamic minor allocation failed"); + ret = -ENODEV; + goto out_put_disk; + } gd->private_data = dev; sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); set_capacity(gd, disk_capacity); @@ -407,7 +416,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); @@ -445,6 +454,8 @@ out_free_queue: blk_cleanup_queue(dev->rq); out_free_tags: blk_mq_free_tag_set(&dev->tag_set); +out_remove_minor: + idr_remove(&ubiblock_minor_idr, gd->first_minor); out_put_disk: put_disk(dev->gd); out_free_dev: @@ -463,6 +474,7 @@ 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"); + idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); put_disk(dev->gd); } |