Merge tag 'for-5.16/drivers-2021-11-09' of git://git.kernel.dk/linux-block
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Nov 2021 19:24:08 +0000 (11:24 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Nov 2021 19:24:08 +0000 (11:24 -0800)
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
  ...

20 files changed:
block/genhd.c
drivers/block/ataflop.c
drivers/block/brd.c
drivers/block/drbd/drbd_main.c
drivers/block/floppy.c
drivers/block/loop.c
drivers/block/nbd.c
drivers/block/ps3disk.c
drivers/block/ps3vram.c
drivers/block/sunvdc.c
drivers/block/z2ram.c
drivers/block/zram/zram_drv.c
drivers/md/bcache/btree.c
drivers/md/bcache/super.c
drivers/md/md-bitmap.c
drivers/md/raid5-ppl.c
drivers/mtd/ubi/block.c
drivers/nvdimm/blk.c
drivers/nvdimm/btt.c
drivers/nvdimm/pmem.c

index a4e9e8e..ca2fbab 100644 (file)
@@ -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 = 0, try to allocate any unused major number.
  * @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.
  *
index d14bdc3..bf769e6 100644 (file)
@@ -2008,8 +2008,6 @@ static int ataflop_alloc_disk(unsigned int drive, unsigned int type)
        return 0;
 }
 
-static DEFINE_MUTEX(ataflop_probe_lock);
-
 static void ataflop_probe(dev_t dev)
 {
        int drive = MINOR(dev) & 3;
@@ -2020,14 +2018,38 @@ static void ataflop_probe(dev_t dev)
 
        if (drive >= FD_MAX_UNITS || type >= NUM_DISK_MINORS)
                return;
-       mutex_lock(&ataflop_probe_lock);
-       if (!unit[drive].disk[type]) {
-               if (ataflop_alloc_disk(drive, type) == 0) {
-                       add_disk(unit[drive].disk[type]);
-                       unit[drive].registered[type] = true;
+       if (unit[drive].disk[type])
+               return;
+       if (ataflop_alloc_disk(drive, type))
+               return;
+       if (add_disk(unit[drive].disk[type]))
+               goto cleanup_disk;
+       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)
@@ -2053,11 +2075,6 @@ static int __init atari_floppy_init (void)
                /* Amiga, Mac, ... don't have Atari-compatible floppy :-) */
                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++) {
                memset(&unit[i].tag_set, 0, sizeof(unit[i].tag_set));
                unit[i].tag_set.ops = &ataflop_mq_ops;
@@ -2113,7 +2130,12 @@ static int __init atari_floppy_init (void)
               UseTrackbuffer ? "" : "no ");
        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:
        atari_stram_free(DMABuffer);
@@ -2121,9 +2143,6 @@ err:
        while (--i >= 0)
                atari_cleanup_floppy_disk(&unit[i]);
 
-       unregister_blkdev(FLOPPY_MAJOR, "fd");
-out_unlock:
-       mutex_unlock(&ataflop_probe_lock);
        return ret;
 }
 
@@ -2168,14 +2187,8 @@ __setup("floppy=", atari_floppy_setup);
 
 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");
-
-       del_timer_sync(&fd_timer);
-       atari_stram_free( DMABuffer );
+       atari_floppy_cleanup();
 }
 
 module_init(atari_floppy_init)
index aa04727..a896ee1 100644 (file)
@@ -370,6 +370,7 @@ static int brd_alloc(int i)
        struct brd_device *brd;
        struct gendisk *disk;
        char buf[DISK_NAME_LEN];
