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 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). Moreover all partition tables known
by the kernel are managed (kpartx implements only a subset).
Signed-off-by: Laurent Vivier <[email protected]>
---
drivers/block/loop.c | 46 ++++++++++++++++++++++++++++++++++++++++------
1 files changed, 40 insertions(+), 6 deletions(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 91ebb00..49f1a22 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -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
*/
@@ -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:
@@ -1360,6 +1367,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 partition by loop device");
MODULE_LICENSE("GPL");
MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR);
@@ -1412,7 +1421,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;
@@ -1422,7 +1431,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;
@@ -1485,7 +1494,7 @@ static struct kobject *loop_probe(dev_t dev, int *part, void *data)
static int __init loop_init(void)
{
int i, nr;
- unsigned long range;
+ unsigned long range, bitfield;
struct loop_device *lo, *next;
/*
@@ -1502,7 +1511,13 @@ static int __init loop_init(void)
* themselves and have kernel automatically instantiate actual
* device on-demand.
*/
- if (max_loop > 1UL << MINORBITS)
+
+ bitfield = max_part;
+ part_shift = 0;
+ if (max_part > 0)
+ part_shift = fls(max_part);
+
+ if (max_loop > 1UL << (MINORBITS - part_shift))
return -EINVAL;
if (max_loop) {
@@ -1510,7 +1525,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"))
@@ -1549,7 +1564,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);
@@ -1569,4 +1584,23 @@ static int __init max_loop_setup(char *str)
}
__setup("max_loop=", max_loop_setup);
+
+static int __init max_part_setup(char *str)
+{
+ max_part = simple_strtol(str, NULL, 0);
+ if (max_part < 1) {
+ /* there is at least one partition */
+ printk(KERN_ERR "loop: max_part cannot be lesser than 1\n");
+ return 0;
+ }
+ if (max_part > MINORBITS - 1) {
+ /* we must keep at least one bit for loop device number */
+ printk(KERN_ERR "loop: max_part cannot be greater than %d\n",
+ MINORBITS - 1);
+ return 0;
+ }
+ return 1;
+}
+
+__setup("max_part=", max_part_setup);
#endif
--
1.5.2.4
On Thursday 06 March 2008 20:43, Laurent Vivier wrote:
> 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 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). Moreover all partition tables known
> by the kernel are managed (kpartx implements only a subset).
Do you think we do something similar for drivers/block/brd.c too? I'd
like to try to maintain parity between them where possible...
Le jeudi 06 mars 2008 à 20:57 +1100, Nick Piggin a écrit :
> On Thursday 06 March 2008 20:43, Laurent Vivier wrote:
> > 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 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). Moreover all partition tables known
> > by the kernel are managed (kpartx implements only a subset).
>
> Do you think we do something similar for drivers/block/brd.c too? I'd
> like to try to maintain parity between them where possible...
I think it is possible (I've the same patch for NBD too), but I think
it is completely useless.
For loop, it is another story because it uses disk images that can be
created from a partition or a real device (or a virtual disk).
Regards,
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth
On Thursday 06 March 2008 21:16, Laurent Vivier wrote:
> Le jeudi 06 mars 2008 à 20:57 +1100, Nick Piggin a écrit :
> > Do you think we do something similar for drivers/block/brd.c too? I'd
> > like to try to maintain parity between them where possible...
>
> I think it is possible (I've the same patch for NBD too), but I think
> it is completely useless.
It's useful for testing, and for minimising the divergence in the
code.
Le jeudi 06 mars 2008 à 21:56 +1100, Nick Piggin a écrit :
> On Thursday 06 March 2008 21:16, Laurent Vivier wrote:
> > Le jeudi 06 mars 2008 à 20:57 +1100, Nick Piggin a écrit :
>
> > > Do you think we do something similar for drivers/block/brd.c too? I'd
> > > like to try to maintain parity between them where possible...
> >
> > I think it is possible (I've the same patch for NBD too), but I think
> > it is completely useless.
>
> It's useful for testing, and for minimising the divergence in the
> code.
OK, I can try to submit a patch, if you want...
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth
Le jeudi 06 mars 2008 à 11:34 +0000, Pádraig Brady a écrit :
> Laurent Vivier wrote:
> > 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".
>
> I like it!
Thanks,
> Shouldn't we set max_part to non zero by default though?
Well, the problem is that you modify the default minor number of loop
device if max_part != 0, so I'm afraid of compatibility problems:
with max_part=0, loop0 is minor 0, loop1 is minor 1,
with max_part=63, loop0 is minor 0, loop1 is minor 64, whereas loop0p1
is minor 1.
> Hopefully I can throw away my loopback partition mounting script soon :)
> http://www.pixelbeat.org/scripts/lomount.sh
>
> cheers,
> Pádraig.
>
Regards,
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth
Laurent Vivier wrote:
> 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".
I like it!
Shouldn't we set max_part to non zero by default though?
Hopefully I can throw away my loopback partition mounting script soon :)
http://www.pixelbeat.org/scripts/lomount.sh
cheers,
P?draig.
Laurent Vivier wrote:
> Le jeudi 06 mars 2008 à 11:34 +0000, Pádraig Brady a écrit :
>> Laurent Vivier wrote:
>>> 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".
>> I like it!
>
> Thanks,
>
>> Shouldn't we set max_part to non zero by default though?
>
> Well, the problem is that you modify the default minor number of loop
> device if max_part != 0, so I'm afraid of compatibility problems:
I understand that. But who would care about specific minor numbers?
Hmm how does your patch relate to this: http://lwn.net/Articles/110426/
As an aside, I also notice on my system from the following output that
the limit of the number of partitions for a sata/scsi disk seems to be 15:
$ ls -la /dev/sd[ab]
brw-rw---- 1 root disk 8, 0 2007-11-13 10:35 /dev/sda
brw-rw---- 1 root plugdev 8, 16 2008-03-06 12:11 /dev/sdb
Pádraig.
On Thu, Mar 06, 2008 at 10:43:32AM +0100, Laurent Vivier wrote:
> 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".
I've done something else before as have done others, but at that time
we didn't want it in because it breaks the device number encoding.
Nowdays where a lot of systems use udev it probably makes sense to put
it in. The default is to not show any partitions which is safe. Did
you test if udev is smart enough to find out loop has partitions when
loaded with the paramater? If yes this can go in with a little
documentation added, if not please also work with the udev folks to
find a way to automatically detect that loop can sometimes support
partitions.
Le jeudi 06 mars 2008 à 12:21 +0000, Pádraig Brady a écrit :
> Laurent Vivier wrote:
> > Le jeudi 06 mars 2008 à 11:34 +0000, Pádraig Brady a écrit :
> >> Laurent Vivier wrote:
> >>> 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".
> >> I like it!
> >
> > Thanks,
> >
> >> Shouldn't we set max_part to non zero by default though?
> >
> > Well, the problem is that you modify the default minor number of loop
> > device if max_part != 0, so I'm afraid of compatibility problems:
>
> I understand that. But who would care about specific minor numbers?
Well, in some case I care about the minor number.
Normally, device name is meaningless, i.e. you can call the device as
you want, the real information comes from the inode, the major number
for the driver, and the minor number as a parameter for the driver. For
instance, if I have a device node and I want to know if it is a SCSI
disk or an ATA disk I make a fstat() and I look at the major number, if
I want to know if it is the first disk or the second, a partition or
not, I look at the minor number.
> Hmm how does your patch relate to this: http://lwn.net/Articles/110426/
I didn't know this one but it is very similar.
> As an aside, I also notice on my system from the following output that
> the limit of the number of partitions for a sata/scsi disk seems to be 15:
>
> $ ls -la /dev/sd[ab]
> brw-rw---- 1 root disk 8, 0 2007-11-13 10:35 /dev/sda
> brw-rw---- 1 root plugdev 8, 16 2008-03-06 12:11 /dev/sdb
For the scsi disk, the minor number contains the disk number and the
partition number, if I remember correctly originally minor number were 8
bits (it is not the case now I believe), and SCSI disk id can be from 0
to 15 (4 bits) so it lets only 4 bits for partition number (15
partitions)
Regards,
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth
Le jeudi 06 mars 2008 à 07:35 -0500, Christoph Hellwig a écrit :
> On Thu, Mar 06, 2008 at 10:43:32AM +0100, Laurent Vivier wrote:
> > 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".
>
> I've done something else before as have done others, but at that time
> we didn't want it in because it breaks the device number encoding.
>
> Nowdays where a lot of systems use udev it probably makes sense to put
> it in. The default is to not show any partitions which is safe. Did
> you test if udev is smart enough to find out loop has partitions when
> loaded with the paramater? If yes this can go in with a little
Well, my system is a Debian Etch, and all loop devices and loop
partitions are created automatically, so I imagine udev is working fine
with that...
> documentation added, if not please also work with the udev folks to
> find a way to automatically detect that loop can sometimes support
> partitions.
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth
Nick Piggin <[email protected]> wrote:
> On Thursday 06 March 2008 21:16, Laurent Vivier wrote:
>> Le jeudi 06 mars 2008 ? 20:57 +1100, Nick Piggin a ?crit :
>> > Do you think we do something similar for drivers/block/brd.c too? I'd
>> > like to try to maintain parity between them where possible...
>>
>> I think it is possible (I've the same patch for NBD too), but I think
>> it is completely useless.
>
> It's useful for testing, and for minimising the divergence in the
> code.
Maybe there should be a common mechanism to use partitions on any block
device. Maybe there is - I have dark memories about the device mapper
being able to parse partition tables, and plans on moving partition
support to userspace.
On Fri, Mar 7, 2008 at 12:56 PM, Bodo Eggert <[email protected]> wrote:
> Nick Piggin <[email protected]> wrote:
> > On Thursday 06 March 2008 21:16, Laurent Vivier wrote:
> >> Le jeudi 06 mars 2008 ? 20:57 +1100, Nick Piggin a ?crit :
>
> >> > Do you think we do something similar for drivers/block/brd.c too? I'd
> >> > like to try to maintain parity between them where possible...
> >>
> >> I think it is possible (I've the same patch for NBD too), but I think
> >> it is completely useless.
> >
> > It's useful for testing, and for minimising the divergence in the
> > code.
>
> Maybe there should be a common mechanism to use partitions on any block
> device. Maybe there is - I have dark memories about the device mapper
> being able to parse partition tables, and plans on moving partition
> support to userspace.
It's easy to add partition support to the loopback device. A patch
that realizes this was already published in 2004. See also
http://lwn.net/Articles/110426/.
Bart Van Assche.
Le vendredi 07 mars 2008 à 12:56 +0100, Bodo Eggert a écrit :
> Nick Piggin <[email protected]> wrote:
> > On Thursday 06 March 2008 21:16, Laurent Vivier wrote:
> >> Le jeudi 06 mars 2008 à 20:57 +1100, Nick Piggin a écrit :
>
> >> > Do you think we do something similar for drivers/block/brd.c too? I'd
> >> > like to try to maintain parity between them where possible...
> >>
> >> I think it is possible (I've the same patch for NBD too), but I think
> >> it is completely useless.
> >
> > It's useful for testing, and for minimising the divergence in the
> > code.
>
> Maybe there should be a common mechanism to use partitions on any block
> device. Maybe there is - I have dark memories about the device mapper
The mechanism exists: the driver must call alloc_disk() with a value !=
1. This is what is modifying this patch.
> being able to parse partition tables, and plans on moving partition
> support to userspace.
This is kpartx.
Laurent
--
----------------- [email protected] ------------------
"Programmers who subconsciously view themselves as artists
will enjoy what they do and will do it better." D. Knuth