Merge branch 'upstream' of git://ftp.linux-mips.org/pub/scm/upstream-linus
[pandora-kernel.git] / drivers / block / loop.c
index b8af22e..d3a25b0 100644 (file)
@@ -82,6 +82,9 @@
 static LIST_HEAD(loop_devices);
 static DEFINE_MUTEX(loop_devices_mutex);
 
+static int max_part;
+static int part_shift;
+
 /*
  * Transfer functions
  */
@@ -543,7 +546,7 @@ static void loop_unplug(struct request_queue *q)
 {
        struct loop_device *lo = q->queuedata;
 
-       clear_bit(QUEUE_FLAG_PLUGGED, &q->queue_flags);
+       queue_flag_clear_unlocked(QUEUE_FLAG_PLUGGED, q);
        blk_run_address_space(lo->lo_backing_file->f_mapping);
 }
 
@@ -692,6 +695,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file,
                goto out_putf;
 
        fput(old_file);
+       if (max_part > 0)
+               ioctl_by_bdev(bdev, BLKRRPART, 0);
        return 0;
 
  out_putf:
@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file,
        }
        lo->lo_state = Lo_bound;
        wake_up_process(lo->lo_thread);
+       if (max_part > 0)
+               ioctl_by_bdev(bdev, BLKRRPART, 0);
        return 0;
 
 out_clr:
@@ -919,6 +926,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
        fput(filp);
        /* This is safe: open() is still holding a reference. */
        module_put(THIS_MODULE);
+       if (max_part > 0)
+               ioctl_by_bdev(bdev, BLKRRPART, 0);
        return 0;
 }
 
@@ -973,6 +982,10 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
        lo->transfer = xfer->transfer;
        lo->ioctl = xfer->ioctl;
 
+       if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) !=
+            (info->lo_flags & LO_FLAGS_AUTOCLEAR))
+               lo->lo_flags ^= LO_FLAGS_AUTOCLEAR;
+
        lo->lo_encrypt_key_size = info->lo_encrypt_key_size;
        lo->lo_init[0] = info->lo_init[0];
        lo->lo_init[1] = info->lo_init[1];
@@ -1331,6 +1344,10 @@ static int lo_release(struct inode *inode, struct file *file)
 
        mutex_lock(&lo->lo_ctl_mutex);
        --lo->lo_refcnt;
+
+       if ((lo->lo_flags & LO_FLAGS_AUTOCLEAR) && !lo->lo_refcnt)
+               loop_clr_fd(lo, inode->i_bdev);
+
        mutex_unlock(&lo->lo_ctl_mutex);
 
        return 0;
@@ -1352,6 +1369,8 @@ static struct block_device_operations lo_fops = {
 static int max_loop;
 module_param(max_loop, int, 0);
 MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
+module_param(max_part, int, 0);
+MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
 
@@ -1404,7 +1423,7 @@ static struct loop_device *loop_alloc(int i)
        if (!lo->lo_queue)
                goto out_free_dev;
 
-       disk = lo->lo_disk = alloc_disk(1);
+       disk = lo->lo_disk = alloc_disk(1 << part_shift);
        if (!disk)
                goto out_free_queue;
 
@@ -1414,7 +1433,7 @@ static struct loop_device *loop_alloc(int i)
        init_waitqueue_head(&lo->lo_event);
        spin_lock_init(&lo->lo_lock);
        disk->major             = LOOP_MAJOR;
-       disk->first_minor       = i;
+       disk->first_minor       = i << part_shift;
        disk->fops              = &lo_fops;
        disk->private_data      = lo;
        disk->queue             = lo->lo_queue;
@@ -1494,7 +1513,12 @@ static int __init loop_init(void)
         *     themselves and have kernel automatically instantiate actual
         *     device on-demand.
         */
-       if (max_loop > 1UL << MINORBITS)
+
+       part_shift = 0;
+       if (max_part > 0)
+               part_shift = fls(max_part);
+
+       if (max_loop > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
        if (max_loop) {
@@ -1502,7 +1526,7 @@ static int __init loop_init(void)
                range = max_loop;
        } else {
                nr = 8;
-               range = 1UL << MINORBITS;
+               range = 1UL << (MINORBITS - part_shift);
        }
 
        if (register_blkdev(LOOP_MAJOR, "loop"))
@@ -1541,7 +1565,7 @@ static void __exit loop_exit(void)
        unsigned long range;
        struct loop_device *lo, *next;
 
-       range = max_loop ? max_loop :  1UL << MINORBITS;
+       range = max_loop ? max_loop :  1UL << (MINORBITS - part_shift);
 
        list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
                loop_del_one(lo);