Re: [PATCH 15/19] amiflop: use separate gendisks for Amiga vs MS-DOS mode
On 9/3/20 10:01 AM, Christoph Hellwig wrote: Use separate gendisks (which share a tag_set) for the native Amgiga vs the MS-DOS mode 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 --- drivers/block/amiflop.c | 98 +++-- 1 file changed, 55 insertions(+), 43 deletions(-) Reviewed-by: Hannes Reinecke Cheers, Hannes -- Dr. Hannes ReineckeKernel Storage Architect h...@suse.de +49 911 74053 688 SUSE Software Solutions GmbH, Maxfeldstr. 5, 90409 Nürnberg HRB 36809 (AG Nürnberg), Geschäftsführer: Felix Imendörffer
[PATCH 15/19] amiflop: use separate gendisks for Amiga vs MS-DOS mode
Use separate gendisks (which share a tag_set) for the native Amgiga vs the MS-DOS mode 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 --- drivers/block/amiflop.c | 98 +++-- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 226219da3da6a7..de2bad8d1512f2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -201,7 +201,7 @@ struct amiga_floppy_struct { int busy; /* true when drive is active */ int dirty; /* true when trackbuf is not on disk */ int status; /* current error code for unit */ - struct gendisk *gendisk; + struct gendisk *gendisk[2]; struct blk_mq_tag_set tag_set; }; @@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return -EBUSY; } + if (unit[drive].type->code == FD_NODRIVE) { + mutex_unlock(_mutex); + return -ENXIO; + } + if (mode & (FMODE_READ|FMODE_WRITE)) { check_disk_change(bdev); if (mode & FMODE_WRITE) { @@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) unit[drive].dtype=_types[system]; unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* data_types[system].sects*unit[drive].type->sect_mult; - set_capacity(unit[drive].gendisk, unit[drive].blocks); + set_capacity(unit[drive].gendisk[system], unit[drive].blocks); printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); @@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = { .queue_rq = amiflop_queue_rq, }; -static struct gendisk *fd_alloc_disk(int drive) +static int fd_alloc_disk(int drive, int system) { struct gendisk *disk; disk = alloc_disk(1); if (!disk) goto out; - - disk->queue = blk_mq_init_sq_queue([drive].tag_set, _mq_ops, - 2, BLK_MQ_F_SHOULD_MERGE); - if (IS_ERR(disk->queue)) { - disk->queue = NULL; + disk->queue = blk_mq_init_queue([drive].tag_set); + if (IS_ERR(disk->queue)) goto out_put_disk; - } + disk->major = FLOPPY_MAJOR; + disk->first_minor = drive + system; + disk->fops = _fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; + if (system) + sprintf(disk->disk_name, "fd%d_msdos", drive); + else + sprintf(disk->disk_name, "fd%d", drive); + disk->private_data = [drive]; + set_capacity(disk, 880 * 2); + + unit[drive].gendisk[system] = disk; + add_disk(disk); + return 0; + +out_put_disk: + disk->queue = NULL; + put_disk(disk); +out: + return -ENOMEM; +} + +static int fd_alloc_drive(int drive) +{ unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL); if (!unit[drive].trackbuf) - goto out_cleanup_queue; + goto out; - return disk; + memset([drive].tag_set, 0, sizeof(unit[drive].tag_set)); + unit[drive].tag_set.ops = _mq_ops; + unit[drive].tag_set.nr_hw_queues = 1; + unit[drive].tag_set.nr_maps = 1; + unit[drive].tag_set.queue_depth = 2; + unit[drive].tag_set.numa_node = NUMA_NO_NODE; + unit[drive].tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + if (blk_mq_alloc_tag_set([drive].tag_set)) + goto out_cleanup_trackbuf; -out_cleanup_queue: - blk_cleanup_queue(disk->queue); - disk->queue = NULL; + pr_cont(" fd%d", drive); + + if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1)) + goto out_cleanup_tagset; + return 0; + +out_cleanup_tagset: blk_mq_free_tag_set([drive].tag_set); -out_put_disk: - put_disk(disk); +out_cleanup_trackbuf: + kfree(unit[drive].trackbuf); out: unit[drive].type->code = FD_NODRIVE; - return NULL; + return -ENOMEM; } static int __init fd_probe_drives(void) @@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void) drives=0; nomem=0; for(drive=0;drivecode == FD_NODRIVE) continue; - disk = fd_alloc_disk(drive); - if (!disk) { + if (fd_alloc_drive(drive) < 0) { pr_cont(" no mem for fd%d", drive); nomem = 1; continue; } - unit[drive].gendisk = disk; drives++; - -
[PATCH 15/19] amiflop: use separate gendisks for Amiga vs MS-DOS mode
Use separate gendisks (which share a tag_set) for the native Amgiga vs the MS-DOS mode 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 --- drivers/block/amiflop.c | 98 +++-- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 226219da3da6a7..de2bad8d1512f2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -201,7 +201,7 @@ struct amiga_floppy_struct { int busy; /* true when drive is active */ int dirty; /* true when trackbuf is not on disk */ int status; /* current error code for unit */ - struct gendisk *gendisk; + struct gendisk *gendisk[2]; struct blk_mq_tag_set tag_set; }; @@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return -EBUSY; } + if (unit[drive].type->code == FD_NODRIVE) { + mutex_unlock(_mutex); + return -ENXIO; + } + if (mode & (FMODE_READ|FMODE_WRITE)) { check_disk_change(bdev); if (mode & FMODE_WRITE) { @@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) unit[drive].dtype=_types[system]; unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* data_types[system].sects*unit[drive].type->sect_mult; - set_capacity(unit[drive].gendisk, unit[drive].blocks); + set_capacity(unit[drive].gendisk[system], unit[drive].blocks); printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); @@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = { .queue_rq = amiflop_queue_rq, }; -static struct gendisk *fd_alloc_disk(int drive) +static int fd_alloc_disk(int drive, int system) { struct gendisk *disk; disk = alloc_disk(1); if (!disk) goto out; - - disk->queue = blk_mq_init_sq_queue([drive].tag_set, _mq_ops, - 2, BLK_MQ_F_SHOULD_MERGE); - if (IS_ERR(disk->queue)) { - disk->queue = NULL; + disk->queue = blk_mq_init_queue([drive].tag_set); + if (IS_ERR(disk->queue)) goto out_put_disk; - } + disk->major = FLOPPY_MAJOR; + disk->first_minor = drive + system; + disk->fops = _fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; + if (system) + sprintf(disk->disk_name, "fd%d_msdos", drive); + else + sprintf(disk->disk_name, "fd%d", drive); + disk->private_data = [drive]; + set_capacity(disk, 880 * 2); + + unit[drive].gendisk[system] = disk; + add_disk(disk); + return 0; + +out_put_disk: + disk->queue = NULL; + put_disk(disk); +out: + return -ENOMEM; +} + +static int fd_alloc_drive(int drive) +{ unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL); if (!unit[drive].trackbuf) - goto out_cleanup_queue; + goto out; - return disk; + memset([drive].tag_set, 0, sizeof(unit[drive].tag_set)); + unit[drive].tag_set.ops = _mq_ops; + unit[drive].tag_set.nr_hw_queues = 1; + unit[drive].tag_set.nr_maps = 1; + unit[drive].tag_set.queue_depth = 2; + unit[drive].tag_set.numa_node = NUMA_NO_NODE; + unit[drive].tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + if (blk_mq_alloc_tag_set([drive].tag_set)) + goto out_cleanup_trackbuf; -out_cleanup_queue: - blk_cleanup_queue(disk->queue); - disk->queue = NULL; + pr_cont(" fd%d", drive); + + if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1)) + goto out_cleanup_tagset; + return 0; + +out_cleanup_tagset: blk_mq_free_tag_set([drive].tag_set); -out_put_disk: - put_disk(disk); +out_cleanup_trackbuf: + kfree(unit[drive].trackbuf); out: unit[drive].type->code = FD_NODRIVE; - return NULL; + return -ENOMEM; } static int __init fd_probe_drives(void) @@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void) drives=0; nomem=0; for(drive=0;drivecode == FD_NODRIVE) continue; - disk = fd_alloc_disk(drive); - if (!disk) { + if (fd_alloc_drive(drive) < 0) { pr_cont(" no mem for fd%d", drive); nomem = 1; continue; } - unit[drive].gendisk = disk; drives++; - -
[PATCH 15/19] amiflop: use separate gendisks for Amiga vs MS-DOS mode
Use separate gendisks (which share a tag_set) for the native Amgiga vs the MS-DOS mode 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 --- drivers/block/amiflop.c | 98 +++-- 1 file changed, 55 insertions(+), 43 deletions(-) diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 226219da3da6a7..de2bad8d1512f2 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -201,7 +201,7 @@ struct amiga_floppy_struct { int busy; /* true when drive is active */ int dirty; /* true when trackbuf is not on disk */ int status; /* current error code for unit */ - struct gendisk *gendisk; + struct gendisk *gendisk[2]; struct blk_mq_tag_set tag_set; }; @@ -1669,6 +1669,11 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) return -EBUSY; } + if (unit[drive].type->code == FD_NODRIVE) { + mutex_unlock(_mutex); + return -ENXIO; + } + if (mode & (FMODE_READ|FMODE_WRITE)) { check_disk_change(bdev); if (mode & FMODE_WRITE) { @@ -1695,7 +1700,7 @@ static int floppy_open(struct block_device *bdev, fmode_t mode) unit[drive].dtype=_types[system]; unit[drive].blocks=unit[drive].type->heads*unit[drive].type->tracks* data_types[system].sects*unit[drive].type->sect_mult; - set_capacity(unit[drive].gendisk, unit[drive].blocks); + set_capacity(unit[drive].gendisk[system], unit[drive].blocks); printk(KERN_INFO "fd%d: accessing %s-disk with %s-layout\n",drive, unit[drive].type->name, data_types[system].name); @@ -1772,36 +1777,68 @@ static const struct blk_mq_ops amiflop_mq_ops = { .queue_rq = amiflop_queue_rq, }; -static struct gendisk *fd_alloc_disk(int drive) +static int fd_alloc_disk(int drive, int system) { struct gendisk *disk; disk = alloc_disk(1); if (!disk) goto out; - - disk->queue = blk_mq_init_sq_queue([drive].tag_set, _mq_ops, - 2, BLK_MQ_F_SHOULD_MERGE); - if (IS_ERR(disk->queue)) { - disk->queue = NULL; + disk->queue = blk_mq_init_queue([drive].tag_set); + if (IS_ERR(disk->queue)) goto out_put_disk; - } + disk->major = FLOPPY_MAJOR; + disk->first_minor = drive + system; + disk->fops = _fops; + disk->events = DISK_EVENT_MEDIA_CHANGE; + if (system) + sprintf(disk->disk_name, "fd%d_msdos", drive); + else + sprintf(disk->disk_name, "fd%d", drive); + disk->private_data = [drive]; + set_capacity(disk, 880 * 2); + + unit[drive].gendisk[system] = disk; + add_disk(disk); + return 0; + +out_put_disk: + disk->queue = NULL; + put_disk(disk); +out: + return -ENOMEM; +} + +static int fd_alloc_drive(int drive) +{ unit[drive].trackbuf = kmalloc(FLOPPY_MAX_SECTORS * 512, GFP_KERNEL); if (!unit[drive].trackbuf) - goto out_cleanup_queue; + goto out; - return disk; + memset([drive].tag_set, 0, sizeof(unit[drive].tag_set)); + unit[drive].tag_set.ops = _mq_ops; + unit[drive].tag_set.nr_hw_queues = 1; + unit[drive].tag_set.nr_maps = 1; + unit[drive].tag_set.queue_depth = 2; + unit[drive].tag_set.numa_node = NUMA_NO_NODE; + unit[drive].tag_set.flags = BLK_MQ_F_SHOULD_MERGE; + if (blk_mq_alloc_tag_set([drive].tag_set)) + goto out_cleanup_trackbuf; -out_cleanup_queue: - blk_cleanup_queue(disk->queue); - disk->queue = NULL; + pr_cont(" fd%d", drive); + + if (fd_alloc_disk(drive, 0) || fd_alloc_disk(drive, 1)) + goto out_cleanup_tagset; + return 0; + +out_cleanup_tagset: blk_mq_free_tag_set([drive].tag_set); -out_put_disk: - put_disk(disk); +out_cleanup_trackbuf: + kfree(unit[drive].trackbuf); out: unit[drive].type->code = FD_NODRIVE; - return NULL; + return -ENOMEM; } static int __init fd_probe_drives(void) @@ -1812,29 +1849,16 @@ static int __init fd_probe_drives(void) drives=0; nomem=0; for(drive=0;drivecode == FD_NODRIVE) continue; - disk = fd_alloc_disk(drive); - if (!disk) { + if (fd_alloc_drive(drive) < 0) { pr_cont(" no mem for fd%d", drive); nomem = 1; continue; } - unit[drive].gendisk = disk; drives++; - -