|
|
@@ -518,6 +518,18 @@ void blk_free_devt(dev_t devt)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * We invalidate devt by assigning NULL pointer for devt in idr.
|
|
|
+ */
|
|
|
+void blk_invalidate_devt(dev_t devt)
|
|
|
+{
|
|
|
+ if (MAJOR(devt) == BLOCK_EXT_MAJOR) {
|
|
|
+ spin_lock_bh(&ext_devt_lock);
|
|
|
+ idr_replace(&ext_devt_idr, NULL, blk_mangle_minor(MINOR(devt)));
|
|
|
+ spin_unlock_bh(&ext_devt_lock);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static char *bdevt_str(dev_t devt, char *buf)
|
|
|
{
|
|
|
if (MAJOR(devt) <= 0xff && MINOR(devt) <= 0xff) {
|
|
|
@@ -769,6 +781,13 @@ void del_gendisk(struct gendisk *disk)
|
|
|
|
|
|
if (!(disk->flags & GENHD_FL_HIDDEN))
|
|
|
blk_unregister_region(disk_devt(disk), disk->minors);
|
|
|
+ /*
|
|
|
+ * 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(disk_devt(disk));
|
|
|
|
|
|
kobject_put(disk->part0.holder_dir);
|
|
|
kobject_put(disk->slave_dir);
|