block: bio-integrity: Advance seed correctly for larger interval sizes
[platform/kernel/linux-rpi.git] / block / genhd.c
index b498585..de789d1 100644 (file)
@@ -420,6 +420,8 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
                                DISK_MAX_PARTS);
                        disk->minors = DISK_MAX_PARTS;
                }
+               if (disk->first_minor + disk->minors > MINORMASK + 1)
+                       return -EINVAL;
        } else {
                if (WARN_ON(disk->minors))
                        return -EINVAL;
@@ -432,10 +434,6 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
                disk->flags |= GENHD_FL_EXT_DEVT;
        }
 
-       ret = disk_alloc_events(disk);
-       if (ret)
-               goto out_free_ext_minor;
-
        /* delay uevents, until we scanned partition table */
        dev_set_uevent_suppress(ddev, 1);
 
@@ -446,7 +444,12 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
                ddev->devt = MKDEV(disk->major, disk->first_minor);
        ret = device_add(ddev);
        if (ret)
-               goto out_disk_release_events;
+               goto out_free_ext_minor;
+
+       ret = disk_alloc_events(disk);
+       if (ret)
+               goto out_device_del;
+
        if (!sysfs_deprecated) {
                ret = sysfs_create_link(block_depr, &ddev->kobj,
                                        kobject_name(&ddev->kobj));
@@ -467,11 +470,15 @@ int device_add_disk(struct device *parent, struct gendisk *disk,
 
        disk->part0->bd_holder_dir =
                kobject_create_and_add("holders", &ddev->kobj);
-       if (!disk->part0->bd_holder_dir)
+       if (!disk->part0->bd_holder_dir) {
+               ret = -ENOMEM;
                goto out_del_integrity;
+       }
        disk->slave_dir = kobject_create_and_add("slaves", &ddev->kobj);
-       if (!disk->slave_dir)
+       if (!disk->slave_dir) {
+               ret = -ENOMEM;
                goto out_put_holder_dir;
+       }
 
        ret = bd_register_pending_holders(disk);
        if (ret < 0)
@@ -530,8 +537,6 @@ out_del_block_link:
                sysfs_remove_link(block_depr, dev_name(ddev));
 out_device_del:
        device_del(ddev);
-out_disk_release_events:
-       disk_release_events(disk);
 out_free_ext_minor:
        if (disk->major == BLOCK_EXT_MAJOR)
                blk_free_ext_minor(disk->first_minor);
@@ -588,16 +593,6 @@ void del_gendisk(struct gendisk *disk)
         * Prevent new I/O from crossing bio_queue_enter().
         */
        blk_queue_start_drain(q);
-       blk_mq_freeze_queue_wait(q);
-
-       rq_qos_exit(q);
-       blk_sync_queue(q);
-       blk_flush_integrity();
-       /*
-        * Allow using passthrough request again after the queue is torn down.
-        */
-       blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
-       __blk_mq_unfreeze_queue(q, true);
 
        if (!(disk->flags & GENHD_FL_HIDDEN)) {
                sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
@@ -620,6 +615,18 @@ void del_gendisk(struct gendisk *disk)
                sysfs_remove_link(block_depr, dev_name(disk_to_dev(disk)));
        pm_runtime_set_memalloc_noio(disk_to_dev(disk), false);
        device_del(disk_to_dev(disk));
+
+       blk_mq_freeze_queue_wait(q);
+
+       rq_qos_exit(q);
+       blk_sync_queue(q);
+       blk_flush_integrity();
+       /*
+        * Allow using passthrough request again after the queue is torn down.
+        */
+       blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
+       __blk_mq_unfreeze_queue(q, true);
+
 }
 EXPORT_SYMBOL(del_gendisk);
 
@@ -1080,6 +1087,8 @@ static void disk_release(struct device *dev)
        might_sleep();
        WARN_ON_ONCE(disk_live(disk));
 
+       blk_mq_cancel_work_sync(disk->queue);
+
        disk_release_events(disk);
        kfree(disk->random);
        xa_destroy(&disk->part_tbl);