+       int err = -ENOMEM;
 
        mutex_lock(&brd_devices_mutex);
        list_for_each_entry(brd, &brd_devices, brd_list) {
@@ -420,16 +421,20 @@ static int brd_alloc(int i)
        /* Tell the block layer that this is not a rotational device */
        blk_queue_flag_set(QUEUE_FLAG_NONROT, 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;
 
+out_cleanup_disk:
+       blk_cleanup_disk(disk);
 out_free_dev:
        mutex_lock(&brd_devices_mutex);
        list_del(&brd->brd_list);
        mutex_unlock(&brd_devices_mutex);
        kfree(brd);
-       return -ENOMEM;
+       return err;
 }
 
 static void brd_probe(dev_t dev)
index 19db80a..53ba2dd 100644 (file)
@@ -2796,7 +2796,7 @@ enum drbd_ret_code drbd_create_device(struct drbd_config_context *adm_ctx, unsig
 
        err = add_disk(disk);
        if (err)
-               goto out_cleanup_disk;
+               goto out_idr_remove_vol;
 
        /* inherit the connection state */
        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
        drbd_debugfs_device_add(device);
        return NO_ERROR;
 
-out_cleanup_disk:
-       blk_cleanup_disk(disk);
 out_idr_remove_vol:
        idr_remove(&connection->peer_devices, vnr);
 out_idr_remove_from_resource:
index 3873e78..c4267da 100644 (file)
@@ -4528,10 +4528,19 @@ static void floppy_probe(dev_t dev)
                return;
 
        mutex_lock(&floppy_probe_lock);
-       if (!disks[drive][type]) {
-               if (floppy_alloc_disk(drive, type) == 0)
-                       add_disk(disks[drive][type]);
-       }
+       if (disks[drive][type])
+               goto out;
+       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);
 }
 
index 3c09a33..a154cab 100644 (file)
@@ -1983,7 +1983,6 @@ static int loop_add(int i)
                goto out_free_dev;
        i = err;
 
-       err = -ENOMEM;
        lo->tag_set.ops = &loop_mq_ops;
        lo->tag_set.nr_hw_queues = 1;
        lo->tag_set.queue_depth = 128;
index b47b2a8..5a1f984 100644 (file)
@@ -260,7 +260,7 @@ static void nbd_dev_remove(struct nbd_device *nbd)
        mutex_lock(&nbd_index_mutex);
        idr_remove(&nbd_index_idr, nbd->index);
        mutex_unlock(&nbd_index_mutex);
-
+       destroy_workqueue(nbd->recv_workq);
        kfree(nbd);
 }
 
@@ -755,6 +755,8 @@ static struct nbd_cmd *nbd_handle_reply(struct nbd_device *nbd, int index,
        if (cmd->index != index) {
                dev_err(disk_to_dev(nbd->disk), "Unexpected reply %d from different sock %d (expected %d)",
                        tag, index, cmd->index);
+               ret = -ENOENT;
+               goto out;
        }
        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",
@@ -1314,10 +1316,6 @@ static void nbd_config_put(struct nbd_device *nbd)
                kfree(nbd->config);
                nbd->config = NULL;
 
-               if (nbd->recv_workq)
-                       destroy_workqueue(nbd->recv_workq);
-               nbd->recv_workq = NULL;
-
                nbd->tag_set.timeout = 0;
                nbd->disk->queue->limits.discard_granularity = 0;
                nbd->disk->queue->limits.discard_alignment = 0;
@@ -1346,14 +1344,6 @@ static int nbd_start_device(struct nbd_device *nbd)
                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);
        nbd->pid = task_pid_nr(current);
 
@@ -1779,6 +1769,15 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
        }
        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
         */
@@ -1803,13 +1802,13 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
        disk->major = NBD_MAJOR;
 
        /* Too big first_minor can cause duplicate creation of
-        * sysfs files/links, since first_minor will be truncated to
-        * byte in __device_add_disk().
+        * sysfs files/links, since index << part_shift might overflow, or
+        * MKDEV() expect that the max bits of first_minor is 20.
         */
        disk->first_minor = index << part_shift;
