brd: handle on-demand devices correctly
[linux-flexiantxendom0-natty.git] / drivers / block / brd.c
index 1d2c186..c94bc48 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/highmem.h>
+#include <linux/mutex.h>
 #include <linux/radix-tree.h>
 #include <linux/buffer_head.h> /* invalidate_bh_lrus() */
 #include <linux/slab.h>
@@ -54,6 +55,7 @@ struct brd_device {
 /*
  * Look up and return a brd's page for a given sector.
  */
+static DEFINE_MUTEX(brd_mutex);
 static struct page *brd_lookup_page(struct brd_device *brd, sector_t sector)
 {
        pgoff_t idx;
@@ -401,6 +403,7 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
         * ram device BLKFLSBUF has special semantics, we want to actually
         * release and destroy the ramdisk data.
         */
+       mutex_lock(&brd_mutex);
        mutex_lock(&bdev->bd_mutex);
        error = -EBUSY;
        if (bdev->bd_openers <= 1) {
@@ -417,13 +420,14 @@ static int brd_ioctl(struct block_device *bdev, fmode_t mode,
                error = 0;
        }
        mutex_unlock(&bdev->bd_mutex);
+       mutex_unlock(&brd_mutex);
 
        return error;
 }
 
 static const struct block_device_operations brd_fops = {
        .owner =                THIS_MODULE,
-       .locked_ioctl =         brd_ioctl,
+       .ioctl =                brd_ioctl,
 #ifdef CONFIG_BLK_DEV_XIP
        .direct_access =        brd_direct_access,
 #endif
@@ -479,7 +483,6 @@ static struct brd_device *brd_alloc(int i)
        if (!brd->brd_queue)
                goto out_free_dev;
        blk_queue_make_request(brd->brd_queue, brd_make_request);
-       blk_queue_ordered(brd->brd_queue, QUEUE_ORDERED_TAG);
        blk_queue_max_hw_sectors(brd->brd_queue, 1024);
        blk_queue_bounce_limit(brd->brd_queue, BLK_BOUNCE_ANY);
 
@@ -549,7 +552,7 @@ static struct kobject *brd_probe(dev_t dev, int *part, void *data)
        struct kobject *kobj;
 
        mutex_lock(&brd_devices_mutex);
-       brd = brd_init_one(dev & MINORMASK);
+       brd = brd_init_one(MINOR(dev) >> part_shift);
        kobj = brd ? get_disk(brd->brd_disk) : ERR_PTR(-ENOMEM);
        mutex_unlock(&brd_devices_mutex);
 
@@ -582,15 +585,18 @@ static int __init brd_init(void)
        if (max_part > 0)
                part_shift = fls(max_part);
 
+       if ((1UL << part_shift) > DISK_MAX_PARTS)
+               return -EINVAL;
+
        if (rd_nr > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
        if (rd_nr) {
                nr = rd_nr;
-               range = rd_nr;
+               range = rd_nr << part_shift;
        } else {
                nr = CONFIG_BLK_DEV_RAM_COUNT;
-               range = 1UL << (MINORBITS - part_shift);
+               range = 1UL << MINORBITS;
        }
 
        if (register_blkdev(RAMDISK_MAJOR, "ramdisk"))
@@ -629,7 +635,7 @@ static void __exit brd_exit(void)
        unsigned long range;
        struct brd_device *brd, *next;
 
-       range = rd_nr ? rd_nr :  1UL << (MINORBITS - part_shift);
+       range = rd_nr ? rd_nr << part_shift : 1UL << MINORBITS;
 
        list_for_each_entry_safe(brd, next, &brd_devices, brd_list)
                brd_del_one(brd);