loop: preallocate eight loop devices
The kernel on-demand loop device instantiation breaks several user space tools as the tools are not ready to cope with the "on-demand feature". Fix it by instantiate default 8 loop devices and also reinstate max_loop module parameter. Signed-off-by: Ken Chen <kenchen@google.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
c287ef1ff9
commit
a47653fc26
|
@ -1354,7 +1354,7 @@ static struct block_device_operations lo_fops = {
|
|||
*/
|
||||
static int max_loop;
|
||||
module_param(max_loop, int, 0);
|
||||
MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand");
|
||||
MODULE_PARM_DESC(max_loop, "Maximum number of loop devices");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
|
||||
|
||||
|
@ -1394,16 +1394,11 @@ int loop_unregister_transfer(int number)
|
|||
EXPORT_SYMBOL(loop_register_transfer);
|
||||
EXPORT_SYMBOL(loop_unregister_transfer);
|
||||
|
||||
static struct loop_device *loop_init_one(int i)
|
||||
static struct loop_device *loop_alloc(int i)
|
||||
{
|
||||
struct loop_device *lo;
|
||||
struct gendisk *disk;
|
||||
|
||||
list_for_each_entry(lo, &loop_devices, lo_list) {
|
||||
if (lo->lo_number == i)
|
||||
return lo;
|
||||
}
|
||||
|
||||
lo = kzalloc(sizeof(*lo), GFP_KERNEL);
|
||||
if (!lo)
|
||||
goto out;
|
||||
|
@ -1427,8 +1422,6 @@ static struct loop_device *loop_init_one(int i)
|
|||
disk->private_data = lo;
|
||||
disk->queue = lo->lo_queue;
|
||||
sprintf(disk->disk_name, "loop%d", i);
|
||||
add_disk(disk);
|
||||
list_add_tail(&lo->lo_list, &loop_devices);
|
||||
return lo;
|
||||
|
||||
out_free_queue:
|
||||
|
@ -1439,15 +1432,37 @@ out:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void loop_del_one(struct loop_device *lo)
|
||||
static void loop_free(struct loop_device *lo)
|
||||
{
|
||||
del_gendisk(lo->lo_disk);
|
||||
blk_cleanup_queue(lo->lo_queue);
|
||||
put_disk(lo->lo_disk);
|
||||
list_del(&lo->lo_list);
|
||||
kfree(lo);
|
||||
}
|
||||
|
||||
static struct loop_device *loop_init_one(int i)
|
||||
{
|
||||
struct loop_device *lo;
|
||||
|
||||
list_for_each_entry(lo, &loop_devices, lo_list) {
|
||||
if (lo->lo_number == i)
|
||||
return lo;
|
||||
}
|
||||
|
||||
lo = loop_alloc(i);
|
||||
if (lo) {
|
||||
add_disk(lo->lo_disk);
|
||||
list_add_tail(&lo->lo_list, &loop_devices);
|
||||
}
|
||||
return lo;
|
||||
}
|
||||
|
||||
static void loop_del_one(struct loop_device *lo)
|
||||
{
|
||||
del_gendisk(lo->lo_disk);
|
||||
loop_free(lo);
|
||||
}
|
||||
|
||||
static struct kobject *loop_probe(dev_t dev, int *part, void *data)
|
||||
{
|
||||
struct loop_device *lo;
|
||||
|
@ -1464,28 +1479,77 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
|
|||
|
||||
static int __init loop_init(void)
|
||||
{
|
||||
if (register_blkdev(LOOP_MAJOR, "loop"))
|
||||
return -EIO;
|
||||
blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
|
||||
THIS_MODULE, loop_probe, NULL, NULL);
|
||||
int i, nr;
|
||||
unsigned long range;
|
||||
struct loop_device *lo, *next;
|
||||
|
||||
/*
|
||||
* loop module now has a feature to instantiate underlying device
|
||||
* structure on-demand, provided that there is an access dev node.
|
||||
* However, this will not work well with user space tool that doesn't
|
||||
* know about such "feature". In order to not break any existing
|
||||
* tool, we do the following:
|
||||
*
|
||||
* (1) if max_loop is specified, create that many upfront, and this
|
||||
* also becomes a hard limit.
|
||||
* (2) if max_loop is not specified, create 8 loop device on module
|
||||
* load, user can further extend loop device by create dev node
|
||||
* themselves and have kernel automatically instantiate actual
|
||||
* device on-demand.
|
||||
*/
|
||||
if (max_loop > 1UL << MINORBITS)
|
||||
return -EINVAL;
|
||||
|
||||
if (max_loop) {
|
||||
printk(KERN_INFO "loop: the max_loop option is obsolete "
|
||||
"and will be removed in March 2008\n");
|
||||
|
||||
nr = max_loop;
|
||||
range = max_loop;
|
||||
} else {
|
||||
nr = 8;
|
||||
range = 1UL << MINORBITS;
|
||||
}
|
||||
|
||||
if (register_blkdev(LOOP_MAJOR, "loop"))
|
||||
return -EIO;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
lo = loop_alloc(i);
|
||||
if (!lo)
|
||||
goto Enomem;
|
||||
list_add_tail(&lo->lo_list, &loop_devices);
|
||||
}
|
||||
|
||||
/* point of no return */
|
||||
|
||||
list_for_each_entry(lo, &loop_devices, lo_list)
|
||||
add_disk(lo->lo_disk);
|
||||
|
||||
blk_register_region(MKDEV(LOOP_MAJOR, 0), range,
|
||||
THIS_MODULE, loop_probe, NULL, NULL);
|
||||
|
||||
printk(KERN_INFO "loop: module loaded\n");
|
||||
return 0;
|
||||
|
||||
Enomem:
|
||||
printk(KERN_INFO "loop: out of memory\n");
|
||||
|
||||
list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
|
||||
loop_free(lo);
|
||||
|
||||
unregister_blkdev(LOOP_MAJOR, "loop");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static void __exit loop_exit(void)
|
||||
{
|
||||
unsigned long range;
|
||||
struct loop_device *lo, *next;
|
||||
|
||||
range = max_loop ? max_loop : 1UL << MINORBITS;
|
||||
|
||||
list_for_each_entry_safe(lo, next, &loop_devices, lo_list)
|
||||
loop_del_one(lo);
|
||||
|
||||
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS);
|
||||
blk_unregister_region(MKDEV(LOOP_MAJOR, 0), range);
|
||||
if (unregister_blkdev(LOOP_MAJOR, "loop"))
|
||||
printk(KERN_WARNING "loop: cannot unregister blkdev\n");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue