diff options
-rw-r--r-- | drivers/block/loop.c | 184 | ||||
-rw-r--r-- | include/linux/loop.h | 2 |
2 files changed, 112 insertions, 74 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 0d4ccd4a0957..af6d7274a7cc 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -77,9 +77,8 @@ | |||
77 | 77 | ||
78 | #include <asm/uaccess.h> | 78 | #include <asm/uaccess.h> |
79 | 79 | ||
80 | static int max_loop = 8; | 80 | static LIST_HEAD(loop_devices); |
81 | static struct loop_device *loop_dev; | 81 | static DEFINE_MUTEX(loop_devices_mutex); |
82 | static struct gendisk **disks; | ||
83 | 82 | ||
84 | /* | 83 | /* |
85 | * Transfer functions | 84 | * Transfer functions |
@@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo) | |||
183 | if (unlikely((loff_t)x != size)) | 182 | if (unlikely((loff_t)x != size)) |
184 | return -EFBIG; | 183 | return -EFBIG; |
185 | 184 | ||
186 | set_capacity(disks[lo->lo_number], x); | 185 | set_capacity(lo->lo_disk, x); |
187 | return 0; | 186 | return 0; |
188 | } | 187 | } |
189 | 188 | ||
@@ -812,7 +811,7 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, | |||
812 | lo->lo_queue->queuedata = lo; | 811 | lo->lo_queue->queuedata = lo; |
813 | lo->lo_queue->unplug_fn = loop_unplug; | 812 | lo->lo_queue->unplug_fn = loop_unplug; |
814 | 813 | ||
815 | set_capacity(disks[lo->lo_number], size); | 814 | set_capacity(lo->lo_disk, size); |
816 | bd_set_size(bdev, size << 9); | 815 | bd_set_size(bdev, size << 9); |
817 | 816 | ||
818 | set_blocksize(bdev, lo_blocksize); | 817 | set_blocksize(bdev, lo_blocksize); |
@@ -832,7 +831,7 @@ out_clr: | |||
832 | lo->lo_device = NULL; | 831 | lo->lo_device = NULL; |
833 | lo->lo_backing_file = NULL; | 832 | lo->lo_backing_file = NULL; |
834 | lo->lo_flags = 0; | 833 | lo->lo_flags = 0; |
835 | set_capacity(disks[lo->lo_number], 0); | 834 | set_capacity(lo->lo_disk, 0); |
836 | invalidate_bdev(bdev); | 835 | invalidate_bdev(bdev); |
837 | bd_set_size(bdev, 0); | 836 | bd_set_size(bdev, 0); |
838 | mapping_set_gfp_mask(mapping, lo->old_gfp_mask); | 837 | mapping_set_gfp_mask(mapping, lo->old_gfp_mask); |
@@ -918,7 +917,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
918 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); | 917 | memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); |
919 | memset(lo->lo_file_name, 0, LO_NAME_SIZE); | 918 | memset(lo->lo_file_name, 0, LO_NAME_SIZE); |
920 | invalidate_bdev(bdev); | 919 | invalidate_bdev(bdev); |
921 | set_capacity(disks[lo->lo_number], 0); | 920 | set_capacity(lo->lo_disk, 0); |
922 | bd_set_size(bdev, 0); | 921 | bd_set_size(bdev, 0); |
923 | mapping_set_gfp_mask(filp->f_mapping, gfp); | 922 | mapping_set_gfp_mask(filp->f_mapping, gfp); |
924 | lo->lo_state = Lo_unbound; | 923 | lo->lo_state = Lo_unbound; |
@@ -1322,6 +1321,18 @@ static long lo_compat_ioctl(struct file *file, unsigned int cmd, unsigned long a | |||
1322 | } | 1321 | } |
1323 | #endif | 1322 | #endif |
1324 | 1323 | ||
1324 | static struct loop_device *loop_find_dev(int number) | ||
1325 | { | ||
1326 | struct loop_device *lo; | ||
1327 | |||
1328 | list_for_each_entry(lo, &loop_devices, lo_list) { | ||
1329 | if (lo->lo_number == number) | ||
1330 | return lo; | ||
1331 | } | ||
1332 | return NULL; | ||
1333 | } | ||
1334 | |||
1335 | static struct loop_device *loop_init_one(int i); | ||
1325 | static int lo_open(struct inode *inode, struct file *file) | 1336 | static int lo_open(struct inode *inode, struct file *file) |
1326 | { | 1337 | { |
1327 | struct loop_device *lo = inode->i_bdev->bd_disk->private_data; | 1338 | struct loop_device *lo = inode->i_bdev->bd_disk->private_data; |
@@ -1330,6 +1341,11 @@ static int lo_open(struct inode *inode, struct file *file) | |||
1330 | lo->lo_refcnt++; | 1341 | lo->lo_refcnt++; |
1331 | mutex_unlock(&lo->lo_ctl_mutex); | 1342 | mutex_unlock(&lo->lo_ctl_mutex); |
1332 | 1343 | ||
1344 | mutex_lock(&loop_devices_mutex); | ||
1345 | if (!loop_find_dev(lo->lo_number + 1)) | ||
1346 | loop_init_one(lo->lo_number + 1); | ||
1347 | mutex_unlock(&loop_devices_mutex); | ||
1348 | |||
1333 | return 0; | 1349 | return 0; |
1334 | } | 1350 | } |
1335 | 1351 | ||
@@ -1357,8 +1373,9 @@ static struct block_device_operations lo_fops = { | |||
1357 | /* | 1373 | /* |
1358 | * And now the modules code and kernel interface. | 1374 | * And now the modules code and kernel interface. |
1359 | */ | 1375 | */ |
1376 | static int max_loop; | ||
1360 | module_param(max_loop, int, 0); | 1377 | module_param(max_loop, int, 0); |
1361 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); | 1378 | MODULE_PARM_DESC(max_loop, "obsolete, loop device is created on-demand"); |
1362 | MODULE_LICENSE("GPL"); | 1379 | MODULE_LICENSE("GPL"); |
1363 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); | 1380 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); |
1364 | 1381 | ||
@@ -1383,7 +1400,7 @@ int loop_unregister_transfer(int number) | |||
1383 | 1400 | ||
1384 | xfer_funcs[n] = NULL; | 1401 | xfer_funcs[n] = NULL; |
1385 | 1402 | ||
1386 | for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { | 1403 | list_for_each_entry(lo, &loop_devices, lo_list) { |
1387 | mutex_lock(&lo->lo_ctl_mutex); | 1404 | mutex_lock(&lo->lo_ctl_mutex); |
1388 | 1405 | ||
1389 | if (lo->lo_encryption == xfer) | 1406 | if (lo->lo_encryption == xfer) |
@@ -1398,91 +1415,110 @@ int loop_unregister_transfer(int number) | |||
1398 | EXPORT_SYMBOL(loop_register_transfer); | 1415 | EXPORT_SYMBOL(loop_register_transfer); |
1399 | EXPORT_SYMBOL(loop_unregister_transfer); | 1416 | EXPORT_SYMBOL(loop_unregister_transfer); |
1400 | 1417 | ||
1401 | static int __init loop_init(void) | 1418 | static struct loop_device *loop_init_one(int i) |
1419 | { | ||
1420 | struct loop_device *lo; | ||
1421 | struct gendisk *disk; | ||
1422 | |||
1423 | lo = kzalloc(sizeof(*lo), GFP_KERNEL); | ||
1424 | if (!lo) | ||
1425 | goto out; | ||
1426 | |||
1427 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); | ||
1428 | if (!lo->lo_queue) | ||
1429 | goto out_free_dev; | ||
1430 | |||
1431 | disk = lo->lo_disk = alloc_disk(1); | ||
1432 | if (!disk) | ||
1433 | goto out_free_queue; | ||
1434 | |||
1435 | mutex_init(&lo->lo_ctl_mutex); | ||
1436 | lo->lo_number = i; | ||
1437 | lo->lo_thread = NULL; | ||
1438 | init_waitqueue_head(&lo->lo_event); | ||
1439 | spin_lock_init(&lo->lo_lock); | ||
1440 | disk->major = LOOP_MAJOR; | ||
1441 | disk->first_minor = i; | ||
1442 | disk->fops = &lo_fops; | ||
1443 | disk->private_data = lo; | ||
1444 | disk->queue = lo->lo_queue; | ||
1445 | sprintf(disk->disk_name, "loop%d", i); | ||
1446 | add_disk(disk); | ||
1447 | list_add_tail(&lo->lo_list, &loop_devices); | ||
1448 | return lo; | ||
1449 | |||
1450 | out_free_queue: | ||
1451 | blk_cleanup_queue(lo->lo_queue); | ||
1452 | out_free_dev: | ||
1453 | kfree(lo); | ||
1454 | out: | ||
1455 | return ERR_PTR(-ENOMEM); | ||
1456 | } | ||
1457 | |||
1458 | static void loop_del_one(struct loop_device *lo) | ||
1402 | { | 1459 | { |
1403 | int i; | 1460 | del_gendisk(lo->lo_disk); |
1461 | blk_cleanup_queue(lo->lo_queue); | ||
1462 | put_disk(lo->lo_disk); | ||
1463 | list_del(&lo->lo_list); | ||
1464 | kfree(lo); | ||
1465 | } | ||
1404 | 1466 | ||
1405 | if (max_loop < 1 || max_loop > 256) { | 1467 | static struct kobject *loop_probe(dev_t dev, int *part, void *data) |
1406 | printk(KERN_WARNING "loop: invalid max_loop (must be between" | 1468 | { |
1407 | " 1 and 256), using default (8)\n"); | 1469 | unsigned int number = dev & MINORMASK; |
1408 | max_loop = 8; | 1470 | struct loop_device *lo; |
1409 | } | 1471 | |
1472 | mutex_lock(&loop_devices_mutex); | ||
1473 | lo = loop_find_dev(number); | ||
1474 | if (lo == NULL) | ||
1475 | lo = loop_init_one(number); | ||
1476 | mutex_unlock(&loop_devices_mutex); | ||
1477 | |||
1478 | *part = 0; | ||
1479 | if (IS_ERR(lo)) | ||
1480 | return (void *)lo; | ||
1481 | else | ||
1482 | return &lo->lo_disk->kobj; | ||
1483 | } | ||
1484 | |||
1485 | static int __init loop_init(void) | ||
1486 | { | ||
1487 | struct loop_device *lo; | ||
1410 | 1488 | ||
1411 | if (register_blkdev(LOOP_MAJOR, "loop")) | 1489 | if (register_blkdev(LOOP_MAJOR, "loop")) |
1412 | return -EIO; | 1490 | return -EIO; |
1491 | blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, | ||
1492 | THIS_MODULE, loop_probe, NULL, NULL); | ||
1413 | 1493 | ||
1414 | loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); | 1494 | lo = loop_init_one(0); |
1415 | if (!loop_dev) | 1495 | if (IS_ERR(lo)) |
1416 | goto out_mem1; | 1496 | goto out; |
1417 | memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); | ||
1418 | 1497 | ||
1419 | disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); | 1498 | if (max_loop) { |
1420 | if (!disks) | 1499 | printk(KERN_INFO "loop: the max_loop option is obsolete " |
1421 | goto out_mem2; | 1500 | "and will be removed in March 2008\n"); |
1422 | 1501 | ||
1423 | for (i = 0; i < max_loop; i++) { | ||
1424 | disks[i] = alloc_disk(1); | ||
1425 | if (!disks[i]) | ||
1426 | goto out_mem3; | ||
1427 | } | 1502 | } |
1428 | 1503 | printk(KERN_INFO "loop: module loaded\n"); | |
1429 | for (i = 0; i < max_loop; i++) { | ||
1430 | struct loop_device *lo = &loop_dev[i]; | ||
1431 | struct gendisk *disk = disks[i]; | ||
1432 | |||
1433 | memset(lo, 0, sizeof(*lo)); | ||
1434 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); | ||
1435 | if (!lo->lo_queue) | ||
1436 | goto out_mem4; | ||
1437 | mutex_init(&lo->lo_ctl_mutex); | ||
1438 | lo->lo_number = i; | ||
1439 | lo->lo_thread = NULL; | ||
1440 | init_waitqueue_head(&lo->lo_event); | ||
1441 | spin_lock_init(&lo->lo_lock); | ||
1442 | disk->major = LOOP_MAJOR; | ||
1443 | disk->first_minor = i; | ||
1444 | disk->fops = &lo_fops; | ||
1445 | sprintf(disk->disk_name, "loop%d", i); | ||
1446 | disk->private_data = lo; | ||
1447 | disk->queue = lo->lo_queue; | ||
1448 | } | ||
1449 | |||
1450 | /* We cannot fail after we call this, so another loop!*/ | ||
1451 | for (i = 0; i < max_loop; i++) | ||
1452 | add_disk(disks[i]); | ||
1453 | printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); | ||
1454 | return 0; | 1504 | return 0; |
1455 | 1505 | ||
1456 | out_mem4: | 1506 | out: |
1457 | while (i--) | ||
1458 | blk_cleanup_queue(loop_dev[i].lo_queue); | ||
1459 | i = max_loop; | ||
1460 | out_mem3: | ||
1461 | while (i--) | ||
1462 | put_disk(disks[i]); | ||
1463 | kfree(disks); | ||
1464 | out_mem2: | ||
1465 | kfree(loop_dev); | ||
1466 | out_mem1: | ||
1467 | unregister_blkdev(LOOP_MAJOR, "loop"); | 1507 | unregister_blkdev(LOOP_MAJOR, "loop"); |
1468 | printk(KERN_ERR "loop: ran out of memory\n"); | 1508 | printk(KERN_ERR "loop: ran out of memory\n"); |
1469 | return -ENOMEM; | 1509 | return -ENOMEM; |
1470 | } | 1510 | } |
1471 | 1511 | ||
1472 | static void loop_exit(void) | 1512 | static void __exit loop_exit(void) |
1473 | { | 1513 | { |
1474 | int i; | 1514 | struct loop_device *lo, *next; |
1475 | 1515 | ||
1476 | for (i = 0; i < max_loop; i++) { | 1516 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) |
1477 | del_gendisk(disks[i]); | 1517 | loop_del_one(lo); |
1478 | blk_cleanup_queue(loop_dev[i].lo_queue); | 1518 | |
1479 | put_disk(disks[i]); | 1519 | blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); |
1480 | } | ||
1481 | if (unregister_blkdev(LOOP_MAJOR, "loop")) | 1520 | if (unregister_blkdev(LOOP_MAJOR, "loop")) |
1482 | printk(KERN_WARNING "loop: cannot unregister blkdev\n"); | 1521 | printk(KERN_WARNING "loop: cannot unregister blkdev\n"); |
1483 | |||
1484 | kfree(disks); | ||
1485 | kfree(loop_dev); | ||
1486 | } | 1522 | } |
1487 | 1523 | ||
1488 | module_init(loop_init); | 1524 | module_init(loop_init); |
diff --git a/include/linux/loop.h b/include/linux/loop.h index 191a595055f0..0b99b31f017b 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h | |||
@@ -64,6 +64,8 @@ struct loop_device { | |||
64 | wait_queue_head_t lo_event; | 64 | wait_queue_head_t lo_event; |
65 | 65 | ||
66 | request_queue_t *lo_queue; | 66 | request_queue_t *lo_queue; |
67 | struct gendisk *lo_disk; | ||
68 | struct list_head lo_list; | ||
67 | }; | 69 | }; |
68 | 70 | ||
69 | #endif /* __KERNEL__ */ | 71 | #endif /* __KERNEL__ */ |