]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - block/partition-generic.c
block: fix an integer overflow in logical block size
[mirror_ubuntu-bionic-kernel.git] / block / partition-generic.c
index 91622db9aedffd997947642a5872802312346869..afde86374081ef9d4b574a55fd6a1c4d43c74b52 100644 (file)
@@ -51,6 +51,12 @@ const char *bdevname(struct block_device *bdev, char *buf)
 
 EXPORT_SYMBOL(bdevname);
 
+const char *bio_devname(struct bio *bio, char *buf)
+{
+       return disk_name(bio->bi_disk, bio->bi_partno, buf);
+}
+EXPORT_SYMBOL(bio_devname);
+
 /*
  * There's very little reason to use this, you should really
  * have a struct block_device just about everywhere and use
@@ -139,13 +145,15 @@ ssize_t part_stat_show(struct device *dev,
                jiffies_to_msecs(part_stat_read(p, time_in_queue)));
 }
 
-ssize_t part_inflight_show(struct device *dev,
-                       struct device_attribute *attr, char *buf)
+ssize_t part_inflight_show(struct device *dev, struct device_attribute *attr,
+                          char *buf)
 {
        struct hd_struct *p = dev_to_part(dev);
+       struct request_queue *q = part_to_disk(p)->queue;
+       unsigned int inflight[2];
 
-       return sprintf(buf, "%8u %8u\n", atomic_read(&p->in_flight[0]),
-               atomic_read(&p->in_flight[1]));
+       part_in_flight_rw(q, p, inflight);
+       return sprintf(buf, "%8u %8u\n", inflight[0], inflight[1]);
 }
 
 #ifdef CONFIG_FAIL_MAKE_REQUEST
@@ -237,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;
@@ -250,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);
 }
 
 /*
@@ -275,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);
 }