From: Ben Hutchings <b...@decadent.org.uk>

Since commit 523e1d3 ('block: make gendisk hold a reference to its
queue'), add_disk() adds a reference to disk->queue, which is then
dropped by disk_release().  But if a disk is destroyed without being
registered through add_disk() (or if add_disk() fails at the first
hurdle) then we have a reference imbalance.

Use the GENHD_FL_UP flag to tell whether this extra reference has been
added.  Remove the incomplete workaround from the floppy driver.

Cc: sta...@vger.kernel.org
Acked-by: Herton Ronaldo Krzesinski <herton.krzesin...@canonical.com>
Signed-off-by: Ben Hutchings <b...@decadent.org.uk>
---
 block/genhd.c          |    6 +++---
 drivers/block/floppy.c |   16 +---------------
 2 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/block/genhd.c b/block/genhd.c
index d839723..633751d 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -587,8 +587,6 @@ void add_disk(struct gendisk *disk)
        WARN_ON(disk->minors && !(disk->major || disk->first_minor));
        WARN_ON(!disk->minors && !(disk->flags & GENHD_FL_EXT_DEVT));
 
-       disk->flags |= GENHD_FL_UP;
-
        retval = blk_alloc_devt(&disk->part0, &devt);
        if (retval) {
                WARN_ON(1);
@@ -596,6 +594,8 @@ void add_disk(struct gendisk *disk)
        }
        disk_to_dev(disk)->devt = devt;
 
+       disk->flags |= GENHD_FL_UP;
+
        /* ->major and ->first_minor aren't supposed to be
         * dereferenced from here on, but set them just in case.
         */
@@ -1105,7 +1105,7 @@ static void disk_release(struct device *dev)
        disk_replace_part_tbl(disk, NULL);
        free_part_stats(&disk->part0);
        free_part_info(&disk->part0);
-       if (disk->queue)
+       if (disk->queue && disk->flags & GENHD_FL_UP)
                blk_put_queue(disk->queue);
        kfree(disk);
 }
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 1e09e99..32551f2 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4322,14 +4322,8 @@ out_unreg_blkdev:
 out_put_disk:
        while (dr--) {
                del_timer_sync(&motor_off_timer[dr]);
-               if (disks[dr]->queue) {
+               if (disks[dr]->queue)
                        blk_cleanup_queue(disks[dr]->queue);
-                       /*
-                        * put_disk() is not paired with add_disk() and
-                        * will put queue reference one extra time. fix it.
-                        */
-                       disks[dr]->queue = NULL;
-               }
                put_disk(disks[dr]);
        }
        destroy_workqueue(floppy_wq);
@@ -4558,14 +4552,6 @@ static void __exit floppy_module_exit(void)
                }
                blk_cleanup_queue(disks[drive]->queue);
 
-               /*
-                * These disks have not called add_disk().  Don't put down
-                * queue reference in put_disk().
-                */
-               if (!(allowed_drive_mask & (1 << drive)) ||
-                   fdc_state[FDC(drive)].version == FDC_NONE)
-                       disks[drive]->queue = NULL;
-
                put_disk(disks[drive]);
        }
 
-- 
1.7.9.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to