Commit 7c3f828b authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Jens Axboe
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarLuis Chamberlain <mcgrof@kernel.org>
Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20210521055116.1053587-2-hch@lst.de


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent d97e594c
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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) {}
#endif

int blk_alloc_devt(struct block_device *part, dev_t *devt);
void blk_free_devt(dev_t devt);
int blk_alloc_ext_minor(void);
void blk_free_ext_minor(unsigned int minor);
char *disk_name(struct gendisk *hd, int partno, char *buf);
#define ADDPART_FLAG_NONE	0
#define ADDPART_FLAG_RAID	1
+36 −60
Original line number Diff line number Diff line
@@ -333,52 +333,22 @@ static int blk_mangle_minor(int minor)
	return minor;
}

/**
 * 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)
int blk_alloc_ext_minor(void)
{
	struct gendisk *disk = bdev->bd_disk;
	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);
	if (idx < 0)
		return idx == -ENOSPC ? -EBUSY : idx;

	*devt = MKDEV(BLOCK_EXT_MAJOR, blk_mangle_minor(idx));
	return 0;
	if (idx < 0) {
		if (idx == -ENOSPC)
			return -EBUSY;
		return idx;
	}
	return blk_mangle_minor(idx);
}

/**
 * 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)
void blk_free_ext_minor(unsigned int minor)
{
	if (MAJOR(devt) == BLOCK_EXT_MAJOR)
		ida_free(&ext_devt_ida, blk_mangle_minor(MINOR(devt)));
	ida_free(&ext_devt_ida, blk_mangle_minor(minor));
}

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,
			      bool register_queue)
{
	dev_t devt;
	int retval;
	int ret;

	/*
	 * The disk queue should now be all set with enough information about
@@ -511,23 +480,29 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
	if (register_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
	 * parameters make sense.
	/*
	 * If the driver provides an explicit major number it also must provide
	 * 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));
	WARN_ON(!disk->minors &&
		!(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN)));

	disk->flags |= GENHD_FL_UP;
	if (disk->major) {
		WARN_ON(!disk->minors);
	} else {
		WARN_ON(disk->minors);
		WARN_ON(!(disk->flags & (GENHD_FL_EXT_DEVT | GENHD_FL_HIDDEN)));

	retval = blk_alloc_devt(disk->part0, &devt);
	if (retval) {
		ret = blk_alloc_ext_minor();
		if (ret < 0) {
			WARN_ON(1);
			return;
		}
	disk->major = MAJOR(devt);
	disk->first_minor = MINOR(devt);
		disk->major = BLOCK_EXT_MAJOR;
		disk->first_minor = MINOR(ret);
	}

	disk->flags |= GENHD_FL_UP;

	disk_alloc_events(disk);

@@ -541,14 +516,14 @@ static void __device_add_disk(struct device *parent, struct gendisk *disk,
	} else {
		struct backing_dev_info *bdi = disk->queue->backing_dev_info;
		struct device *dev = disk_to_dev(disk);
		int ret;

		/* Register BDI before referencing it from bdev */
		dev->devt = devt;
		ret = bdi_register(bdi, "%u:%u", MAJOR(devt), MINOR(devt));
		dev->devt = MKDEV(disk->major, disk->first_minor);
		ret = bdi_register(bdi, "%u:%u",
				   disk->major, disk->first_minor);
		WARN_ON(ret);
		bdi_set_owner(bdi, dev);
		bdev_add(disk->part0, devt);
		bdev_add(disk->part0, dev->devt);
	}
	register_disk(parent, disk, groups);
	if (register_queue)
@@ -1120,7 +1095,8 @@ static void disk_release(struct device *dev)

	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);
	kfree(disk->random);
	xa_destroy(&disk->part_tbl);
+11 −4
Original line number Diff line number Diff line
@@ -260,7 +260,8 @@ static const struct attribute_group *part_attr_groups[] = {

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));
}

@@ -379,9 +380,15 @@ static struct block_device *add_partition(struct gendisk *disk, int partno,
	pdev->type = &part_type;
	pdev->parent = ddev;

	err = blk_alloc_devt(bdev, &devt);
	if (err)
	/* in consecutive minor range? */
	if (bdev->bd_partno < disk->minors) {
		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;

	/* delay uevent until 'holders' subdir is created */