The extra call to blk_alloc_queue results in an extra bdi_init
that corrupts the per-cpu stat lists of the backing dev info,
resulting in a WARNING about list_del corruption on
percpu_counter_destroy when doing "rmmod aoe" or "aoeflush -a"
when AoE targets have been detected and initialized by the
system.

Although the mainline does not have this extra call, 3.7.y does,
so this change cherry picks the commit from the mainline that
eliminates the extra call to blk_alloc_queue.

References:

  RedHat bugzilla ticket with original report
  https://bugzilla.redhat.com/show_bug.cgi?id=853064

  LKML discussion of bug and fix
  http://thread.gmane.org/gmane.linux.kernel/1416336/focus=1416497

Original changelog:

  commit 0a41409c518083133e79015092585d68915865be
  Author: Ed Cashin <[email protected]>
  Date:   Mon Dec 17 16:03:58 2012 -0800

    aoe: remove vestigial request queue allocation

    Before the aoe driver was an I/O request handler, it was a
    make_request-style block driver.  Even so, there was a problem where
    sysfs expected a request queue to exist, so one was provided in commit
    7135a71b19be ("aoe: allocate unused request_queue for sysfs").

    During the transition to the request-handler style, a patch was merged
    that was based on a driver without the noop queue, and the noop queue
    remained in place after the patch was merged, even though a new
    functional queue was introduced by the patch, allocated through
    blk_init_queue.

    The user impact is a memory leak proportional to the number of AoE
    targets discovered.  This patch removes the memory leak and cleans up
    vestiges of the old do-nothing queue from the aoeblk_gdalloc function.

    Signed-off-by: Ed Cashin <[email protected]>
    Signed-off-by: Andrew Morton <[email protected]>
    Signed-off-by: Linus Torvalds <[email protected]>

Reported-by: Josh Boyer <[email protected]>
---
 drivers/block/aoe/aoe.h    |    2 +-
 drivers/block/aoe/aoeblk.c |   17 ++++-------------
 2 files changed, 5 insertions(+), 14 deletions(-)

diff --git a/drivers/block/aoe/aoe.h b/drivers/block/aoe/aoe.h
index d2ed7f1..28653b5 100644
--- a/drivers/block/aoe/aoe.h
+++ b/drivers/block/aoe/aoe.h
@@ -1,5 +1,5 @@
 /* Copyright (c) 2012 Coraid, Inc.  See COPYING for GPL terms. */
-#define VERSION "50"
+#define VERSION "50q"
 #define AOE_MAJOR 152
 #define DEVICE_NAME "aoe"
 
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index 00dfc50..047baf0 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -231,18 +231,12 @@ aoeblk_gdalloc(void *vp)
        if (q == NULL) {
                pr_err("aoe: cannot allocate block queue for %ld.%d\n",
                        d->aoemajor, d->aoeminor);
-               mempool_destroy(mp);
-               goto err_disk;
+               goto err_mempool;
        }
 
-       d->blkq = blk_alloc_queue(GFP_KERNEL);
-       if (!d->blkq)
-               goto err_mempool;
-       d->blkq->backing_dev_info.name = "aoe";
-       if (bdi_init(&d->blkq->backing_dev_info))
-               goto err_blkq;
        spin_lock_irqsave(&d->lock, flags);
-       blk_queue_max_hw_sectors(d->blkq, BLK_DEF_MAX_SECTORS);
+       blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS);
+       q->backing_dev_info.name = "aoe";
        q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_CACHE_SIZE;
        d->bufpool = mp;
        d->blkq = gd->queue = q;
@@ -265,11 +259,8 @@ aoeblk_gdalloc(void *vp)
        aoedisk_add_sysfs(d);
        return;
 
-err_blkq:
-       blk_cleanup_queue(d->blkq);
-       d->blkq = NULL;
 err_mempool:
-       mempool_destroy(d->bufpool);
+       mempool_destroy(mp);
 err_disk:
        put_disk(gd);
 err:
-- 
1.7.1

--
To unsubscribe from this list: send the line "unsubscribe stable" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to