Commit cb690f52 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.16/drivers-2021-11-09' of git://git.kernel.dk/linux-block

Pull more block driver updates from Jens Axboe:

 - Last series adding error handling support for add_disk() in drivers.
   After this one, and once the SCSI side has been merged, we can
   finally annotate add_disk() as must_check. (Luis)

 - bcache fixes (Coly)

 - zram fixes (Ming)

 - ataflop locking fix (Tetsuo)

 - nbd fixes (Ye, Yu)

 - MD merge via Song
      - Cleanup (Yang)
      - sysfs fix (Guoqing)

 - Misc fixes (Geert, Wu, luo)

* tag 'for-5.16/drivers-2021-11-09' of git://git.kernel.dk/linux-block: (34 commits)
  bcache: Revert "bcache: use bvec_virt"
  ataflop: Add missing semicolon to return statement
  floppy: address add_disk() error handling on probe
  ataflop: address add_disk() error handling on probe
  block: update __register_blkdev() probe documentation
  ataflop: remove ataflop_probe_lock mutex
  mtd/ubi/block: add error handling support for add_disk()
  block/sunvdc: add error handling support for add_disk()
  z2ram: add error handling support for add_disk()
  nvdimm/pmem: use add_disk() error handling
  nvdimm/pmem: cleanup the disk if pmem_release_disk() is yet assigned
  nvdimm/blk: add error handling support for add_disk()
  nvdimm/blk: avoid calling del_gendisk() on early failures
  nvdimm/btt: add error handling support for add_disk()
  nvdimm/btt: use goto error labels on btt_blk_init()
  loop: Remove duplicate assignments
  drbd: Fix double free problem in drbd_create_device
  nvdimm/btt: do not call del_gendisk() if not needed
  bcache: fix use-after-free problem in bcache_device_free()
  zram: replace fsync_bdev with sync_blockdev
  ...
