]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/partition-generic.c
blk-mq: move cancel of requeue_work to the front of blk_exit_queue
[mirror_ubuntu-bionic-kernel.git] / block / partition-generic.c
index db57cced9b987371e6c8a3c72ff6721b9d540bda..afde86374081ef9d4b574a55fd6a1c4d43c74b52 100644 (file)
@@ -245,9 +245,10 @@ struct device_type part_type = {
        .uevent         = part_uevent,
 };
 
-static void delete_partition_rcu_cb(struct rcu_head *head)
+static void delete_partition_work_fn(struct work_struct *work)
 {
-       struct hd_struct *part = container_of(head, struct hd_struct, rcu_head);
+       struct hd_struct *part = container_of(to_rcu_work(work), struct hd_struct,
+                                       rcu_work);
 
        part->start_sect = 0;
        part->nr_sects = 0;
@@ -258,7 +259,8 @@ static void delete_partition_rcu_cb(struct rcu_head *head)
 void __delete_partition(struct percpu_ref *ref)
 {
        struct hd_struct *part = container_of(ref, struct hd_struct, ref);
-       call_rcu(&part->rcu_head, delete_partition_rcu_cb);
+       INIT_RCU_WORK(&part->rcu_work, delete_partition_work_fn);
+       queue_rcu_work(system_wq, &part->rcu_work);
 }
 
 /*
@@ -283,6 +285,13 @@ void delete_partition(struct gendisk *disk, int partno)
        kobject_put(part->holder_dir);
        device_del(part_to_dev(part));
 
+       /*
+        * Remove gendisk pointer from idr so that it cannot be looked up
+        * while RCU period before freeing gendisk is running to prevent
+        * use-after-free issues. Note that the device number stays
+        * "in-use" until we really free the gendisk.
+        */
+       blk_invalidate_devt(part_devt(part));
        hd_struct_kill(part);
 }