Merge tag 'driver-core-6.2-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[sfrench/cifs-2.6.git] / block / genhd.c
index 0f9769db2de83405352dab021dacbe3f0ca91d0c..ab3cbe44196f77c1b69a6847813997d3396e96b0 100644 (file)
@@ -356,7 +356,7 @@ void disk_uevent(struct gendisk *disk, enum kobject_action action)
 }
 EXPORT_SYMBOL_GPL(disk_uevent);
 
-int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
+int disk_scan_partitions(struct gendisk *disk, fmode_t mode, void *owner)
 {
        struct block_device *bdev;
 
@@ -366,6 +366,9 @@ int disk_scan_partitions(struct gendisk *disk, fmode_t mode)
                return -EINVAL;
        if (disk->open_partitions)
                return -EBUSY;
+       /* Someone else has bdev exclusively open? */
+       if (disk->part0->bd_holder && disk->part0->bd_holder != owner)
+               return -EBUSY;
 
        set_bit(GD_NEED_PART_SCAN, &disk->state);
        bdev = blkdev_get_by_dev(disk_devt(disk), mode, NULL);
@@ -479,10 +482,6 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
                goto out_put_holder_dir;
        }
 
-       ret = bd_register_pending_holders(disk);
-       if (ret < 0)
-               goto out_put_slave_dir;
-
        ret = blk_register_queue(disk);
        if (ret)
                goto out_put_slave_dir;
@@ -500,7 +499,7 @@ int __must_check device_add_disk(struct device *parent, struct gendisk *disk,
 
                bdev_add(disk->part0, ddev->devt);
                if (get_capacity(disk))
-                       disk_scan_partitions(disk, FMODE_READ);
+                       disk_scan_partitions(disk, FMODE_READ, NULL);
 
                /*
                 * Announce the disk and partitions after all partitions are
@@ -530,6 +529,7 @@ out_unregister_queue:
        rq_qos_exit(disk->queue);
 out_put_slave_dir:
        kobject_put(disk->slave_dir);
+       disk->slave_dir = NULL;
 out_put_holder_dir:
        kobject_put(disk->part0->bd_holder_dir);
 out_del_integrity:
@@ -560,6 +560,11 @@ void blk_mark_disk_dead(struct gendisk *disk)
 {
        set_bit(GD_DEAD, &disk->state);
        blk_queue_start_drain(disk->queue);
+
+       /*
+        * Stop buffered writers from dirtying pages that can't be written out.
+        */
+       set_capacity_and_notify(disk, 0);
 }
 EXPORT_SYMBOL_GPL(blk_mark_disk_dead);
 
@@ -629,6 +634,7 @@ void del_gendisk(struct gendisk *disk)
 
        kobject_put(disk->part0->bd_holder_dir);
        kobject_put(disk->slave_dir);
+       disk->slave_dir = NULL;
 
        part_stat_set_all(disk->part0, 0);
        disk->part0->bd_stamp = 0;
@@ -643,7 +649,9 @@ void del_gendisk(struct gendisk *disk)
 
        blk_sync_queue(q);
        blk_flush_integrity();
-       blk_mq_cancel_work_sync(q);
+
+       if (queue_is_mq(q))
+               blk_mq_cancel_work_sync(q);
 
        blk_mq_quiesce_queue(q);
        if (q->elevator) {
@@ -1181,9 +1189,9 @@ static void disk_release(struct device *dev)
        iput(disk->part0->bd_inode);    /* frees the disk */
 }
 
-static int block_uevent(struct device *dev, struct kobj_uevent_env *env)
+static int block_uevent(const struct device *dev, struct kobj_uevent_env *env)
 {
-       struct gendisk *disk = dev_to_disk(dev);
+       const struct gendisk *disk = dev_to_disk(dev);
 
        return add_uevent_var(env, "DISKSEQ=%llu", disk->diskseq);
 }
@@ -1193,21 +1201,10 @@ struct class block_class = {
        .dev_uevent     = block_uevent,
 };
 
-static char *block_devnode(struct device *dev, umode_t *mode,
-                          kuid_t *uid, kgid_t *gid)
-{
-       struct gendisk *disk = dev_to_disk(dev);
-
-       if (disk->fops->devnode)
-               return disk->fops->devnode(disk, mode);
-       return NULL;
-}
-
 const struct device_type disk_type = {
        .name           = "disk",
        .groups         = disk_attr_groups,
        .release        = disk_release,
-       .devnode        = block_devnode,
 };
 
 #ifdef CONFIG_PROC_FS
@@ -1412,7 +1409,7 @@ struct gendisk *__blk_alloc_disk(int node, struct lock_class_key *lkclass)
        struct request_queue *q;
        struct gendisk *disk;
 
-       q = blk_alloc_queue(node, false);
+       q = blk_alloc_queue(node);
        if (!q)
                return NULL;