z2ram: use separate gendisk for the different modes
Use separate gendisks (which share a tag_set) for the different operating modes instead of redirecting the gendisk lookup using a probe callback. This avoids potential problems with aliased block_device instances and will eventually allow for removing the blk_register_region framework. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Hannes Reinecke <hare@suse.de> Signed-off-by: Jens Axboe <axboe@kernel.dk>
This commit is contained in:
parent
6c3a05e127
commit
76487f0241
|
@ -63,7 +63,7 @@ static int current_device = -1;
|
||||||
|
|
||||||
static DEFINE_SPINLOCK(z2ram_lock);
|
static DEFINE_SPINLOCK(z2ram_lock);
|
||||||
|
|
||||||
static struct gendisk *z2ram_gendisk;
|
static struct gendisk *z2ram_gendisk[Z2MINOR_COUNT];
|
||||||
|
|
||||||
static blk_status_t z2_queue_rq(struct blk_mq_hw_ctx *hctx,
|
static blk_status_t z2_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||||
const struct blk_mq_queue_data *bd)
|
const struct blk_mq_queue_data *bd)
|
||||||
|
@ -283,7 +283,7 @@ static int z2_open(struct block_device *bdev, fmode_t mode)
|
||||||
|
|
||||||
current_device = device;
|
current_device = device;
|
||||||
z2ram_size <<= Z2RAM_CHUNKSHIFT;
|
z2ram_size <<= Z2RAM_CHUNKSHIFT;
|
||||||
set_capacity(z2ram_gendisk, z2ram_size >> 9);
|
set_capacity(z2ram_gendisk[device], z2ram_size >> 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&z2ram_mutex);
|
mutex_unlock(&z2ram_mutex);
|
||||||
|
@ -315,71 +315,87 @@ static const struct block_device_operations z2_fops = {
|
||||||
.release = z2_release,
|
.release = z2_release,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct kobject *z2_find(dev_t dev, int *part, void *data)
|
|
||||||
{
|
|
||||||
*part = 0;
|
|
||||||
return get_disk_and_module(z2ram_gendisk);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct request_queue *z2_queue;
|
|
||||||
static struct blk_mq_tag_set tag_set;
|
static struct blk_mq_tag_set tag_set;
|
||||||
|
|
||||||
static const struct blk_mq_ops z2_mq_ops = {
|
static const struct blk_mq_ops z2_mq_ops = {
|
||||||
.queue_rq = z2_queue_rq,
|
.queue_rq = z2_queue_rq,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int z2ram_register_disk(int minor)
|
||||||
|
{
|
||||||
|
struct request_queue *q;
|
||||||
|
struct gendisk *disk;
|
||||||
|
|
||||||
|
disk = alloc_disk(1);
|
||||||
|
if (!disk)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
q = blk_mq_init_queue(&tag_set);
|
||||||
|
if (IS_ERR(q)) {
|
||||||
|
put_disk(disk);
|
||||||
|
return PTR_ERR(q);
|
||||||
|
}
|
||||||
|
|
||||||
|
disk->major = Z2RAM_MAJOR;
|
||||||
|
disk->first_minor = minor;
|
||||||
|
disk->fops = &z2_fops;
|
||||||
|
if (minor)
|
||||||
|
sprintf(disk->disk_name, "z2ram%d", minor);
|
||||||
|
else
|
||||||
|
sprintf(disk->disk_name, "z2ram");
|
||||||
|
disk->queue = q;
|
||||||
|
|
||||||
|
z2ram_gendisk[minor] = disk;
|
||||||
|
add_disk(disk);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int __init z2_init(void)
|
static int __init z2_init(void)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret, i;
|
||||||
|
|
||||||
if (!MACH_IS_AMIGA)
|
if (!MACH_IS_AMIGA)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
ret = -EBUSY;
|
|
||||||
if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
|
if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
|
||||||
goto err;
|
return -EBUSY;
|
||||||
|
|
||||||
ret = -ENOMEM;
|
tag_set.ops = &z2_mq_ops;
|
||||||
z2ram_gendisk = alloc_disk(1);
|
tag_set.nr_hw_queues = 1;
|
||||||
if (!z2ram_gendisk)
|
tag_set.nr_maps = 1;
|
||||||
goto out_disk;
|
tag_set.queue_depth = 16;
|
||||||
|
tag_set.numa_node = NUMA_NO_NODE;
|
||||||
|
tag_set.flags = BLK_MQ_F_SHOULD_MERGE;
|
||||||
|
ret = blk_mq_alloc_tag_set(&tag_set);
|
||||||
|
if (ret)
|
||||||
|
goto out_unregister_blkdev;
|
||||||
|
|
||||||
z2_queue = blk_mq_init_sq_queue(&tag_set, &z2_mq_ops, 16,
|
for (i = 0; i < Z2MINOR_COUNT; i++) {
|
||||||
BLK_MQ_F_SHOULD_MERGE);
|
ret = z2ram_register_disk(i);
|
||||||
if (IS_ERR(z2_queue)) {
|
if (ret && i == 0)
|
||||||
ret = PTR_ERR(z2_queue);
|
goto out_free_tagset;
|
||||||
z2_queue = NULL;
|
|
||||||
goto out_queue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
z2ram_gendisk->major = Z2RAM_MAJOR;
|
|
||||||
z2ram_gendisk->first_minor = 0;
|
|
||||||
z2ram_gendisk->fops = &z2_fops;
|
|
||||||
sprintf(z2ram_gendisk->disk_name, "z2ram");
|
|
||||||
|
|
||||||
z2ram_gendisk->queue = z2_queue;
|
|
||||||
add_disk(z2ram_gendisk);
|
|
||||||
blk_register_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT, THIS_MODULE,
|
|
||||||
z2_find, NULL, NULL);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
out_queue:
|
out_free_tagset:
|
||||||
put_disk(z2ram_gendisk);
|
blk_mq_free_tag_set(&tag_set);
|
||||||
out_disk:
|
out_unregister_blkdev:
|
||||||
unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
|
unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
|
||||||
err:
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit z2_exit(void)
|
static void __exit z2_exit(void)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
blk_unregister_region(MKDEV(Z2RAM_MAJOR, 0), Z2MINOR_COUNT);
|
|
||||||
unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
|
unregister_blkdev(Z2RAM_MAJOR, DEVICE_NAME);
|
||||||
del_gendisk(z2ram_gendisk);
|
|
||||||
put_disk(z2ram_gendisk);
|
for (i = 0; i < Z2MINOR_COUNT; i++) {
|
||||||
blk_cleanup_queue(z2_queue);
|
del_gendisk(z2ram_gendisk[i]);
|
||||||
|
blk_cleanup_queue(z2ram_gendisk[i]->queue);
|
||||||
|
put_disk(z2ram_gendisk[i]);
|
||||||
|
}
|
||||||
blk_mq_free_tag_set(&tag_set);
|
blk_mq_free_tag_set(&tag_set);
|
||||||
|
|
||||||
if (current_device != -1) {
|
if (current_device != -1) {
|
||||||
|
|
Loading…
Reference in New Issue