block: refactor device number setup in __device_add_disk

Untangle the mess around blk_alloc_devt by moving the check for
the used allocation scheme into the callers.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Luis Chamberlain <mcgrof@kernel.org>
Reviewed-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20210521055116.1053587-2-hch@lst.de
Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
Christoph Hellwig 2021-05-21 07:50:51 +02:00 committed by Jens Axboe
parent d97e594c51
commit 7c3f828b52
3 changed files with 49 additions and 66 deletions

View File

@ -343,8 +343,8 @@ static inline void blk_queue_free_zone_bitmaps(struct request_queue *q) {}
static inline void blk_queue_clear_zone_settings(struct request_queue *q) {} static inline void blk_queue_clear_zone_settings(struct request_queue *q) {}
#endif #endif
int blk_alloc_devt(struct block_device *part, dev_t *devt); int blk_alloc_ext_minor(void);
void blk_free_devt(dev_t devt); void blk_free_ext_minor(unsigned int minor);
char *disk_name(struct gendisk *hd, int partno, char *buf); char *disk_name(struct gendisk *hd, int partno, char *buf);
#define ADDPART_FLAG_NONE 0 #define ADDPART_FLAG_NONE 0
#define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_RAID 1

View File

@ -333,52 +333,22 @@ static int blk_mangle_minor(int minor)
return minor; return minor;
} }
/** int blk_alloc_ext_minor(void)
* blk_alloc_devt - allocate a dev_t for a block device
* @bdev: block device to allocate dev_t for
* @devt: out parameter for resulting dev_t
*
* Allocate a dev_t for block device.
*
* RETURNS:
* 0 on success, allocated dev_t is returned in *@devt. -errno on
* failure.
*
* CONTEXT:
* Might sleep.
*/
int blk_alloc_devt(struct block_device *bdev, dev_t *devt)
{ {
struct gendisk *disk = bdev->bd_disk;
int idx; int idx;
/* in consecutive minor range? */
if (bdev->bd_partno < disk->minors) {
*devt = MKDEV(disk->major, disk->first_minor + bdev->bd_partno);
return 0;
}
idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT, GFP_KERNEL); idx = ida_alloc_range(&ext_devt_ida, 0, NR_EXT_DEVT, GFP_KERNEL);
if (idx < 0) if (idx < 0) {
return idx == -ENOSPC ? -EBUSY : idx; if (idx == -ENOSPC)
return -EBUSY;
*devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx)); return idx;
return 0; }
return blk_mangle_minor(idx);
} }
/** void blk_free_ext_minor(unsigned int minor)
* blk_free_devt - free a dev_t
* @devt: dev_t to free
*
* Free @devt which was allocated using blk_alloc_devt().
*
* CONTEXT:
* Might sleep.
*/
void blk_free_devt(dev_t devt)
{ {
if (MAJOR(devt) == BLOCK_EXT_MAJOR) ida_free(&ext_devt_ida, blk_mangle_minor(minor));
ida_free(&ext_devt_ida, blk_mangle_minor(MINOR(devt)));
} }
static char *bdevt_str(dev_t devt, char *buf) static char *bdevt_str(dev_t devt, char *buf)
@ -499,8 +469,7 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
const struct attribute_group **groups, const struct attribute_group **groups,
bool register_queue) bool register_queue)
{ {
dev_t devt; int ret;
int retval;
/* /*
* The disk queue should now be all set with enough information about * The disk queue should now be all set with enough information about
@ -511,24 +480,30 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
if (register_queue) if (register_queue)
elevator_init_mq(disk->queue); elevator_init_mq(disk->queue);
/* minors == 0 indicates to use ext devt from part0 and should /*
* be accompanied with EXT_DEVT flag. Make sure all * If the driver provides an explicit major number it also must provide
* parameters make sense. * the number of minors numbers supported, and those will be used to
* setup the gendisk.
* Otherwise just allocate the device numbers for both the whole device
* and all partitions from the extended dev_t space.
*/ */
WARN_ON(disk->minors && !(disk->major || disk->first_minor)); if (disk->major) {
WARN_ON(!disk->minors && WARN_ON(!disk->minors);
!(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN))); } else {
WARN_ON(disk->minors);
WARN_ON(!(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN)));
ret = blk_alloc_ext_minor();
if (ret < 0) {
WARN_ON(1);
return;
}
disk->major = BLOCK_EXT_MAJOR;
disk->first_minor = MINOR(ret);
}
disk->flags |= GENHD_FL_UP; disk->flags |= GENHD_FL_UP;
retval = blk_alloc_devt(disk->part0, &devt);
if (retval) {
WARN_ON(1);
return;
}
disk->major = MAJOR(devt);
disk->first_minor = MINOR(devt);
disk_alloc_events(disk); disk_alloc_events(disk);
if (disk->flags & GENHD_FL_HIDDEN) { if (disk->flags & GENHD_FL_HIDDEN) {
@ -541,14 +516,14 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
} else { } else {
struct backing_dev_info *bdi = disk->queue->backing_dev_info; struct backing_dev_info *bdi = disk->queue->backing_dev_info;
struct device *dev = disk_to_dev(disk); struct device *dev = disk_to_dev(disk);
int ret;
/* Register BDI before referencing it from bdev */ /* Register BDI before referencing it from bdev */
dev->devt = devt; dev->devt = MKDEV(disk->major, disk->first_minor);
ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt)); ret = bdi_register(bdi, "%u:%u",
disk->major, disk->first_minor);
WARN_ON(ret); WARN_ON(ret);
bdi_set_owner(bdi, dev); bdi_set_owner(bdi, dev);
bdev_add(disk->part0, devt); bdev_add(disk->part0, dev->devt);
} }
register_disk(parent, disk, groups); register_disk(parent, disk, groups);
if (register_queue) if (register_queue)
@ -1120,7 +1095,8 @@ static void disk_release(struct device *dev)
might_sleep(); might_sleep();
blk_free_devt(dev->devt); if (MAJOR(dev->devt) == BLOCK_EXT_MAJOR)
blk_free_ext_minor(MINOR(dev->devt));
disk_release_events(disk); disk_release_events(disk);
kfree(disk->random); kfree(disk->random);
xa_destroy(&disk->part_tbl); xa_destroy(&disk->part_tbl);

View File

@ -260,7 +260,8 @@ static const struct attribute_group *part_attr_groups[] = {
static void part_release(struct device *dev) static void part_release(struct device *dev)
{ {
blk_free_devt(dev->devt); if (MAJOR(dev->devt) == BLOCK_EXT_MAJOR)
blk_free_ext_minor(MINOR(dev->devt));
bdput(dev_to_bdev(dev)); bdput(dev_to_bdev(dev));
} }
@ -379,9 +380,15 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
pdev->type = &part_type; pdev->type = &part_type;
pdev->parent = ddev; pdev->parent = ddev;
err = blk_alloc_devt(bdev, &devt); /* in consecutive minor range? */
if (err) if (bdev->bd_partno < disk->minors) {
goto out_put; devt = MKDEV(disk->major, disk->first_minor + bdev->bd_partno);
} else {
err = blk_alloc_ext_minor();
if (err < 0)
goto out_put;
devt = MKDEV(BLOCK_EXT_MAJOR, err);
}
pdev->devt = devt; pdev->devt = devt;
/* delay uevent until 'holders' subdir is created */ /* delay uevent until 'holders' subdir is created */