parents 3e28850c 2878feae
...@@ -213,7 +213,10 @@ void blkdev_show(struct seq_file *seqf, off_t offset) ...@@ -213,7 +213,10 @@ void blkdev_show(struct seq_file *seqf, off_t offset)
* @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If * @major: the requested major device number [1..BLKDEV_MAJOR_MAX-1]. If
* @major = 0, try to allocate any unused major number. * @major = 0, try to allocate any unused major number.
* @name: the name of the new block device as a zero terminated string * @name: the name of the new block device as a zero terminated string
* @probe: allback that is called on access to any minor number of @major * @probe: pre-devtmpfs / pre-udev callback used to create disks when their
* pre-created device node is accessed. When a probe call uses
* add_disk() and it fails the driver must cleanup resources. This
* interface may soon be removed.
* *
* The @name must be unique within the system. * The @name must be unique within the system.
* *
......
...@@ -2008,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type) ...@@ -2008,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
return 0; return 0;
} }
static DEFINE_MUTEX(ataflop_probe_lock);
static void ataflop_probe(dev_t dev) static void ataflop_probe(dev_t dev)
{ {
int drive = MINOR(dev) & 3; int drive = MINOR(dev) & 3;
...@@ -2020,14 +2018,38 @@ static void ataflop_probe(dev_t dev) ...@@ -2020,14 +2018,38 @@ static void ataflop_probe(dev_t dev)
if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS) if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS)
return; return;
mutex_lock(&ataflop_probe_lock); if (unit[drive].disk[type])
if (!unit[drive].disk[type]) { return;
if (ataflop_alloc_disk(drive, type) == 0) { if (ataflop_alloc_disk(drive, type))
add_disk(unit[drive].disk[type]); return;
if (add_disk(unit[drive].disk[type]))
goto cleanup_disk;
unit[drive].registered[type] = true; unit[drive].registered[type] = true;
return;
cleanup_disk:
blk_cleanup_disk(unit[drive].disk[type]);
unit[drive].disk[type] = NULL;
}
static void atari_floppy_cleanup(void)
{
int i;
int type;
for (i = 0; i < FD_MAX_UNITS; i++) {
for (type = 0; type < NUM_DISK_MINORS; type++) {
if (!unit[i].disk[type])
continue;
del_gendisk(unit[i].disk[type]);
blk_cleanup_queue(unit[i].disk[type]->queue);
put_disk(unit[i].disk[type]);
} }
blk_mq_free_tag_set(&unit[i].tag_set);
} }
mutex_unlock(&ataflop_probe_lock);
del_timer_sync(&fd_timer);
atari_stram_free(DMABuffer);
} }
static void atari_cleanup_floppy_disk(struct atari_floppy_struct *fs) static void atari_cleanup_floppy_disk(struct atari_floppy_struct *fs)
...@@ -2053,11 +2075,6 @@ static int __init atari_floppy_init (void) ...@@ -2053,11 +2075,6 @@ static int __init atari_floppy_init (void)
/* Amiga, Mac, ... don't have Atari-compatible floppy :-) */ /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
return -ENODEV; return -ENODEV;
mutex_lock(&ataflop_probe_lock);
ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe);
if (ret)
goto out_unlock;
for (i = 0; i < FD_MAX_UNITS; i++) { for (i = 0; i < FD_MAX_UNITS; i++) {
memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set)); memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set));
unit[i].tag_set.ops = &ataflop_mq_ops; unit[i].tag_set.ops = &ataflop_mq_ops;
...@@ -2113,7 +2130,12 @@ static int __init atari_floppy_init (void) ...@@ -2113,7 +2130,12 @@ static int __init atari_floppy_init (void)
UseTrackbuffer ? "" : "no "); UseTrackbuffer ? "" : "no ");
config_types(); config_types();
return 0; ret = __register_blkdev(FLOPPY_MAJOR, "fd", ataflop_probe);
if (ret) {
printk(KERN_ERR "atari_floppy_init: cannot register block device\n");
atari_floppy_cleanup();
}
return ret;
err_out_dma: err_out_dma:
atari_stram_free(DMABuffer); atari_stram_free(DMABuffer);
...@@ -2121,9 +2143,6 @@ static int __init atari_floppy_init (void) ...@@ -2121,9 +2143,6 @@ static int __init atari_floppy_init (void)
while (--i >= 0) while (--i >= 0)
atari_cleanup_floppy_disk(&unit[i]); atari_cleanup_floppy_disk(&unit[i]);
unregister_blkdev(FLOPPY_MAJOR, "fd");
out_unlock:
mutex_unlock(&ataflop_probe_lock);
return ret; return ret;
} }
...@@ -2168,14 +2187,8 @@ __setup("floppy=", atari_floppy_setup); ...@@ -2168,14 +2187,8 @@ __setup("floppy=", atari_floppy_setup);
static void __exit atari_floppy_exit(void) static void __exit atari_floppy_exit(void)
{ {
int i;
for (i = 0; i < FD_MAX_UNITS; i++)
atari_cleanup_floppy_disk(&unit[i]);
unregister_blkdev(FLOPPY_MAJOR, "fd"); unregister_blkdev(FLOPPY_MAJOR, "fd");
atari_floppy_cleanup();
del_timer_sync(&fd_timer);
atari_stram_free( DMABuffer );
} }
module_init(atari_floppy_init) module_init(atari_floppy_init)
......
...@@ -370,6 +370,7 @@ static int brd_alloc(int i) ...@@ -370,6 +370,7 @@ static int brd_alloc(int i)
struct brd_device *brd; struct brd_device *brd;
struct gendisk *disk; struct gendisk *disk;
char buf[DISK_NAME_LEN]; char buf[DISK_NAME_LEN];
int err = -ENOMEM;
mutex_lock(&brd_devices_mutex); mutex_lock(&brd_devices_mutex);
list_for_each_entry(brd, &brd_devices, brd_list) { list_for_each_entry(brd, &brd_devices, brd_list) {
...@@ -420,16 +421,20 @@ static int brd_alloc(int i) ...@@ -420,16 +421,20 @@ static int brd_alloc(int i)
/* Tell the block layer that this is not a rotational device */ /* Tell the block layer that this is not a rotational device */
blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, disk->queue);
add_disk(disk); err = add_disk(disk);
if (err)
goto out_cleanup_disk;
return 0; return 0;
out_cleanup_disk:
blk_cleanup_disk(disk);
out_free_dev: out_free_dev:
mutex_lock(&brd_devices_mutex); mutex_lock(&brd_devices_mutex);
list_del(&brd->brd_list); list_del(&brd->brd_list);
mutex_unlock(&brd_devices_mutex); mutex_unlock(&brd_devices_mutex);
kfree(brd); kfree(brd);
return -ENOMEM; return err;
} }
static void brd_probe(dev_t dev) static void brd_probe(dev_t dev)
......
...@@ -2796,7 +2796,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig ...@@ -2796,7 +2796,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
err = add_disk(disk); err = add_disk(disk);
if (err) if (err)
goto out_cleanup_disk; goto out_idr_remove_vol;
/* inherit the connection state */ /* inherit the connection state */
device->state.conn = first_connection(resource)->cstate; device->state.conn = first_connection(resource)->cstate;
...@@ -2810,8 +2810,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig ...@@ -2810,8 +2810,6 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
drbd_debugfs_device_add(device); drbd_debugfs_device_add(device);
return NO_ERROR; return NO_ERROR;
out_cleanup_disk:
blk_cleanup_disk(disk);
out_idr_remove_vol: out_idr_remove_vol:
idr_remove(&connection->peer_devices, vnr); idr_remove(&connection->peer_devices, vnr);
out_idr_remove_from_resource: out_idr_remove_from_resource:
......
...@@ -4528,10 +4528,19 @@ static void floppy_probe(dev_t dev) ...@@ -4528,10 +4528,19 @@ static void floppy_probe(dev_t dev)
return; return;
mutex_lock(&floppy_probe_lock); mutex_lock(&floppy_probe_lock);
if (!disks[drive][type]) { if (disks[drive][type])
if (floppy_alloc_disk(drive, type) == 0) goto out;
add_disk(disks[drive][type]); if (floppy_alloc_disk(drive, type))
} goto out;
if (add_disk(disks[drive][type]))
goto cleanup_disk;
out:
mutex_unlock(&floppy_probe_lock);
return;
cleanup_disk:
blk_cleanup_disk(disks[drive][type]);
disks[drive][type] = NULL;
mutex_unlock(&floppy_probe_lock); mutex_unlock(&floppy_probe_lock);
} }
......
...@@ -1983,7 +1983,6 @@ static int loop_add(int i) ...@@ -1983,7 +1983,6 @@ static int loop_add(int i)
goto out_free_dev; goto out_free_dev;
i = err; i = err;
err = -ENOMEM;
lo->tag_set.ops = &loop_mq_ops; lo->tag_set.ops = &loop_mq_ops;
lo->tag_set.nr_hw_queues = 1; lo->tag_set.nr_hw_queues = 1;
lo->tag_set.queue_depth = 128; lo->tag_set.queue_depth = 128;
......
...@@ -260,7 +260,7 @@ static void nbd_dev_remove(struct nbd_device *nbd) ...@@ -260,7 +260,7 @@ static void nbd_dev_remove(struct nbd_device *nbd)
mutex_lock(&nbd_index_mutex); mutex_lock(&nbd_index_mutex);
idr_remove(&nbd_index_idr, nbd->index); idr_remove(&nbd_index_idr, nbd->index);
mutex_unlock(&nbd_index_mutex); mutex_unlock(&nbd_index_mutex);
destroy_workqueue(nbd->recv_workq);
kfree(nbd); kfree(nbd);
} }
...@@ -755,6 +755,8 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index, ...@@ -755,6 +755,8 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
if (cmd->index != index) { if (cmd->index != index) {
dev_err(disk_to_dev(nbd->disk), "Unexpected reply %d from different sock %d (expected %d)", dev_err(disk_to_dev(nbd->disk), "Unexpected reply %d from different sock %d (expected %d)",
tag, index, cmd->index); tag, index, cmd->index);
ret = -ENOENT;
goto out;
} }
if (cmd->cmd_cookie != nbd_handle_to_cookie(handle)) { if (cmd->cmd_cookie != nbd_handle_to_cookie(handle)) {
dev_err(disk_to_dev(nbd->disk), "Double reply on req %p, cmd_cookie %u, handle cookie %u\n", dev_err(disk_to_dev(nbd->disk), "Double reply on req %p, cmd_cookie %u, handle cookie %u\n",
...@@ -1314,10 +1316,6 @@ static void nbd_config_put(struct nbd_device *nbd) ...@@ -1314,10 +1316,6 @@ static void nbd_config_put(struct nbd_device *nbd)
kfree(nbd->config); kfree(nbd->config);
nbd->config = NULL; nbd->config = NULL;
if (nbd->recv_workq)
destroy_workqueue(nbd->recv_workq);
nbd->recv_workq = NULL;
nbd->tag_set.timeout = 0; nbd->tag_set.timeout = 0;
nbd->disk->queue->limits.discard_granularity = 0; nbd->disk->queue->limits.discard_granularity = 0;
nbd->disk->queue->limits.discard_alignment = 0; nbd->disk->queue->limits.discard_alignment = 0;
...@@ -1346,14 +1344,6 @@ static int nbd_start_device(struct nbd_device *nbd) ...@@ -1346,14 +1344,6 @@ static int nbd_start_device(struct nbd_device *nbd)
return -EINVAL; return -EINVAL;
} }
nbd->recv_workq = alloc_workqueue("knbd%d-recv",
WQ_MEM_RECLAIM | WQ_HIGHPRI |
WQ_UNBOUND, 0, nbd->index);
if (!nbd->recv_workq) {
dev_err(disk_to_dev(nbd->disk), "Could not allocate knbd recv work queue.\n");
return -ENOMEM;
}
blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections); blk_mq_update_nr_hw_queues(&nbd->tag_set, config->num_connections);
nbd->pid = task_pid_nr(current); nbd->pid = task_pid_nr(current);
...@@ -1779,6 +1769,15 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) ...@@ -1779,6 +1769,15 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
} }
nbd->disk = disk; nbd->disk = disk;
nbd->recv_workq = alloc_workqueue("nbd%d-recv",
WQ_MEM_RECLAIM | WQ_HIGHPRI |
WQ_UNBOUND, 0, nbd->index);
if (!nbd->recv_workq) {
dev_err(disk_to_dev(nbd->disk), "Could not allocate knbd recv work queue.\n");
err = -ENOMEM;
goto out_err_disk;
}
/* /*
* Tell the block layer that we are not a rotational device * Tell the block layer that we are not a rotational device
*/ */
...@@ -1803,13 +1802,13 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) ...@@ -1803,13 +1802,13 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
disk->major = NBD_MAJOR; disk->major = NBD_MAJOR;
/* Too big first_minor can cause duplicate creation of /* Too big first_minor can cause duplicate creation of
* sysfs files/links, since first_minor will be truncated to * sysfs files/links, since index << part_shift might overflow, or
* byte in __device_add_disk(). * MKDEV() expect that the max bits of first_minor is 20.
*/ */
disk->first_minor = index << part_shift; disk->first_minor = index << part_shift;
if (disk->first_minor > 0xff) { if (disk->first_minor < index || disk->first_minor > MINORMASK) {
err = -EINVAL; err = -EINVAL;
goto out_free_idr; goto out_free_work;
} }
disk->minors = 1 << part_shift; disk->minors = 1 << part_shift;
...@@ -1818,7 +1817,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) ...@@ -1818,7 +1817,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
sprintf(disk->disk_name, "nbd%d", index); sprintf(disk->disk_name, "nbd%d", index);
err = add_disk(disk); err = add_disk(disk);
if (err) if (err)
goto out_err_disk; goto out_free_work;
/* /*
* Now publish the device. * Now publish the device.
...@@ -1827,6 +1826,8 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs) ...@@ -1827,6 +1826,8 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
nbd_total_devices++; nbd_total_devices++;
return nbd; return nbd;
out_free_work:
destroy_workqueue(nbd->recv_workq);
out_err_disk: out_err_disk:
blk_cleanup_disk(disk); blk_cleanup_disk(disk);
out_free_idr: out_free_idr:
...@@ -2082,12 +2083,9 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd) ...@@ -2082,12 +2083,9 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
nbd_disconnect(nbd); nbd_disconnect(nbd);
sock_shutdown(nbd); sock_shutdown(nbd);
/* /*
* Make sure recv thread has finished, so it does not drop the last * Make sure recv thread has finished, we can safely call nbd_clear_que()
* config ref and try to destroy the workqueue from inside the work
* queue. And this also ensure that we can safely call nbd_clear_que()
* to cancel the inflight I/Os. * to cancel the inflight I/Os.
*/ */
if (nbd->recv_workq)
flush_workqueue(nbd->recv_workq); flush_workqueue(nbd->recv_workq);
nbd_clear_que(nbd); nbd_clear_que(nbd);
nbd->task_setup = NULL; nbd->task_setup = NULL;
......
...@@ -467,9 +467,13 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev) ...@@ -467,9 +467,13 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
gendisk->disk_name, priv->model, priv->raw_capacity >> 11, gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
get_capacity(gendisk) >> 11); get_capacity(gendisk) >> 11);
device_add_disk(&dev->sbd.core, gendisk, NULL); error = device_add_disk(&dev->sbd.core, gendisk, NULL);
return 0; if (error)
goto fail_cleanup_disk;
return 0;
fail_cleanup_disk:
blk_cleanup_disk(gendisk);
fail_free_tag_set: fail_free_tag_set:
blk_mq_free_tag_set(&priv->tag_set); blk_mq_free_tag_set(&priv->tag_set);
fail_teardown: fail_teardown:
......
...@@ -753,9 +753,14 @@ static int ps3vram_probe(struct ps3_system_bus_device *dev) ...@@ -753,9 +753,14 @@ static int ps3vram_probe(struct ps3_system_bus_device *dev)
dev_info(&dev->core, "%s: Using %llu MiB of GPU memory\n", dev_info(&dev->core, "%s: Using %llu MiB of GPU memory\n",
gendisk->disk_name, get_capacity(gendisk) >> 11); gendisk->disk_name, get_capacity(gendisk) >> 11);
device_add_disk(&dev->core, gendisk, NULL); error = device_add_disk(&dev->core, gendisk, NULL);
if (error)
goto out_cleanup_disk;
return 0; return 0;
out_cleanup_disk:
blk_cleanup_disk(gendisk);
out_cache_cleanup: out_cache_cleanup:
remove_proc_entry(DEVICE_NAME, NULL); remove_proc_entry(DEVICE_NAME, NULL);
ps3vram_cache_cleanup(dev); ps3vram_cache_cleanup(dev);
......
...@@ -826,8 +826,8 @@ static int probe_disk(struct vdc_port *port) ...@@ -826,8 +826,8 @@ static int probe_disk(struct vdc_port *port)
if (IS_ERR(g)) { if (IS_ERR(g)) {
printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n", printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
port->vio.name); port->vio.name);
blk_mq_free_tag_set(&port->tag_set); err = PTR_ERR(g);
return PTR_ERR(g); goto out_free_tag;
} }
port->disk = g; port->disk = g;
...@@ -879,9 +879,17 @@ static int probe_disk(struct vdc_port *port) ...@@ -879,9 +879,17 @@ static int probe_disk(struct vdc_port *port)
port->vdisk_size, (port->vdisk_size >> (20 - 9)), port->vdisk_size, (port->vdisk_size >> (20 - 9)),
port->vio.ver.major, port->vio.ver.minor); port->vio.ver.major, port->vio.ver.minor);
device_add_disk(&port->vio.vdev->dev, g, NULL); err = device_add_disk(&port->vio.vdev->dev, g, NULL);
if (err)
goto out_cleanup_disk;
return 0; return 0;
out_cleanup_disk:
blk_cleanup_disk(g);
out_free_tag:
blk_mq_free_tag_set(&port->tag_set);
return err;
} }
static struct ldc_channel_config vdc_ldc_cfg = { static struct ldc_channel_config vdc_ldc_cfg = {
......
...@@ -318,6 +318,7 @@ static const struct blk_mq_ops z2_mq_ops = { ...@@ -318,6 +318,7 @@ static const struct blk_mq_ops z2_mq_ops = {
static int z2ram_register_disk(int minor) static int z2ram_register_disk(int minor)
{ {
struct gendisk *disk; struct gendisk *disk;
int err;
disk = blk_mq_alloc_disk(&tag_set, NULL); disk = blk_mq_alloc_disk(&tag_set, NULL);
if (IS_ERR(disk)) if (IS_ERR(disk))
...@@ -333,8 +334,10 @@ static int z2ram_register_disk(int minor) ...@@ -333,8 +334,10 @@ static int z2ram_register_disk(int minor)
sprintf(disk->disk_name, "z2ram"); sprintf(disk->disk_name, "z2ram");
z2ram_gendisk[minor] = disk; z2ram_gendisk[minor] = disk;
add_disk(disk); err = add_disk(disk);
return 0; if (err)
blk_cleanup_disk(disk);
return err;
} }
static int __init z2_init(void) static int __init z2_init(void)
......
...@@ -1734,12 +1734,13 @@ static void zram_reset_device(struct zram *zram) ...@@ -1734,12 +1734,13 @@ static void zram_reset_device(struct zram *zram)
set_capacity_and_notify(zram->disk, 0); set_capacity_and_notify(zram->disk, 0);
part_stat_set_all(zram->disk->part0, 0); part_stat_set_all(zram->disk->part0, 0);
up_write(&zram->init_lock);
/* I/O operation under all of CPU are done so let's free */ /* I/O operation under all of CPU are done so let's free */
zram_meta_free(zram, disksize); zram_meta_free(zram, disksize);
memset(&zram->stats, 0, sizeof(zram->stats)); memset(&zram->stats, 0, sizeof(zram->stats));
zcomp_destroy(comp); zcomp_destroy(comp);
reset_bdev(zram); reset_bdev(zram);
up_write(&zram->init_lock);
} }
static ssize_t disksize_store(struct device *dev, static ssize_t disksize_store(struct device *dev,
...@@ -1819,7 +1820,7 @@ static ssize_t reset_store(struct device *dev, ...@@ -1819,7 +1820,7 @@ static ssize_t reset_store(struct device *dev,
mutex_unlock(&bdev->bd_disk->open_mutex); mutex_unlock(&bdev->bd_disk->open_mutex);
/* Make sure all the pending I/O are finished */ /* Make sure all the pending I/O are finished */
fsync_bdev(bdev); sync_blockdev(bdev);
zram_reset_device(zram); zram_reset_device(zram);
mutex_lock(&bdev->bd_disk->open_mutex); mutex_lock(&bdev->bd_disk->open_mutex);
...@@ -1979,7 +1980,9 @@ static int zram_add(void) ...@@ -1979,7 +1980,9 @@ static int zram_add(void)
blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX); blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue); blk_queue_flag_set(QUEUE_FLAG_STABLE_WRITES, zram->disk->queue);
device_add_disk(NULL, zram->disk, zram_disk_attr_groups); ret = device_add_disk(NULL, zram->disk, zram_disk_attr_groups);
if (ret)
goto out_cleanup_disk;
strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor));
...@@ -1987,6 +1990,8 @@ static int zram_add(void) ...@@ -1987,6 +1990,8 @@ static int zram_add(void)
pr_info("Added device: %s\n", zram->disk->disk_name); pr_info("Added device: %s\n", zram->disk->disk_name);
return device_id; return device_id;
out_cleanup_disk:
blk_cleanup_disk(zram->disk);
out_free_idr: out_free_idr:
idr_remove(&zram_index_idr, device_id); idr_remove(&zram_index_idr, device_id);
out_free_dev: out_free_dev:
...@@ -1997,25 +2002,47 @@ static int zram_add(void) ...@@ -1997,25 +2002,47 @@ static int zram_add(void)
static int zram_remove(struct zram *zram) static int zram_remove(struct zram *zram)
{ {
struct block_device *bdev = zram->disk->part0; struct block_device *bdev = zram->disk->part0;
bool claimed;
mutex_lock(&bdev->bd_disk->open_mutex); mutex_lock(&bdev->bd_disk->open_mutex);
if (bdev->bd_openers || zram->claim) { if (bdev->bd_openers) {
mutex_unlock(&bdev->bd_disk->open_mutex); mutex_unlock(&bdev->bd_disk->open_mutex);
return -EBUSY; return -EBUSY;
} }
claimed = zram->claim;
if (!claimed)
zram->claim = true; zram->claim = true;
mutex_unlock(&bdev->bd_disk->open_mutex); mutex_unlock(&bdev->bd_disk->open_mutex);
zram_debugfs_unregister(zram); zram_debugfs_unregister(zram);
if (claimed) {
/*
* If we were claimed by reset_store(), del_gendisk() will
* wait until reset_store() is done, so nothing need to do.
*/
;
} else {
/* Make sure all the pending I/O are finished */ /* Make sure all the pending I/O are finished */
fsync_bdev(bdev); sync_blockdev(bdev);
zram_reset_device(zram); zram_reset_device(zram);
}
pr_info("Removed device: %s\n", zram->disk->disk_name); pr_info("Removed device: %s\n", zram->disk->disk_name);
del_gendisk(zram->disk); del_gendisk(zram->disk);
/* del_gendisk drains pending reset_store */
WARN_ON_ONCE(claimed && zram->claim);
/*
* disksize_store() may be called in between zram_reset_device()
* and del_gendisk(), so run the last reset to avoid leaking
* anything allocated with disksize_store()
*/
zram_reset_device(zram);
blk_cleanup_disk(zram->disk); blk_cleanup_disk(zram->disk);
kfree(zram); kfree(zram);
return 0; return 0;
...@@ -2092,7 +2119,7 @@ static struct class zram_control_class = { ...@@ -2092,7 +2119,7 @@ static struct class zram_control_class = {
static int zram_remove_cb(int id, void *ptr, void *data) static int zram_remove_cb(int id, void *ptr, void *data)
{ {
zram_remove(ptr); WARN_ON_ONCE(zram_remove(ptr));
return 0; return 0;
} }
......
...@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b) ...@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b)
struct bvec_iter_all iter_all; struct bvec_iter_all iter_all;
bio_for_each_segment_all(bv, b->bio, iter_all) { bio_for_each_segment_all(bv, b->bio, iter_all) {
memcpy(bvec_virt(bv), addr, PAGE_SIZE); memcpy(page_address(bv->bv_page), addr, PAGE_SIZE);
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
......
...@@ -885,9 +885,9 @@ static void bcache_device_free(struct bcache_device *d) ...@@ -885,9 +885,9 @@ static void bcache_device_free(struct bcache_device *d)
bcache_device_detach(d); bcache_device_detach(d);
if (disk) { if (disk) {
blk_cleanup_disk(disk);
ida_simple_remove(&bcache_device_idx, ida_simple_remove(&bcache_device_idx,
first_minor_to_idx(disk->first_minor)); first_minor_to_idx(disk->first_minor));
blk_cleanup_disk(disk);
} }
bioset_exit(&d->bio_split); bioset_exit(&d->bio_split);
......
...@@ -2469,11 +2469,30 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len) ...@@ -2469,11 +2469,30 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
{ {
unsigned long backlog; unsigned long backlog;
unsigned long old_mwb = mddev->bitmap_info.max_write_behind; unsigned long old_mwb = mddev->bitmap_info.max_write_behind;
struct md_rdev *rdev;
bool has_write_mostly = false;
int rv = kstrtoul(buf, 10, &backlog); int rv = kstrtoul(buf, 10, &backlog);
if (rv) if (rv)
return rv; return rv;
if (backlog > COUNTER_MAX) if (backlog > COUNTER_MAX)
return -EINVAL; return -EINVAL;
/*
* Without write mostly device, it doesn't make sense to set
* backlog for max_write_behind.
*/
rdev_for_each(rdev, mddev) {
if (test_bit(WriteMostly, &rdev->flags)) {
has_write_mostly = true;
break;
}
}
if (!has_write_mostly) {
pr_warn_ratelimited("%s: can't set backlog, no write mostly device available\n",
mdname(mddev));
return -EINVAL;
}
mddev->bitmap_info.max_write_behind = backlog; mddev->bitmap_info.max_write_behind = backlog;
if (!backlog && mddev->serial_info_pool) { if (!backlog && mddev->serial_info_pool) {
/* serial_info_pool is not needed if backlog is zero */ /* serial_info_pool is not needed if backlog is zero */
......
...@@ -1081,7 +1081,7 @@ static int ppl_load_distributed(struct ppl_log *log) ...@@ -1081,7 +1081,7 @@ static int ppl_load_distributed(struct ppl_log *log)
struct ppl_conf *ppl_conf = log->ppl_conf; struct ppl_conf *ppl_conf = log->ppl_conf;
struct md_rdev *rdev = log->rdev; struct md_rdev *rdev = log->rdev;
struct mddev *mddev = rdev->mddev; struct mddev *mddev = rdev->mddev;
struct page *page, *page2, *tmp; struct page *page, *page2;
struct ppl_header *pplhdr = NULL, *prev_pplhdr = NULL; struct ppl_header *pplhdr = NULL, *prev_pplhdr = NULL;
u32 crc, crc_stored; u32 crc, crc_stored;
u32 signature; u32 signature;
...@@ -1156,9 +1156,7 @@ static int ppl_load_distributed(struct ppl_log *log) ...@@ -1156,9 +1156,7 @@ static int ppl_load_distributed(struct ppl_log *log)
prev_pplhdr_offset = pplhdr_offset; prev_pplhdr_offset = pplhdr_offset;
prev_pplhdr = pplhdr; prev_pplhdr = pplhdr;
tmp = page; swap(page, page2);
page = page2;
page2 = tmp;
/* calculate next potential ppl offset */ /* calculate next potential ppl offset */
for (i = 0; i < le32_to_cpu(pplhdr->entries_count); i++) for (i = 0; i < le32_to_cpu(pplhdr->entries_count); i++)
......
...@@ -447,12 +447,18 @@ int ubiblock_create(struct ubi_volume_info *vi) ...@@ -447,12 +447,18 @@ int ubiblock_create(struct ubi_volume_info *vi)
list_add_tail(&dev->list, &ubiblock_devices); list_add_tail(&dev->list, &ubiblock_devices);
/* Must be the last step: anyone can call file ops from now on */ /* Must be the last step: anyone can call file ops from now on */
add_disk(dev->gd); ret = add_disk(dev->gd);
if (ret)
goto out_destroy_wq;
dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
dev->ubi_num, dev->vol_id, vi->name); dev->ubi_num, dev->vol_id, vi->name);
mutex_unlock(&devices_mutex); mutex_unlock(&devices_mutex);
return 0; return 0;
out_destroy_wq:
list_del(&dev->list);
destroy_workqueue(dev->wq);
out_remove_minor: out_remove_minor:
idr_remove(&ubiblock_minor_idr, gd->first_minor); idr_remove(&ubiblock_minor_idr, gd->first_minor);
out_cleanup_disk: out_cleanup_disk:
......
...@@ -239,6 +239,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk) ...@@ -239,6 +239,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
resource_size_t available_disk_size; resource_size_t available_disk_size;
struct gendisk *disk; struct gendisk *disk;
u64 internal_nlba; u64 internal_nlba;
int rc;
internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk)); internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk));
available_disk_size = internal_nlba * nsblk_sector_size(nsblk); available_disk_size = internal_nlba * nsblk_sector_size(nsblk);
...@@ -255,20 +256,28 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk) ...@@ -255,20 +256,28 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
blk_queue_logical_block_size(disk->queue, nsblk_sector_size(nsblk)); blk_queue_logical_block_size(disk->queue, nsblk_sector_size(nsblk));
blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue); blk_queue_flag_set(QUEUE_FLAG_NONROT, disk->queue);
if (devm_add_action_or_reset(dev, nd_blk_release_disk, disk))
return -ENOMEM;
if (nsblk_meta_size(nsblk)) { if (nsblk_meta_size(nsblk)) {
int rc = nd_integrity_init(disk, nsblk_meta_size(nsblk)); rc = nd_integrity_init(disk, nsblk_meta_size(nsblk));
if (rc) if (rc)
return rc; goto out_before_devm_err;
} }
set_capacity(disk, available_disk_size >> SECTOR_SHIFT); set_capacity(disk, available_disk_size >> SECTOR_SHIFT);
device_add_disk(dev, disk, NULL); rc = device_add_disk(dev, disk, NULL);
if (rc)
goto out_before_devm_err;
/* nd_blk_release_disk() is called if this fails */
if (devm_add_action_or_reset(dev, nd_blk_release_disk, disk))
return -ENOMEM;
nvdimm_check_and_set_ro(disk); nvdimm_check_and_set_ro(disk);
return 0; return 0;
out_before_devm_err:
blk_cleanup_disk(disk);
return rc;
} }
static int nd_blk_probe(struct device *dev) static int nd_blk_probe(struct device *dev)
......
...@@ -1519,6 +1519,7 @@ static int btt_blk_init(struct btt *btt) ...@@ -1519,6 +1519,7 @@ static int btt_blk_init(struct btt *btt)
{ {
struct nd_btt *nd_btt = btt->nd_btt; struct nd_btt *nd_btt = btt->nd_btt;
struct nd_namespace_common *ndns = nd_btt->ndns; struct nd_namespace_common *ndns = nd_btt->ndns;
int rc = -ENOMEM;
btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE); btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE);
if (!btt->btt_disk) if (!btt->btt_disk)
...@@ -1534,20 +1535,24 @@ static int btt_blk_init(struct btt *btt) ...@@ -1534,20 +1535,24 @@ static int btt_blk_init(struct btt *btt)
blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue); blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue);
if (btt_meta_size(btt)) { if (btt_meta_size(btt)) {
int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt)); rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
if (rc)
if (rc) { goto out_cleanup_disk;
del_gendisk(btt->btt_disk);
blk_cleanup_disk(btt->btt_disk);
return rc;
}
} }
set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9); set_capacity(btt->btt_disk, btt->nlba * btt->sector_size >> 9);
device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL); rc = device_add_disk(&btt->nd_btt->dev, btt->btt_disk, NULL);
if (rc)
goto out_cleanup_disk;
btt->nd_btt->size = btt->nlba * (u64)btt->sector_size; btt->nd_btt->size = btt->nlba * (u64)btt->sector_size;
nvdimm_check_and_set_ro(btt->btt_disk); nvdimm_check_and_set_ro(btt->btt_disk);
return 0; return 0;
out_cleanup_disk:
blk_cleanup_disk(btt->btt_disk);
return rc;
} }
static void btt_blk_cleanup(struct btt *btt) static void btt_blk_cleanup(struct btt *btt)
......
...@@ -428,8 +428,10 @@ static int pmem_attach_disk(struct device *dev, ...@@ -428,8 +428,10 @@ static int pmem_attach_disk(struct device *dev,
bb_range.end = res->end; bb_range.end = res->end;
} }
if (IS_ERR(addr)) if (IS_ERR(addr)) {
return PTR_ERR(addr); rc = PTR_ERR(addr);
goto out;
}
pmem->virt_addr = addr; pmem->virt_addr = addr;
blk_queue_write_cache(q, true, fua); blk_queue_write_cache(q, true, fua);
...@@ -454,12 +456,15 @@ static int pmem_attach_disk(struct device *dev, ...@@ -454,12 +456,15 @@ static int pmem_attach_disk(struct device *dev,
flags = DAXDEV_F_SYNC; flags = DAXDEV_F_SYNC;
dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags); dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags);
if (IS_ERR(dax_dev)) { if (IS_ERR(dax_dev)) {
return PTR_ERR(dax_dev); rc = PTR_ERR(dax_dev);
goto out;
} }
dax_write_cache(dax_dev, nvdimm_has_cache(nd_region)); dax_write_cache(dax_dev, nvdimm_has_cache(nd_region));
pmem->dax_dev = dax_dev; pmem->dax_dev = dax_dev;
device_add_disk(dev, disk, pmem_attribute_groups); rc = device_add_disk(dev, disk, pmem_attribute_groups);
if (rc)
goto out_cleanup_dax;
if (devm_add_action_or_reset(dev, pmem_release_disk, pmem)) if (devm_add_action_or_reset(dev, pmem_release_disk, pmem))
return -ENOMEM; return -ENOMEM;
...@@ -469,8 +474,14 @@ static int pmem_attach_disk(struct device *dev, ...@@ -469,8 +474,14 @@ static int pmem_attach_disk(struct device *dev,
"badblocks"); "badblocks");
if (!pmem->bb_state) if (!pmem->bb_state)
dev_warn(dev, "'badblocks' notification disabled\n"); dev_warn(dev, "'badblocks' notification disabled\n");
return 0; return 0;
out_cleanup_dax:
kill_dax(pmem->dax_dev);
put_dax(pmem->dax_dev);
out:
blk_cleanup_disk(pmem->disk);
return rc;
} }
static int nd_pmem_probe(struct device *dev) static int nd_pmem_probe(struct device *dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment