diff options
author | Laurent Vivier <Laurent.Vivier@bull.net> | 2008-03-26 07:11:53 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2008-04-21 03:50:08 -0400 |
commit | 476a4813cfddf7cf159956cc0e2d3c830c1507e3 (patch) | |
tree | 11c824363b8ea789ccb3c6f3b38320bcf79b3aa4 | |
parent | 22a9189fd073db3d03a4cf8b8c098aa207602de1 (diff) |
loop: manage partitions in disk image
This patch allows to use loop device with partitionned disk image.
Original behavior of loop is not modified.
A new parameter is introduced to define how many partition we want to be
able to manage per loop device. This parameter is "max_part".
For instance, to manage 63 partitions / loop device, we will do:
# modprobe loop max_part=63
# ls -l /dev/loop?*
brw-rw---- 1 root disk 7, 0 2008-03-05 14:55 /dev/loop0
brw-rw---- 1 root disk 7, 64 2008-03-05 14:55 /dev/loop1
brw-rw---- 1 root disk 7, 128 2008-03-05 14:55 /dev/loop2
brw-rw---- 1 root disk 7, 192 2008-03-05 14:55 /dev/loop3
brw-rw---- 1 root disk 7, 256 2008-03-05 14:55 /dev/loop4
brw-rw---- 1 root disk 7, 320 2008-03-05 14:55 /dev/loop5
brw-rw---- 1 root disk 7, 384 2008-03-05 14:55 /dev/loop6
brw-rw---- 1 root disk 7, 448 2008-03-05 14:55 /dev/loop7
And to attach a raw partitionned disk image, the original losetup is used:
# losetup -f etch.img
# ls -l /dev/loop?*
brw-rw---- 1 root disk 7, 0 2008-03-05 14:55 /dev/loop0
brw-rw---- 1 root disk 7, 1 2008-03-05 14:57 /dev/loop0p1
brw-rw---- 1 root disk 7, 2 2008-03-05 14:57 /dev/loop0p2
brw-rw---- 1 root disk 7, 5 2008-03-05 14:57 /dev/loop0p5
brw-rw---- 1 root disk 7, 64 2008-03-05 14:55 /dev/loop1
brw-rw---- 1 root disk 7, 128 2008-03-05 14:55 /dev/loop2
brw-rw---- 1 root disk 7, 192 2008-03-05 14:55 /dev/loop3
brw-rw---- 1 root disk 7, 256 2008-03-05 14:55 /dev/loop4
brw-rw---- 1 root disk 7, 320 2008-03-05 14:55 /dev/loop5
brw-rw---- 1 root disk 7, 384 2008-03-05 14:55 /dev/loop6
brw-rw---- 1 root disk 7, 448 2008-03-05 14:55 /dev/loop7
# mount /dev/loop0p1 /mnt
# ls /mnt
bench cdrom home lib mnt root srv usr
bin dev initrd lost+found opt sbin sys var
boot etc initrd.img media proc selinux tmp vmlinuz
# umount /mnt
# losetup -d /dev/loop0
Of course, the same behavior can be done using kpartx on a loop device,
but modifying loop avoids to stack several layers of block device (loop +
device mapper), this is a very light modification (40% of modifications
are to manage the new parameter).
Signed-off-by: Laurent Vivier <Laurent.Vivier@bull.net>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
-rw-r--r-- | drivers/block/loop.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 91ebb007416c..f7f163557aa0 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -82,6 +82,9 @@ | |||
82 | static LIST_HEAD(loop_devices); | 82 | static LIST_HEAD(loop_devices); |
83 | static DEFINE_MUTEX(loop_devices_mutex); | 83 | static DEFINE_MUTEX(loop_devices_mutex); |
84 | 84 | ||
85 | static int max_part; | ||
86 | static int part_shift; | ||
87 | |||
85 | /* | 88 | /* |
86 | * Transfer functions | 89 | * Transfer functions |
87 | */ | 90 | */ |
@@ -692,6 +695,8 @@ static int loop_change_fd(struct loop_device *lo, struct file *lo_file, | |||
692 | goto out_putf; | 695 | goto out_putf; |
693 | 696 | ||
694 | fput(old_file); | 697 | fput(old_file); |
698 | if (max_part > 0) | ||
699 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
695 | return 0; | 700 | return 0; |
696 | 701 | ||
697 | out_putf: | 702 | out_putf: |
@@ -819,6 +824,8 @@ static int loop_set_fd(struct loop_device *lo, struct file *lo_file, | |||
819 | } | 824 | } |
820 | lo->lo_state = Lo_bound; | 825 | lo->lo_state = Lo_bound; |
821 | wake_up_process(lo->lo_thread); | 826 | wake_up_process(lo->lo_thread); |
827 | if (max_part > 0) | ||
828 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
822 | return 0; | 829 | return 0; |
823 | 830 | ||
824 | out_clr: | 831 | out_clr: |
@@ -919,6 +926,8 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev) | |||
919 | fput(filp); | 926 | fput(filp); |
920 | /* This is safe: open() is still holding a reference. */ | 927 | /* This is safe: open() is still holding a reference. */ |
921 | module_put(THIS_MODULE); | 928 | module_put(THIS_MODULE); |
929 | if (max_part > 0) | ||
930 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
922 | return 0; | 931 | return 0; |
923 | } | 932 | } |
924 | 933 | ||
@@ -1360,6 +1369,8 @@ static struct block_device_operations lo_fops = { | |||
1360 | static int max_loop; | 1369 | static int max_loop; |
1361 | module_param(max_loop, int, 0); | 1370 | module_param(max_loop, int, 0); |
1362 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); | 1371 | MODULE_PARM_DESC(max_loop, "Maximum number of loop devices"); |
1372 | module_param(max_part, int, 0); | ||
1373 | MODULE_PARM_DESC(max_part, "Maximum number of partitions per loop device"); | ||
1363 | MODULE_LICENSE("GPL"); | 1374 | MODULE_LICENSE("GPL"); |
1364 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); | 1375 | MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); |
1365 | 1376 | ||
@@ -1412,7 +1423,7 @@ static struct loop_device *loop_alloc(int i) | |||
1412 | if (!lo->lo_queue) | 1423 | if (!lo->lo_queue) |
1413 | goto out_free_dev; | 1424 | goto out_free_dev; |
1414 | 1425 | ||
1415 | disk = lo->lo_disk = alloc_disk(1); | 1426 | disk = lo->lo_disk = alloc_disk(1 << part_shift); |
1416 | if (!disk) | 1427 | if (!disk) |
1417 | goto out_free_queue; | 1428 | goto out_free_queue; |
1418 | 1429 | ||
@@ -1422,7 +1433,7 @@ static struct loop_device *loop_alloc(int i) | |||
1422 | init_waitqueue_head(&lo->lo_event); | 1433 | init_waitqueue_head(&lo->lo_event); |
1423 | spin_lock_init(&lo->lo_lock); | 1434 | spin_lock_init(&lo->lo_lock); |
1424 | disk->major = LOOP_MAJOR; | 1435 | disk->major = LOOP_MAJOR; |
1425 | disk->first_minor = i; | 1436 | disk->first_minor = i << part_shift; |
1426 | disk->fops = &lo_fops; | 1437 | disk->fops = &lo_fops; |
1427 | disk->private_data = lo; | 1438 | disk->private_data = lo; |
1428 | disk->queue = lo->lo_queue; | 1439 | disk->queue = lo->lo_queue; |
@@ -1502,7 +1513,12 @@ static int __init loop_init(void) | |||
1502 | * themselves and have kernel automatically instantiate actual | 1513 | * themselves and have kernel automatically instantiate actual |
1503 | * device on-demand. | 1514 | * device on-demand. |
1504 | */ | 1515 | */ |
1505 | if (max_loop > 1UL << MINORBITS) | 1516 | |
1517 | part_shift = 0; | ||
1518 | if (max_part > 0) | ||
1519 | part_shift = fls(max_part); | ||
1520 | |||
1521 | if (max_loop > 1UL << (MINORBITS - part_shift)) | ||
1506 | return -EINVAL; | 1522 | return -EINVAL; |
1507 | 1523 | ||
1508 | if (max_loop) { | 1524 | if (max_loop) { |
@@ -1510,7 +1526,7 @@ static int __init loop_init(void) | |||
1510 | range = max_loop; | 1526 | range = max_loop; |
1511 | } else { | 1527 | } else { |
1512 | nr = 8; | 1528 | nr = 8; |
1513 | range = 1UL << MINORBITS; | 1529 | range = 1UL << (MINORBITS - part_shift); |
1514 | } | 1530 | } |
1515 | 1531 | ||
1516 | if (register_blkdev(LOOP_MAJOR, "loop")) | 1532 | if (register_blkdev(LOOP_MAJOR, "loop")) |
@@ -1549,7 +1565,7 @@ static void __exit loop_exit(void) | |||
1549 | unsigned long range; | 1565 | unsigned long range; |
1550 | struct loop_device *lo, *next; | 1566 | struct loop_device *lo, *next; |
1551 | 1567 | ||
1552 | range = max_loop ? max_loop : 1UL << MINORBITS; | 1568 | range = max_loop ? max_loop : 1UL << (MINORBITS - part_shift); |
1553 | 1569 | ||
1554 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) | 1570 | list_for_each_entry_safe(lo, next, &loop_devices, lo_list) |
1555 | loop_del_one(lo); | 1571 | loop_del_one(lo); |