-       if (disk->first_minor > 0xff) {
+       if (disk->first_minor < index || disk->first_minor > MINORMASK) {
                err = -EINVAL;
-               goto out_free_idr;
+               goto out_free_work;
        }
 
        disk->minors = 1 << part_shift;
@@ -1818,7 +1817,7 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
        sprintf(disk->disk_name, "nbd%d", index);
        err = add_disk(disk);
        if (err)
-               goto out_err_disk;
+               goto out_free_work;
 
        /*
         * Now publish the device.
@@ -1827,6 +1826,8 @@ static struct nbd_device *nbd_dev_add(int index, unsigned int refs)
        nbd_total_devices++;
        return nbd;
 
+out_free_work:
+       destroy_workqueue(nbd->recv_workq);
 out_err_disk:
        blk_cleanup_disk(disk);
 out_free_idr:
@@ -2082,13 +2083,10 @@ static void nbd_disconnect_and_put(struct nbd_device *nbd)
        nbd_disconnect(nbd);
        sock_shutdown(nbd);
        /*
-        * Make sure recv thread has finished, so it does not drop the last
-        * 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()
+        * Make sure recv thread has finished, we can safely call nbd_clear_que()
         * 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->task_setup = NULL;
        mutex_unlock(&nbd->config_lock);
index 8d51efb..3054adf 100644 (file)
@@ -467,9 +467,13 @@ static int ps3disk_probe(struct ps3_system_bus_device *_dev)
                 gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
                 get_capacity(gendisk) >> 11);
 
-       device_add_disk(&dev->sbd.core, gendisk, NULL);
-       return 0;
+       error = device_add_disk(&dev->sbd.core, gendisk, NULL);
+       if (error)
+               goto fail_cleanup_disk;
 
+       return 0;
+fail_cleanup_disk:
+       blk_cleanup_disk(gendisk);
 fail_free_tag_set:
        blk_mq_free_tag_set(&priv->tag_set);
 fail_teardown:
index d1ebf19..c187664 100644 (file)
@@ -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",
                 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;
 
+out_cleanup_disk:
+       blk_cleanup_disk(gendisk);
 out_cache_cleanup:
        remove_proc_entry(DEVICE_NAME, NULL);
        ps3vram_cache_cleanup(dev);
index 4d4bb81..6f45a53 100644 (file)
@@ -826,8 +826,8 @@ static int probe_disk(struct vdc_port *port)
        if (IS_ERR(g)) {
                printk(KERN_ERR PFX "%s: Could not allocate gendisk.\n",
                       port->vio.name);
-               blk_mq_free_tag_set(&port->tag_set);
-               return PTR_ERR(g);
+               err = PTR_ERR(g);
+               goto out_free_tag;
        }
 
        port->disk = g;
@@ -879,9 +879,17 @@ static int probe_disk(struct vdc_port *port)
               port->vdisk_size, (port->vdisk_size >> (20 - 9)),
               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;
+
+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 = {
index 4eef218..ccc52c9 100644 (file)
@@ -318,6 +318,7 @@ static const struct blk_mq_ops z2_mq_ops = {
 static int z2ram_register_disk(int minor)
 {
        struct gendisk *disk;
+       int err;
 
        disk = blk_mq_alloc_disk(&tag_set, NULL);
        if (IS_ERR(disk))
@@ -333,8 +334,10 @@ static int z2ram_register_disk(int minor)
                sprintf(disk->disk_name, "z2ram");
 
        z2ram_gendisk[minor] = disk;
-       add_disk(disk);
-       return 0;
+       err = add_disk(disk);
+       if (err)
+               blk_cleanup_disk(disk);
+       return err;
 }
 
 static int __init z2_init(void)
index c8931ba..08d7953 100644 (file)
@@ -1734,12 +1734,13 @@ static void zram_reset_device(struct zram *zram)
        set_capacity_and_notify(zram->disk, 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 */
        zram_meta_free(zram, disksize);
        memset(&zram->stats, 0, sizeof(zram->stats));
        zcomp_destroy(comp);
        reset_bdev(zram);
+
+       up_write(&zram->init_lock);
 }
 
 static ssize_t disksize_store(struct device *dev,
@@ -1819,7 +1820,7 @@ static ssize_t reset_store(struct device *dev,
        mutex_unlock(&bdev->bd_disk->open_mutex);
 
        /* Make sure all the pending I/O are finished */
-       fsync_bdev(bdev);
+       sync_blockdev(bdev);
        zram_reset_device(zram);
 
        mutex_lock(&bdev->bd_disk->open_mutex);
@@ -1979,7 +1980,9 @@ static int zram_add(void)
                blk_queue_max_write_zeroes_sectors(zram->disk->queue, UINT_MAX);
 
        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));
 
