Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
[platform/kernel/linux-starfive.git] / drivers / block / loop.c
index a076a14..76c8da7 100644 (file)
@@ -1540,9 +1540,9 @@ static const struct block_device_operations lo_fops = {
  * And now the modules code and kernel interface.
  */
 static int max_loop;
-module_param(max_loop, int, 0);
+module_param(max_loop, int, S_IRUGO);
 MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
-module_param(max_part, int, 0);
+module_param(max_part, int, S_IRUGO);
 MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -1658,7 +1658,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
        struct kobject *kobj;
 
        mutex_lock(&loop_devices_mutex);
-       lo = loop_init_one(dev & MINORMASK);
+       lo = loop_init_one(MINOR(dev) >> part_shift);
        kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
        mutex_unlock(&loop_devices_mutex);
 
@@ -1688,18 +1688,32 @@ static int __init loop_init(void)
         */
 
        part_shift = 0;
-       if (max_part > 0)
+       if (max_part > 0) {
                part_shift = fls(max_part);
 
+               /*
+                * Adjust max_part according to part_shift as it is exported
+                * to user space so that user can decide correct minor number
+                * if [s]he want to create more devices.
+                *
+                * Note that -1 is required because partition 0 is reserved
+                * for the whole disk.
+                */
+               max_part = (1UL << part_shift) - 1;
+       }
+
+       if ((1UL << part_shift) > DISK_MAX_PARTS)
+               return -EINVAL;
+
        if (max_loop > 1UL << (MINORBITS - part_shift))
                return -EINVAL;
 
        if (max_loop) {
                nr = max_loop;
-               range = max_loop;
+               range = max_loop << part_shift;
        } else {
                nr = 8;
-               range = 1UL << (MINORBITS - part_shift);
+               range = 1UL << MINORBITS;
        }
 
        if (register_blkdev(LOOP_MAJOR, "loop"))
@@ -1738,7 +1752,7 @@ static void __exit loop_exit(void)
        unsigned long range;
        struct loop_device *lo, *next;
 
-       range = max_loop ? max_loop :  1UL << (MINORBITS - part_shift);
+       range = max_loop ? max_loop << part_shift : 1UL << MINORBITS;
 
        list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
                loop_del_one(lo);