[S390] xpram: per device block request queues.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 10 Oct 2008 19:33:24 +0000 (21:33 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 10 Oct 2008 19:33:59 +0000 (21:33 +0200)
The xpram driver uses a single block device queue for all of its
devices so far. With recent kernels removing xpram module fails to
clean up all sysfs files. The next time the xpram module is loaded
you'll get warnings:

  WARNING: at fs/sysfs/dir.c:463 sysfs_add_one+0x5e/0x64()
  sysfs: duplicate filename '35:0' can not be created
  Modules linked in: xpram(+) [last unloaded: xpram]

Followed by the usual WARN_ON output, followed by an error message
from kobject_add_internal, followed by a badness in genhd. Allocating
a block queue per device fixes this.

Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
drivers/s390/block/xpram.c

index dd9b986389a2bf4a2d38a71a64c01dfe25718ef3..03916989ed2d63ec7a45966353c8350e260640ad 100644 (file)
@@ -56,6 +56,7 @@ typedef struct {
 static xpram_device_t xpram_devices[XPRAM_MAX_DEVS];
 static unsigned int xpram_sizes[XPRAM_MAX_DEVS];
 static struct gendisk *xpram_disks[XPRAM_MAX_DEVS];
+static struct request_queue *xpram_queues[XPRAM_MAX_DEVS];
 static unsigned int xpram_pages;
 static int xpram_devs;
 
@@ -330,18 +331,22 @@ static int __init xpram_setup_sizes(unsigned long pages)
        return 0;
 }
 
-static struct request_queue *xpram_queue;
-
 static int __init xpram_setup_blkdev(void)
 {
        unsigned long offset;
        int i, rc = -ENOMEM;
 
        for (i = 0; i < xpram_devs; i++) {
-               struct gendisk *disk = alloc_disk(1);
-               if (!disk)
+               xpram_disks[i] = alloc_disk(1);
+               if (!xpram_disks[i])
+                       goto out;
+               xpram_queues[i] = blk_alloc_queue(GFP_KERNEL);
+               if (!xpram_queues[i]) {
+                       put_disk(xpram_disks[i]);
                        goto out;
-               xpram_disks[i] = disk;
+               }
+               blk_queue_make_request(xpram_queues[i], xpram_make_request);
+               blk_queue_hardsect_size(xpram_queues[i], 4096);
        }
 
        /*
@@ -351,18 +356,6 @@ static int __init xpram_setup_blkdev(void)
        if (rc < 0)
                goto out;
 
-       /*
-        * Assign the other needed values: make request function, sizes and
-        * hardsect size. All the minor devices feature the same value.
-        */
-       xpram_queue = blk_alloc_queue(GFP_KERNEL);
-       if (!xpram_queue) {
-               rc = -ENOMEM;
-               goto out_unreg;
-       }
-       blk_queue_make_request(xpram_queue, xpram_make_request);
-       blk_queue_hardsect_size(xpram_queue, 4096);
-
        /*
         * Setup device structures.
         */
@@ -377,18 +370,18 @@ static int __init xpram_setup_blkdev(void)
                disk->first_minor = i;
                disk->fops = &xpram_devops;
                disk->private_data = &xpram_devices[i];
-               disk->queue = xpram_queue;
+               disk->queue = xpram_queues[i];
                sprintf(disk->disk_name, "slram%d", i);
                set_capacity(disk, xpram_sizes[i] << 1);
                add_disk(disk);
        }
 
        return 0;
-out_unreg:
-       unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
 out:
-       while (i--)
+       while (i--) {
+               blk_cleanup_queue(xpram_queues[i]);
                put_disk(xpram_disks[i]);
+       }
        return rc;
 }
 
@@ -400,10 +393,10 @@ static void __exit xpram_exit(void)
        int i;
        for (i = 0; i < xpram_devs; i++) {
                del_gendisk(xpram_disks[i]);
+               blk_cleanup_queue(xpram_queues[i]);
                put_disk(xpram_disks[i]);
        }
        unregister_blkdev(XPRAM_MAJOR, XPRAM_NAME);
-       blk_cleanup_queue(xpram_queue);
 }
 
 static int __init xpram_init(void)