@@ -1987,6 +1990,8 @@ static int zram_add(void)
        pr_info("Added device: %s\n", zram->disk->disk_name);
        return device_id;
 
+out_cleanup_disk:
+       blk_cleanup_disk(zram->disk);
 out_free_idr:
        idr_remove(&zram_index_idr, device_id);
 out_free_dev:
@@ -1997,25 +2002,47 @@ out_free_dev:
 static int zram_remove(struct zram *zram)
 {
        struct block_device *bdev = zram->disk->part0;
+       bool claimed;
 
        mutex_lock(&bdev->bd_disk->open_mutex);
-       if (bdev->bd_openers || zram->claim) {
+       if (bdev->bd_openers) {
                mutex_unlock(&bdev->bd_disk->open_mutex);
                return -EBUSY;
        }
 
-       zram->claim = true;
+       claimed = zram->claim;
+       if (!claimed)
+               zram->claim = true;
        mutex_unlock(&bdev->bd_disk->open_mutex);
 
        zram_debugfs_unregister(zram);
 
-       /* Make sure all the pending I/O are finished */
-       fsync_bdev(bdev);
-       zram_reset_device(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 */
+               sync_blockdev(bdev);
+               zram_reset_device(zram);
+       }
 
        pr_info("Removed device: %s\n", zram->disk->disk_name);
 
        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);
        kfree(zram);
        return 0;
@@ -2092,7 +2119,7 @@ static struct class zram_control_class = {
 
 static int zram_remove_cb(int id, void *ptr, void *data)
 {
-       zram_remove(ptr);
+       WARN_ON_ONCE(zram_remove(ptr));
        return 0;
 }
 
index 93b67b8..88c573e 100644 (file)
@@ -378,7 +378,7 @@ static void do_btree_node_write(struct btree *b)
                struct bvec_iter_all 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;
                }
 
index 4a9a65d..86b9e35 100644 (file)
@@ -885,9 +885,9 @@ static void bcache_device_free(struct bcache_device *d)
                bcache_device_detach(d);
 
        if (disk) {
-               blk_cleanup_disk(disk);
                ida_simple_remove(&bcache_device_idx,
                                  first_minor_to_idx(disk->first_minor));
+               blk_cleanup_disk(disk);
        }
 
        bioset_exit(&d->bio_split);
index e29c629..bfd6026 100644 (file)
@@ -2469,11 +2469,30 @@ backlog_store(struct mddev *mddev, const char *buf, size_t len)
 {
        unsigned long backlog;
        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);
        if (rv)
                return rv;
        if (backlog > COUNTER_MAX)
                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;
        if (!backlog && mddev->serial_info_pool) {
                /* serial_info_pool is not needed if backlog is zero */
index 3ddc2aa..4ab4179 100644 (file)
@@ -1081,7 +1081,7 @@ static int ppl_load_distributed(struct ppl_log *log)
        struct ppl_conf *ppl_conf = log->ppl_conf;
        struct md_rdev *rdev = log->rdev;
        struct mddev *mddev = rdev->mddev;
-       struct page *page, *page2, *tmp;
+       struct page *page, *page2;
        struct ppl_header *pplhdr = NULL, *prev_pplhdr = NULL;
        u32 crc, crc_stored;
        u32 signature;
@@ -1156,9 +1156,7 @@ static int ppl_load_distributed(struct ppl_log *log)
                prev_pplhdr_offset = pplhdr_offset;
                prev_pplhdr = pplhdr;
 
-               tmp = page;
-               page = page2;
-               page2 = tmp;
+               swap(page, page2);
 
                /* calculate next potential ppl offset */
                for (i = 0; i < le32_to_cpu(pplhdr->entries_count); i++)
index e003b4b..062e6c2 100644 (file)
@@ -447,12 +447,18 @@ int ubiblock_create(struct ubi_volume_info *vi)
        list_add_tail(&dev->list, &ubiblock_devices);
 
        /* 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->ubi_num, dev->vol_id, vi->name);
        mutex_unlock(&devices_mutex);
        return 0;
 
+out_destroy_wq:
+       list_del(&dev->list);
+       destroy_workqueue(dev->wq);
 out_remove_minor:
        idr_remove(&ubiblock_minor_idr, gd->first_minor);
 out_cleanup_disk:
index b6c6866..228c33b 100644 (file)
@@ -239,6 +239,7 @@ static int nsblk_attach_disk(struct nd_namespace_blk *nsblk)
        resource_size_t available_disk_size;
        struct gendisk *disk;
        u64 internal_nlba;
+       int rc;
 
        internal_nlba = div_u64(nsblk->size, nsblk_internal_lbasize(nsblk));
        available_disk_size = internal_nlba * nsblk_sector_size(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_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)) {
-               int rc = nd_integrity_init(disk, nsblk_meta_size(nsblk));
+               rc = nd_integrity_init(disk, nsblk_meta_size(nsblk));
 
                if (rc)
-                       return rc;
+                       goto out_before_devm_err;
        }
 
        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);
        return 0;
+
+out_before_devm_err:
+       blk_cleanup_disk(disk);
+       return rc;
 }
 
 static int nd_blk_probe(struct device *dev)
index f10a50f..da3f007 100644 (file)
@@ -1519,6 +1519,7 @@ static int btt_blk_init(struct btt *btt)
 {
        struct nd_btt *nd_btt = btt->nd_btt;
        struct nd_namespace_common *ndns = nd_btt->ndns;
+       int rc = -ENOMEM;
 
        btt->btt_disk = blk_alloc_disk(NUMA_NO_NODE);
        if (!btt->btt_disk)
@@ -1534,20 +1535,24 @@ static int btt_blk_init(struct btt *btt)
        blk_queue_flag_set(QUEUE_FLAG_NONROT, btt->btt_disk->queue);
 
        if (btt_meta_size(btt)) {
-               int rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
-
-               if (rc) {
-                       del_gendisk(btt->btt_disk);
-                       blk_cleanup_disk(btt->btt_disk);
-                       return rc;
-               }
+               rc = nd_integrity_init(btt->btt_disk, btt_meta_size(btt));
+               if (rc)
+                       goto out_cleanup_disk;
        }
+
        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;
        nvdimm_check_and_set_ro(btt->btt_disk);
 
        return 0;
+
+out_cleanup_disk:
+       blk_cleanup_disk(btt->btt_disk);
+       return rc;
 }
 
 static void btt_blk_cleanup(struct btt *btt)
index c74d7bc..37fc030 100644 (file)
@@ -428,8 +428,10 @@ static int pmem_attach_disk(struct device *dev,
                bb_range.end = res->end;
        }
 
-       if (IS_ERR(addr))
-               return PTR_ERR(addr);
+       if (IS_ERR(addr)) {
+               rc = PTR_ERR(addr);
+               goto out;
+       }
        pmem->virt_addr = addr;
 
        blk_queue_write_cache(q, true, fua);
@@ -454,12 +456,15 @@ static int pmem_attach_disk(struct device *dev,
                flags = DAXDEV_F_SYNC;
        dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags);
        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));
        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))
                return -ENOMEM;
 
@@ -469,8 +474,14 @@ static int pmem_attach_disk(struct device *dev,
                                          "badblocks");
        if (!pmem->bb_state)
                dev_warn(dev, "'badblocks' notification disabled\n");
-
        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)