LKML Archive on lore.kernel.org help / color / mirror / Atom feed
* max_loop limit @ 2007-03-22 7:57 Tomas M 2007-03-22 11:00 ` markus reichelt 0 siblings, 1 reply; 25+ messages in thread From: Tomas M @ 2007-03-22 7:57 UTC (permalink / raw) To: linux-kernel [-- Attachment #1: Type: text/plain, Size: 1356 bytes --] Hello, this is my first code submitted to kernel, I hope you won't hate it. This 4-lines-change patch adds support for nearly two-times more loop devices. Explanation follows: The maximum amount of loop devices has been 255 for many years, while there is a lot of space for more. The maximum depends on max memory available from kmalloc(), which is usually 128KB, but can be increased in some cases. It would be better to support thousands of loop devices of course, but the change could be more complicated (perhaps replace kmalloc by vmalloc). This four lines change is just simple and sufficient, without any need for kmalloc replacement. I only removed the test if (max_loop > 255), so now we support much more loop devices then before, without ANY OTHER CHANGE to the code. Information: The maximum max_loop is 455 if kmalloc can allocate 128KB, so the amount is nearly doubled without any significant change to kernel code. The maximum could be even bigger I guess, it probably depends on: NR_CPUS, MAX_NUMNODES, CONFIG_MMU and CONFIG_LARGE_ALLOCS. If kmalloc can't allocate enough RAM, loop is simply unloaded. Thank you for your consideration. I hope you will like it and you will include it in kernel. Or, if not, maybe this patch will start some debate regarding the current insufficient limit of 255 loop devices. Tomas M slax.org [-- Attachment #2: loop.c.diff --] [-- Type: text/x-patch, Size: 1861 bytes --] --- linux/drivers/block/loop_old.c 2007-02-04 18:44:54.000000000 +0000 +++ linux/drivers/block/loop.c 2007-03-22 08:31:55.000000000 +0000 @@ -44,6 +44,16 @@ * backing filesystem. * Anton Altaparmakov, 16 Feb 2005 * + * The maximum amount of loop devices has been 255 for many years, while there + * is a lot of space for more. The maximum depends on max memory available + * from kmalloc, which is usually 128KB, but can be even more. + * I removed the test if (max_loop > 255), so now we support much more loop + * devices then before; it probably depends on: + * NR_CPUS, MAX_NUMNODES, CONFIG_MMU and CONFIG_LARGE_ALLOCS. + * Information: The maximum max_loop is 455 if kmalloc handles only 128KB. + * If kmalloc can't allocate enough RAM, loop is simply unloaded. + * Author: Tomas Matejicek, www.slax.org, 21 Mar 2007 + * * Still To Fix: * - Advisory locking is ignored here. * - Should use an own CAP_* category instead of CAP_SYS_ADMIN @@ -1358,7 +1368,7 @@ * And now the modules code and kernel interface. */ module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); +MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-455 on i386)"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1402,9 +1412,9 @@ { int i; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); + if (max_loop < 1) { + printk(KERN_WARNING "loop: invalid max_loop (must be at least 1" + ", using default (8)\n"); max_loop = 8; } @@ -1465,7 +1475,7 @@ kfree(loop_dev); out_mem1: unregister_blkdev(LOOP_MAJOR, "loop"); - printk(KERN_ERR "loop: ran out of memory\n"); + printk(KERN_ERR "loop: ran out of memory for max_loop=%d\n", max_loop); return -ENOMEM; } ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 7:57 max_loop limit Tomas M @ 2007-03-22 11:00 ` markus reichelt 2007-03-22 11:37 ` Tomas M 0 siblings, 1 reply; 25+ messages in thread From: markus reichelt @ 2007-03-22 11:00 UTC (permalink / raw) To: linux-kernel [-- Attachment #1: Type: text/plain, Size: 334 bytes --] * Tomas M <tomas@slax.org> wrote: > I hope you will like it and you will include it in kernel. > Or, if not, maybe this patch will start some debate regarding > the current insufficient limit of 255 loop devices. 255 loop devices are insufficient? What kind of scenario do you have in mind? -- left blank, right bald [-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 11:00 ` markus reichelt @ 2007-03-22 11:37 ` Tomas M 2007-03-22 13:42 ` Eric Dumazet 2007-03-29 14:16 ` max_loop limit Bill Davidsen 0 siblings, 2 replies; 25+ messages in thread From: Tomas M @ 2007-03-22 11:37 UTC (permalink / raw) To: linux-kernel > 255 loop devices are insufficient? What kind of scenario do you have > in mind? > > Thank you very much for replying. In 1981, Bill Gates said that 64KB of memory is enough for everybody. And you know how much RAM do you have right now. :) Every limit is bad. The limit of 255 loop devices has been introduced years ago, in the times when minor device number has been limited by 255. Nowadays, there is no such limitation. There are many possible/reasonable uses for more than 255 loop devices. For example CD/ISO server. My project, Slax Linux live, is based on modular approach where many parts of the root filesystem are stored separately in compressed read-only loop files, and are mounted and unioned to a single root by using union fs (aufs). The question is not "Why do we need more than 255 loops?". The question should be "Why do we need the hardcoded 255-limit in kernel while there is no reason for it at all?" My patch simply removes the hardcoded limitation. Tomas M slax.org ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 11:37 ` Tomas M @ 2007-03-22 13:42 ` Eric Dumazet 2007-03-22 13:42 ` Jens Axboe ` (2 more replies) 2007-03-29 14:16 ` max_loop limit Bill Davidsen 1 sibling, 3 replies; 25+ messages in thread From: Eric Dumazet @ 2007-03-22 13:42 UTC (permalink / raw) To: Tomas M; +Cc: linux-kernel On Thu, 22 Mar 2007 12:37:54 +0100 Tomas M <tomas@slax.org> wrote: > The question is not "Why do we need more than 255 loops?". > The question should be "Why do we need the hardcoded 255-limit in kernel > while there is no reason for it at all?" > > My patch simply removes the hardcoded limitation. Hello Tomas, welcome ! Well, its an attempt to remove a hardcoded limit, but as you said in the Changelog, it really depends on kmalloc() being able to allocate a large continous memory zone. Alas it might fail. The golden rule is to avoid all allocations larger than PAGE_SIZE :) On x86_64, sizeof(struct loop_device) is 368, so the 'new limit' would be 356 instead of 256... You might want a more radical patch : Instead of using : static struct loop_device *loop_dev; loop_dev = kmalloc(max_loop * sizeof(struct loop_device)); Switch to : static struct loop_device **loop_dev; loop_dev = kmalloc(max_loop * sizeof(void *)); if (!loop_dev) rollback... for (i = 0 ; i < max_loop ; i++) { loop_dev[i] = kmalloc(sizeof(struct loop_device)); if (!loop_dev[i]) rollback... } This time, you would be limited to 16384 loop devices on x86_64, 32768 on i386 :) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:42 ` Eric Dumazet @ 2007-03-22 13:42 ` Jens Axboe 2007-03-22 13:52 ` Eric Dumazet 2007-03-22 14:33 ` max_loop limit Al Viro 2007-03-22 14:25 ` Tomas M 2007-03-23 1:34 ` Jan Engelhardt 2 siblings, 2 replies; 25+ messages in thread From: Jens Axboe @ 2007-03-22 13:42 UTC (permalink / raw) To: Eric Dumazet; +Cc: Tomas M, linux-kernel On Thu, Mar 22 2007, Eric Dumazet wrote: > On Thu, 22 Mar 2007 12:37:54 +0100 > Tomas M <tomas@slax.org> wrote: > > > The question is not "Why do we need more than 255 loops?". > > The question should be "Why do we need the hardcoded 255-limit in kernel > > while there is no reason for it at all?" > > > > My patch simply removes the hardcoded limitation. > > Hello Tomas, welcome ! > > Well, its an attempt to remove a hardcoded limit, but as you said in the Changelog, it really depends on kmalloc() being able to allocate a large continous memory zone. Alas it might fail. > The golden rule is to avoid all allocations larger than PAGE_SIZE :) > > On x86_64, sizeof(struct loop_device) is 368, so the 'new limit' would be 356 instead of 256... > > You might want a more radical patch : > > Instead of using : > > static struct loop_device *loop_dev; > loop_dev = kmalloc(max_loop * sizeof(struct loop_device)); > > Switch to : > > static struct loop_device **loop_dev; > loop_dev = kmalloc(max_loop * sizeof(void *)); > if (!loop_dev) rollback... > for (i = 0 ; i < max_loop ; i++) { > loop_dev[i] = kmalloc(sizeof(struct loop_device)); > if (!loop_dev[i]) rollback... > } > > This time, you would be limited to 16384 loop devices on x86_64, 32768 on i386 :) But this still wastes memory, why not just allocate each loop device dynamically when it is set up? The current approach is crap, it is just wasting memory for loop devices, queues, etc. -- Jens Axboe ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:42 ` Jens Axboe @ 2007-03-22 13:52 ` Eric Dumazet 2007-03-22 13:54 ` Jens Axboe 2007-03-22 14:33 ` max_loop limit Al Viro 1 sibling, 1 reply; 25+ messages in thread From: Eric Dumazet @ 2007-03-22 13:52 UTC (permalink / raw) To: Jens Axboe; +Cc: Tomas M, linux-kernel On Thu, 22 Mar 2007 14:42:31 +0100 Jens Axboe <jens.axboe@oracle.com> wrote: > > This time, you would be limited to 16384 loop devices on x86_64, 32768 on i386 :) > > But this still wastes memory, why not just allocate each loop device > dynamically when it is set up? The current approach is crap, it is just > wasting memory for loop devices, queues, etc. > Sure, but it's the first Tomas patch :) Apparently the 'current crap' didnt caugth someone else attention. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:52 ` Eric Dumazet @ 2007-03-22 13:54 ` Jens Axboe 2007-03-22 14:11 ` William Lee Irwin III [not found] ` <20070322151826.c1421851.dada1@cosmosbay.com> 0 siblings, 2 replies; 25+ messages in thread From: Jens Axboe @ 2007-03-22 13:54 UTC (permalink / raw) To: Eric Dumazet; +Cc: Tomas M, linux-kernel On Thu, Mar 22 2007, Eric Dumazet wrote: > On Thu, 22 Mar 2007 14:42:31 +0100 > Jens Axboe <jens.axboe@oracle.com> wrote: > > > > > This time, you would be limited to 16384 loop devices on x86_64, 32768 on i386 :) > > > > But this still wastes memory, why not just allocate each loop device > > dynamically when it is set up? The current approach is crap, it is just > > wasting memory for loop devices, queues, etc. > > > > Sure, but it's the first Tomas patch :) The more the reason to guide him in the direction of a right solution, instead of extending the current bad one! > Apparently the 'current crap' didnt caugth someone else attention. I guess most people don't care, 8 is enough for them and the wasted memory isn't too much to care about - 8 devices and only one used, is wasting at least ~14kb on my machine here. -- Jens Axboe ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:54 ` Jens Axboe @ 2007-03-22 14:11 ` William Lee Irwin III 2007-03-22 15:22 ` Arjan van de Ven 2007-03-22 16:09 ` Pádraig Brady [not found] ` <20070322151826.c1421851.dada1@cosmosbay.com> 1 sibling, 2 replies; 25+ messages in thread From: William Lee Irwin III @ 2007-03-22 14:11 UTC (permalink / raw) To: Jens Axboe; +Cc: Eric Dumazet, Tomas M, linux-kernel On Thu, Mar 22 2007, Eric Dumazet wrote: >> Sure, but it's the first Tomas patch :) On Thu, Mar 22, 2007 at 02:54:57PM +0100, Jens Axboe wrote: > The more the reason to guide him in the direction of a right solution, > instead of extending the current bad one! On Thu, Mar 22 2007, Eric Dumazet wrote: >> Apparently the 'current crap' didnt caugth someone else attention. On Thu, Mar 22, 2007 at 02:54:57PM +0100, Jens Axboe wrote: > I guess most people don't care, 8 is enough for them and the wasted > memory isn't too much to care about - 8 devices and only one used, is > wasting at least ~14kb on my machine here. Any chance we can get some kind of devices set up for partitions of loop devices if we're going to redo loopdev setup? That's been a thorn in my side for some time. -- wli ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 14:11 ` William Lee Irwin III @ 2007-03-22 15:22 ` Arjan van de Ven 2007-03-22 16:09 ` Pádraig Brady 1 sibling, 0 replies; 25+ messages in thread From: Arjan van de Ven @ 2007-03-22 15:22 UTC (permalink / raw) To: William Lee Irwin III; +Cc: Jens Axboe, Eric Dumazet, Tomas M, linux-kernel On Thu, 2007-03-22 at 07:11 -0700, William Lee Irwin III wrote: > On Thu, Mar 22 2007, Eric Dumazet wrote: > >> Sure, but it's the first Tomas patch :) > > On Thu, Mar 22, 2007 at 02:54:57PM +0100, Jens Axboe wrote: > > The more the reason to guide him in the direction of a right solution, > > instead of extending the current bad one! > > On Thu, Mar 22 2007, Eric Dumazet wrote: > >> Apparently the 'current crap' didnt caugth someone else attention. > > On Thu, Mar 22, 2007 at 02:54:57PM +0100, Jens Axboe wrote: > > I guess most people don't care, 8 is enough for them and the wasted > > memory isn't too much to care about - 8 devices and only one used, is > > wasting at least ~14kb on my machine here. > > Any chance we can get some kind of devices set up for partitions of > loop devices if we're going to redo loopdev setup? That's been a thorn > in my side for some time. you can already do that with devmapper and partx combo... ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 14:11 ` William Lee Irwin III 2007-03-22 15:22 ` Arjan van de Ven @ 2007-03-22 16:09 ` Pádraig Brady 2007-03-28 23:34 ` Karel Zak 1 sibling, 1 reply; 25+ messages in thread From: Pádraig Brady @ 2007-03-22 16:09 UTC (permalink / raw) To: William Lee Irwin III; +Cc: Jens Axboe, Eric Dumazet, Tomas M, linux-kernel William Lee Irwin III wrote: > Any chance we can get some kind of devices set up for partitions of > loop devices if we're going to redo loopdev setup? That's been a thorn > in my side for some time. This script might be of use: http://www.pixelbeat.org/scripts/lomount.sh cheers, Pádraig. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 16:09 ` Pádraig Brady @ 2007-03-28 23:34 ` Karel Zak 0 siblings, 0 replies; 25+ messages in thread From: Karel Zak @ 2007-03-28 23:34 UTC (permalink / raw) To: Pádraig Brady Cc: William Lee Irwin III, Jens Axboe, Eric Dumazet, Tomas M, linux-kernel On Thu, Mar 22, 2007 at 04:09:13PM +0000, Pádraig Brady wrote: > William Lee Irwin III wrote: > > Any chance we can get some kind of devices set up for partitions of > > loop devices if we're going to redo loopdev setup? That's been a thorn > > in my side for some time. > > This script might be of use: > http://www.pixelbeat.org/scripts/lomount.sh Ah, lomount... very popular name ;-) Xen guys have lomount too. Unfortunately, these solution are useless with LVM volumes. The kpartx is more usable: http://fedoraproject.org/wiki/FedoraXenQuickstartFC6?highlight=%28Xen%29#head-9c5408e750e8184aece3efe822be0ef6dd1871cd Karel -- Karel Zak <kzak@redhat.com> ^ permalink raw reply [flat|nested] 25+ messages in thread
[parent not found: <20070322151826.c1421851.dada1@cosmosbay.com>]
[parent not found: <20070322142306.GU19922@kernel.dk>]
[parent not found: <20070322153603.1f5d442d.dada1@cosmosbay.com>]
* Re: max_loop limit - paid job offer [not found] ` <20070322153603.1f5d442d.dada1@cosmosbay.com> @ 2007-03-22 15:31 ` Tomas M 0 siblings, 0 replies; 25+ messages in thread From: Tomas M @ 2007-03-22 15:31 UTC (permalink / raw) To: linux-kernel > Really, I dont think Tomas has the skill or time to follow a typical > lkml discussion. > Well I have the skills to follow LKML discussion, but I don't have the skills to provide *perfect* patch for loop.c So I'm offering a financial reward for the *perfect* loop.c patch. It should support *A LOT OF* loop devices without any need to specify any max_loop at all. I offered $256 in my previous email, I don't know if this is enough for this job, so I'm open to all your suggestions. Is there anyone interested? If you hate these offers on LKML then let me know please, I'm just used to pay for others' time, I hope it doesn't offend you. Thank you for your consideration. Tomas M slax.org ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:42 ` Jens Axboe 2007-03-22 13:52 ` Eric Dumazet @ 2007-03-22 14:33 ` Al Viro 2007-03-22 19:51 ` Olivier Galibert 1 sibling, 1 reply; 25+ messages in thread From: Al Viro @ 2007-03-22 14:33 UTC (permalink / raw) To: Jens Axboe; +Cc: Eric Dumazet, Tomas M, linux-kernel On Thu, Mar 22, 2007 at 02:42:31PM +0100, Jens Axboe wrote: > But this still wastes memory, why not just allocate each loop device > dynamically when it is set up? The current approach is crap, it is just > wasting memory for loop devices, queues, etc. Correction: current ABI is crap. To set the thing up you need to open it and issue an ioctl. Which is a bloody bad idea, for obvious reasons... ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 14:33 ` max_loop limit Al Viro @ 2007-03-22 19:51 ` Olivier Galibert 0 siblings, 0 replies; 25+ messages in thread From: Olivier Galibert @ 2007-03-22 19:51 UTC (permalink / raw) To: Al Viro; +Cc: linux-kernel On Thu, Mar 22, 2007 at 02:33:14PM +0000, Al Viro wrote: > Correction: current ABI is crap. To set the thing up you need to open > it and issue an ioctl. Which is a bloody bad idea, for obvious reasons... Agreed. What would be a right way? Global device ala ptmx/tun/tap? New syscall? Something else? OG. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:42 ` Eric Dumazet 2007-03-22 13:42 ` Jens Axboe @ 2007-03-22 14:25 ` Tomas M 2007-03-23 1:34 ` Jan Engelhardt 2 siblings, 0 replies; 25+ messages in thread From: Tomas M @ 2007-03-22 14:25 UTC (permalink / raw) To: linux-kernel > You might want a more radical patch : I agree that my patch is not the perfect solution for max_loop problem. But it nearly doubles max_loop for me (using 386 arch) and moreover it is a FIX for incorrect implementation in kernel IMHO. So I can see REASON to include it in Kernel. Do I cry at the correct tomb? :) > > Instead of using : > :: > Switch to : > :: I'm not any professional kernel hacker, so I don't understand the mysteries regarding ** (pointers to pointers?). Is there anyone who could provide CLEAN patch for loop.c, which would raise the max_loop limit to (at least) 1024 and which would be ACCEPTED to mainline kernel any soon? I'm offering MONEY for this task. Let's say $256 ;-) I hope I didn't offend anyone by this offer. Tomas M slax.org ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 13:42 ` Eric Dumazet 2007-03-22 13:42 ` Jens Axboe 2007-03-22 14:25 ` Tomas M @ 2007-03-23 1:34 ` Jan Engelhardt 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt 2 siblings, 1 reply; 25+ messages in thread From: Jan Engelhardt @ 2007-03-23 1:34 UTC (permalink / raw) To: Eric Dumazet; +Cc: Tomas M, linux-kernel On Mar 22 2007 14:42, Eric Dumazet wrote: >Instead of using : > >static struct loop_device *loop_dev; >loop_dev = kmalloc(max_loop * sizeof(struct loop_device)); > >Switch to : > >static struct loop_device **loop_dev; >loop_dev = kmalloc(max_loop * sizeof(void *)); >if (!loop_dev) rollback... >for (i = 0 ; i < max_loop ; i++) { > loop_dev[i] = kmalloc(sizeof(struct loop_device)); > if (!loop_dev[i]) rollback... >} > >This time, you would be limited to 16384 loop devices on x86_64, 32768 on i386 >:) Oh noes. Please use a linked list (kmalloc cope = perfect) if you really need loads of loopdevs. Sorta struct loopdev { struct list_head lh; int lo_number; }; to keep the /dev/loop%d number consistent across loopdev removal. Maybe it's better to even use an rbtree (linked list does not scale to it). Jan -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH] max_loop limit 2007-03-23 1:34 ` Jan Engelhardt @ 2007-03-23 23:26 ` Jan Engelhardt 2007-03-25 0:17 ` Ken Chen ` (3 more replies) 0 siblings, 4 replies; 25+ messages in thread From: Jan Engelhardt @ 2007-03-23 23:26 UTC (permalink / raw) To: Eric Dumazet; +Cc: Tomas M, Linux Kernel Mailing List Hi, here's one. Allocates all the fluff dynamically. It does not create any dev nodes by itself, so you need to do it (à la mdadm), but you'll get all 1048576 available minors. Sadly, it locks up the foreground process (losetup that would be), and I have not yet figured out why. And the mpt regression elsewhere is hindering me in finding out faster. Signed-off-by: Jan Engelhardt <jengelh@gmx.de> Index: linux-2.6.21-rc4/drivers/block/loop.c =================================================================== --- linux-2.6.21-rc4.orig/drivers/block/loop.c +++ linux-2.6.21-rc4/drivers/block/loop.c @@ -77,9 +77,8 @@ #include <asm/uaccess.h> -static int max_loop = 8; -static struct loop_device *loop_dev; -static struct gendisk **disks; +static LIST_HEAD(loop_devices); +static DEFINE_SPINLOCK(loop_devices_lock); /* * Transfer functions @@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo) if (unlikely((loff_t)x != size)) return -EFBIG; - set_capacity(disks[lo->lo_number], x); + set_capacity(lo->lo_disk, x); return 0; } @@ -812,7 +811,7 @@ static int loop_set_fd(struct loop_devic lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; - set_capacity(disks[lo->lo_number], size); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); set_blocksize(bdev, lo_blocksize); @@ -832,7 +831,7 @@ out_clr: lo->lo_device = NULL; lo->lo_backing_file = NULL; lo->lo_flags = 0; - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); invalidate_bdev(bdev, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(mapping, lo->old_gfp_mask); @@ -918,7 +917,7 @@ static int loop_clr_fd(struct loop_devic memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev, 0); - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; @@ -1357,8 +1356,6 @@ static struct block_device_operations lo /* * And now the modules code and kernel interface. */ -module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1383,7 +1380,7 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + list_for_each_entry(lo, &loop_devices, lo_list) { mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) @@ -1398,102 +1395,102 @@ int loop_unregister_transfer(int number) EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -static int __init loop_init(void) +static struct loop_device *loop_find_dev(unsigned int number) +{ + struct loop_device *lo; + list_for_each_entry(lo, &loop_devices, lo_list) + if (lo->lo_number == number) + return lo; + return NULL; +} + +static struct loop_device *loop_init_one(unsigned int number) { - int i; + struct loop_device *lo; + struct gendisk *disk; + + lo = kzalloc(sizeof(struct loop_device), GFP_KERNEL); + if (lo == NULL) + goto out; + + lo->lo_queue = blk_alloc_queue(GFP_KERNEL); + if (lo->lo_queue == NULL) + goto out_free_dev; + + disk = lo->lo_disk = alloc_disk(1); + if (disk == NULL) + goto out_free_queue; + + mutex_init(&lo->lo_ctl_mutex); + lo->lo_number = number; + lo->lo_thread = NULL; + init_waitqueue_head(&lo->lo_event); + spin_lock_init(&lo->lo_lock); + disk->major = LOOP_MAJOR; + disk->first_minor = number; + disk->fops = &lo_fops; + disk->private_data = lo; + disk->queue = lo->lo_queue; + sprintf(disk->disk_name, "loop%u", number); + add_disk(lo->lo_disk); + + spin_lock(&loop_devices_lock); + list_add_tail(&lo->lo_list, &loop_devices); + spin_unlock(&loop_devices_lock); + return lo; + + out_free_queue: + blk_cleanup_queue(lo->lo_queue); + out_free_dev: + kfree(lo); + out: + return ERR_PTR(-ENOMEM); +} + +static void loop_del_one(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); + return; +} + +static struct kobject *loop_probe(dev_t dev, int *part, void *data) +{ + unsigned int number = dev & MINORMASK; + struct loop_device *lo; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); - max_loop = 8; + if ((lo = loop_find_dev(number)) == NULL) { + lo = loop_init_one(number); + if (IS_ERR(lo)) + return (void *)lo; } + return &lo->lo_disk->kobj; +} + +static int __init loop_init(void) +{ if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; - - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); - if (!loop_dev) - goto out_mem1; - memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); - - disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); - if (!disks) - goto out_mem2; - - for (i = 0; i < max_loop; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out_mem3; - } - - for (i = 0; i < max_loop; i++) { - struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks[i]; - - memset(lo, 0, sizeof(*lo)); - lo->lo_queue = blk_alloc_queue(GFP_KERNEL); - if (!lo->lo_queue) - goto out_mem4; - mutex_init(&lo->lo_ctl_mutex); - lo->lo_number = i; - lo->lo_thread = NULL; - init_waitqueue_head(&lo->lo_event); - spin_lock_init(&lo->lo_lock); - disk->major = LOOP_MAJOR; - disk->first_minor = i; - disk->fops = &lo_fops; - sprintf(disk->disk_name, "loop%d", i); - disk->private_data = lo; - disk->queue = lo->lo_queue; - } - - /* We cannot fail after we call this, so another loop!*/ - for (i = 0; i < max_loop; i++) - add_disk(disks[i]); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); + blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, + THIS_MODULE, loop_probe, NULL, NULL); return 0; +} -out_mem4: - while (i--) - blk_cleanup_queue(loop_dev[i].lo_queue); - i = max_loop; -out_mem3: - while (i--) - put_disk(disks[i]); - kfree(disks); -out_mem2: - kfree(loop_dev); -out_mem1: - unregister_blkdev(LOOP_MAJOR, "loop"); - printk(KERN_ERR "loop: ran out of memory\n"); - return -ENOMEM; -} - -static void loop_exit(void) -{ - int i; - - for (i = 0; i < max_loop; i++) { - del_gendisk(disks[i]); - blk_cleanup_queue(loop_dev[i].lo_queue); - put_disk(disks[i]); - } +static void __exit loop_exit(void) +{ + struct loop_device *lo, *next; + + list_for_each_entry_safe(lo, next, &loop_devices, lo_list) + loop_del_one(lo); + + blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); if (unregister_blkdev(LOOP_MAJOR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); - - kfree(disks); - kfree(loop_dev); } module_init(loop_init); module_exit(loop_exit); - -#ifndef MODULE -static int __init max_loop_setup(char *str) -{ - max_loop = simple_strtol(str, NULL, 0); - return 1; -} - -__setup("max_loop=", max_loop_setup); -#endif Index: linux-2.6.21-rc4/include/linux/loop.h =================================================================== --- linux-2.6.21-rc4.orig/include/linux/loop.h +++ linux-2.6.21-rc4/include/linux/loop.h @@ -16,6 +16,7 @@ #ifdef __KERNEL__ #include <linux/bio.h> #include <linux/blkdev.h> +#include <linux/list.h> #include <linux/spinlock.h> #include <linux/mutex.h> @@ -29,7 +30,8 @@ enum { struct loop_func_table; struct loop_device { - int lo_number; + struct list_head lo_list; + unsigned int lo_number; int lo_refcnt; loff_t lo_offset; loff_t lo_sizelimit; @@ -50,6 +52,7 @@ struct loop_device { struct file * lo_backing_file; struct block_device *lo_device; + struct gendisk *lo_disk; unsigned lo_blocksize; void *key_data; #<EOF> Jan -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt @ 2007-03-25 0:17 ` Ken Chen 2007-03-25 0:29 ` Ken Chen ` (2 subsequent siblings) 3 siblings, 0 replies; 25+ messages in thread From: Ken Chen @ 2007-03-25 0:17 UTC (permalink / raw) To: Jan Engelhardt; +Cc: Eric Dumazet, Tomas M, Linux Kernel Mailing List On 3/23/07, Jan Engelhardt <jengelh@linux01.gwdg.de> wrote: > Sadly, it locks up the foreground process (losetup that would be), and I > have not yet figured out why. And the mpt regression elsewhere is > hindering me in finding out faster. You need to tell the block layer that each loop device is a whole block device, not a partition within another device. Otherwise, I think it will cause a recursive mutex lock in block_dev.c:do_open(). This patch should fix the problem. Signed-off-by: Ken Chen <kenchen@google.com> --- ./drivers/block/loop.c.orig 2007-03-24 17:05:51.000000000 -0700 +++ ./drivers/block/loop.c 2007-03-24 17:06:06.000000000 -0700 @@ -1464,6 +1464,7 @@ if ((lo = loop_find_dev(number)) == NULL) { lo = loop_init_one(number); + *part = 0; if (IS_ERR(lo)) return (void *)lo; } ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt 2007-03-25 0:17 ` Ken Chen @ 2007-03-25 0:29 ` Ken Chen 2007-03-25 8:40 ` Tomas M 2007-03-29 3:54 ` Kyle Moffett 3 siblings, 0 replies; 25+ messages in thread From: Ken Chen @ 2007-03-25 0:29 UTC (permalink / raw) To: Jan Engelhardt; +Cc: Eric Dumazet, Tomas M, Linux Kernel Mailing List On 3/23/07, Jan Engelhardt <jengelh@linux01.gwdg.de> wrote: > @@ -1383,7 +1380,7 @@ int loop_unregister_transfer(int number) > > xfer_funcs[n] = NULL; > > - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { > + list_for_each_entry(lo, &loop_devices, lo_list) { > mutex_lock(&lo->lo_ctl_mutex); Don't you need to use loop_devices_lock to protect the linked list here? > +static struct loop_device *loop_find_dev(unsigned int number) > +{ > + struct loop_device *lo; > + list_for_each_entry(lo, &loop_devices, lo_list) > + if (lo->lo_number == number) > + return lo; > + return NULL; Here too with spin lock?? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt 2007-03-25 0:17 ` Ken Chen 2007-03-25 0:29 ` Ken Chen @ 2007-03-25 8:40 ` Tomas M 2007-03-28 23:41 ` Karel Zak 2007-03-29 3:54 ` Kyle Moffett 3 siblings, 1 reply; 25+ messages in thread From: Tomas M @ 2007-03-25 8:40 UTC (permalink / raw) To: linux-kernel > here's one. Allocates all the fluff dynamically. It does not create any > dev nodes by itself, so you need to do it (à la mdadm) I'm afraid that this would break a lot of things, for example mount -o loop will not work anymore unless you create /dev/loop* manually first, am I correct? In this case, this is unusable for many as it is not backward compatible with old loop.c, am I correct? Tomas M slax.org ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit 2007-03-25 8:40 ` Tomas M @ 2007-03-28 23:41 ` Karel Zak 0 siblings, 0 replies; 25+ messages in thread From: Karel Zak @ 2007-03-28 23:41 UTC (permalink / raw) To: Tomas M; +Cc: linux-kernel On Sun, Mar 25, 2007 at 10:40:10AM +0200, Tomas M wrote: > >here's one. Allocates all the fluff dynamically. It does not create any > >dev nodes by itself, so you need to do it (à la mdadm) > > I'm afraid that this would break a lot of things, for example mount -o > loop will not work anymore unless you create /dev/loop* manually first, Yes, "losetup" and "mount -o loop" call stat( /dev/loopN ) when look for an (un)used loop device. > am I correct? In this case, this is unusable for many as it is not > backward compatible with old loop.c, am I correct? udev ? Karel -- Karel Zak <kzak@redhat.com> ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt ` (2 preceding siblings ...) 2007-03-25 8:40 ` Tomas M @ 2007-03-29 3:54 ` Kyle Moffett 2007-03-29 4:16 ` [PATCH] max_loop limit, t2 Jan Engelhardt 3 siblings, 1 reply; 25+ messages in thread From: Kyle Moffett @ 2007-03-29 3:54 UTC (permalink / raw) To: Jan Engelhardt; +Cc: Eric Dumazet, Tomas M, Linux Kernel Mailing List On Mar 23, 2007, at 19:26:34, Jan Engelhardt wrote: > here's one. Allocates all the fluff dynamically. It does not create > any dev nodes by itself, so you need to do it (à la mdadm), but > you'll get all 1048576 available minors. > > +static LIST_HEAD(loop_devices); Maybe an rbtree would work better here? Maximum number of nodes traversed to get to the bottom of the tree given 2^(20) loop devices is 19 as opposed to the 2^(20) for a linked list. Also, to preserve compatibility with existing userspace loop tools you should probably always allocate one extra loop device. Keep a "highest used loopdev" number and create the one after that so that udev will autocreate a dev node for it. Cheers, Kyle Moffett ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit, t2 2007-03-29 3:54 ` Kyle Moffett @ 2007-03-29 4:16 ` Jan Engelhardt 2007-03-29 8:38 ` [PATCH] max_loop limit, loop.c final working version Tomas M 0 siblings, 1 reply; 25+ messages in thread From: Jan Engelhardt @ 2007-03-29 4:16 UTC (permalink / raw) To: Kyle Moffett; +Cc: Eric Dumazet, Tomas M, Linux Kernel Mailing List On Mar 25 2007 10:40, Tomas M wrote: >On ??, Jan Engelhardt wrote: > >> here's one. Allocates all the fluff dynamically. It does not >> create any dev nodes by itself, so you need to do it (à la mdadm) > > I'm afraid that this would break a lot of things, for example mount > -o loop will not work anymore unless you create /dev/loop* manually > first, am I correct? In this case, this is unusable for many as it > is not backward compatible with old loop.c, am I correct? So here's another try. Use the max_auto_loop= module parameter to define how many device nodes should be created (defaults to 8, like original loop.c) in advance. (More specifically, how many disks you want uevents have generated.) This is because creating all 1048576 possible loop disks in /dev (tmpfs!!) would be really overkill and seldom good for memory usage. On Mar 28 2007 23:54, Kyle Moffett wrote: > Maybe an rbtree would work better here? Maximum number of nodes > traversed to get to the bottom of the tree given 2^(20) loop > devices is 19 as opposed to the 2^(20) for a linked list. Also, to > preserve compatibility with existing userspace loop tools you > should probably always allocate one extra loop device. Keep a > "highest used loopdev" number and create the one after that so that > udev will autocreate a dev node for it. Yeah I already have a ... hack that creates /dev/loop[0-7] but it segfaults ^_^ Perhaps someone knows why. The oops trace I get has kobject_uevent() in it, but I don't think I missed something in the _init function wrt. uevent generation, did I? Signed-off-by: Jan Engelhardt <jengelh@gmx.de> Name: dynamic-loop-jengelh2.diff Index: linux-2.6.21-rc5/drivers/block/Makefile =================================================================== --- linux-2.6.21-rc5.orig/drivers/block/Makefile +++ linux-2.6.21-rc5/drivers/block/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_VIODASD) += viodasd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o obj-$(CONFIG_BLK_DEV_UB) += ub.o +CFLAGS_loop.o += -O0 Index: linux-2.6.21-rc5/drivers/block/loop.c =================================================================== --- linux-2.6.21-rc5.orig/drivers/block/loop.c +++ linux-2.6.21-rc5/drivers/block/loop.c @@ -77,9 +77,9 @@ #include <asm/uaccess.h> -static int max_loop = 8; -static struct loop_device *loop_dev; -static struct gendisk **disks; +static unsigned int max_auto_loop = 8; +static LIST_HEAD(loop_devices); +static DEFINE_SPINLOCK(loop_devices_lock); /* * Transfer functions @@ -183,7 +183,7 @@ figure_loop_size(struct loop_device *lo) if (unlikely((loff_t)x != size)) return -EFBIG; - set_capacity(disks[lo->lo_number], x); + set_capacity(lo->lo_disk, x); return 0; } @@ -812,7 +812,7 @@ static int loop_set_fd(struct loop_devic lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; - set_capacity(disks[lo->lo_number], size); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); set_blocksize(bdev, lo_blocksize); @@ -832,7 +832,7 @@ out_clr: lo->lo_device = NULL; lo->lo_backing_file = NULL; lo->lo_flags = 0; - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); invalidate_bdev(bdev, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(mapping, lo->old_gfp_mask); @@ -918,7 +918,7 @@ static int loop_clr_fd(struct loop_devic memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev, 0); - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; @@ -1357,8 +1357,9 @@ static struct block_device_operations lo /* * And now the modules code and kernel interface. */ -module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); +module_param(max_auto_loop, uint, S_IRUGO); +MODULE_PARM_DESC(max_auto_loop, "Maximum number of auto-generated loop device " + "nodes (0-1048576)"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1383,7 +1384,7 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + list_for_each_entry(lo, &loop_devices, lo_list) { mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) @@ -1398,102 +1399,120 @@ int loop_unregister_transfer(int number) EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -static int __init loop_init(void) +static struct loop_device *loop_find_dev(unsigned int number) +{ + struct loop_device *lo; + list_for_each_entry(lo, &loop_devices, lo_list) + if (lo->lo_number == number) + return lo; + return NULL; +} + +static struct loop_device *loop_init_one(unsigned int number) { - int i; + struct loop_device *lo; + struct gendisk *disk; + + lo = kzalloc(sizeof(struct loop_device), GFP_KERNEL); + if (lo == NULL) + goto out; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); - max_loop = 8; + lo->lo_queue = blk_alloc_queue(GFP_KERNEL); + if (lo->lo_queue == NULL) + goto out_free_dev; + + disk = lo->lo_disk = alloc_disk(1); + if (disk == NULL) + goto out_free_queue; + + mutex_init(&lo->lo_ctl_mutex); + lo->lo_number = number; + lo->lo_thread = NULL; + init_waitqueue_head(&lo->lo_event); + spin_lock_init(&lo->lo_lock); + disk->major = LOOP_MAJOR; + disk->first_minor = number; + disk->fops = &lo_fops; + disk->private_data = lo; + disk->queue = lo->lo_queue; + sprintf(disk->disk_name, "loop%u", number); + add_disk(lo->lo_disk); + + spin_lock(&loop_devices_lock); + list_add_tail(&lo->lo_list, &loop_devices); + spin_unlock(&loop_devices_lock); + return lo; + + out_free_queue: + blk_cleanup_queue(lo->lo_queue); + out_free_dev: + kfree(lo); + out: + return ERR_PTR(-ENOMEM); +} + +static void loop_del_one(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); + return; +} + +static struct kobject *loop_probe(dev_t dev, int *part, void *data) +{ + unsigned int number = dev & MINORMASK; + struct loop_device *lo; + + if ((lo = loop_find_dev(number)) == NULL) { + lo = loop_init_one(number); + if (IS_ERR(lo)) + return (void *)lo; + *part = 0; } + return &lo->lo_disk->kobj; +} + +static int __init loop_init(void) +{ + struct kobject kobj; + int i; + if (register_blkdev(LOOP_MAJOR, "loop")) return -EIO; + blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, + THIS_MODULE, loop_probe, NULL, NULL); - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); - if (!loop_dev) - goto out_mem1; - memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); - - disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); - if (!disks) - goto out_mem2; - - for (i = 0; i < max_loop; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out_mem3; - } - - for (i = 0; i < max_loop; i++) { - struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks[i]; - - memset(lo, 0, sizeof(*lo)); - lo->lo_queue = blk_alloc_queue(GFP_KERNEL); - if (!lo->lo_queue) - goto out_mem4; - mutex_init(&lo->lo_ctl_mutex); - lo->lo_number = i; - lo->lo_thread = NULL; - init_waitqueue_head(&lo->lo_event); - spin_lock_init(&lo->lo_lock); - disk->major = LOOP_MAJOR; - disk->first_minor = i; - disk->fops = &lo_fops; - sprintf(disk->disk_name, "loop%d", i); - disk->private_data = lo; - disk->queue = lo->lo_queue; - } - - /* We cannot fail after we call this, so another loop!*/ - for (i = 0; i < max_loop; i++) - add_disk(disks[i]); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); - return 0; + /* Trigger uevents so that /dev nodes get created by udev */ + for (i = 0; i < max_auto_loop; ++i) { + kobject_init(&kobj); + if (kobject_set_name(&kobj, "loop%u", i) != 0) + /* + * Most likely the Out Of Memory case. Do not try to + * create more objects. + */ + break; + kobject_uevent(&kobj, KOBJ_ADD); + kobject_put(&kobj); + } -out_mem4: - while (i--) - blk_cleanup_queue(loop_dev[i].lo_queue); - i = max_loop; -out_mem3: - while (i--) - put_disk(disks[i]); - kfree(disks); -out_mem2: - kfree(loop_dev); -out_mem1: - unregister_blkdev(LOOP_MAJOR, "loop"); - printk(KERN_ERR "loop: ran out of memory\n"); - return -ENOMEM; + return 0; } -static void loop_exit(void) +static void __exit loop_exit(void) { - int i; + struct loop_device *lo, *next; - for (i = 0; i < max_loop; i++) { - del_gendisk(disks[i]); - blk_cleanup_queue(loop_dev[i].lo_queue); - put_disk(disks[i]); - } + list_for_each_entry_safe(lo, next, &loop_devices, lo_list) + loop_del_one(lo); + + blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); if (unregister_blkdev(LOOP_MAJOR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); - - kfree(disks); - kfree(loop_dev); } module_init(loop_init); module_exit(loop_exit); - -#ifndef MODULE -static int __init max_loop_setup(char *str) -{ - max_loop = simple_strtol(str, NULL, 0); - return 1; -} - -__setup("max_loop=", max_loop_setup); -#endif Index: linux-2.6.21-rc5/include/linux/loop.h =================================================================== --- linux-2.6.21-rc5.orig/include/linux/loop.h +++ linux-2.6.21-rc5/include/linux/loop.h @@ -16,6 +16,7 @@ #ifdef __KERNEL__ #include <linux/bio.h> #include <linux/blkdev.h> +#include <linux/list.h> #include <linux/spinlock.h> #include <linux/mutex.h> @@ -29,7 +30,8 @@ enum { struct loop_func_table; struct loop_device { - int lo_number; + struct list_head lo_list; + unsigned int lo_number; int lo_refcnt; loff_t lo_offset; loff_t lo_sizelimit; @@ -50,6 +52,7 @@ struct loop_device { struct file * lo_backing_file; struct block_device *lo_device; + struct gendisk *lo_disk; unsigned lo_blocksize; void *key_data; #<EOF> Jan -- ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] max_loop limit, loop.c final working version 2007-03-29 4:16 ` [PATCH] max_loop limit, t2 Jan Engelhardt @ 2007-03-29 8:38 ` Tomas M 0 siblings, 0 replies; 25+ messages in thread From: Tomas M @ 2007-03-29 8:38 UTC (permalink / raw) To: Jan Engelhardt, linux-kernel [-- Attachment #1: Type: text/plain, Size: 714 bytes --] This is a diff from Ken Chen, who sent it to me a week ago and received the claimed prize $256. I think it's partially based on Jan's code, while if fixes the bug Jan mentioned (as far as I know). It does the following: - allocate loop dynamically on the fly - allocate one more (spare) loop each time, so losetup and mount tools can work correctly - doesn't need any module parameters Unfortunately 'mount' and 'losetup' binaries are hardcoded to stop searching for free loop device after the minor num 255, so one have to use a workaround in order to use more loops with 'mount': $ losetup /dev/loop1000 file $ mount /dev/loop1000 /mntpnt I hope these binaries will be fixed soon. Tomas M slax.org [-- Attachment #2: loop.c.diff --] [-- Type: text/x-patch, Size: 7610 bytes --] diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 6b5b642..7db2c38 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -77,9 +77,8 @@ #include <linux/kthread.h> #include <asm/uaccess.h> -static int max_loop = 8; -static struct loop_device *loop_dev; -static struct gendisk **disks; +static LIST_HEAD(loop_devices); +static DEFINE_SPINLOCK(loop_devices_lock); /* * Transfer functions @@ -183,7 +182,7 @@ figure_loop_size(struct loop_device *lo) if (unlikely((loff_t)x != size)) return -EFBIG; - set_capacity(disks[lo->lo_number], x); + set_capacity(lo->lo_disk, x); return 0; } @@ -812,7 +811,7 @@ static int loop_set_fd(struct loop_devic lo->lo_queue->queuedata = lo; lo->lo_queue->unplug_fn = loop_unplug; - set_capacity(disks[lo->lo_number], size); + set_capacity(lo->lo_disk, size); bd_set_size(bdev, size << 9); set_blocksize(bdev, lo_blocksize); @@ -832,7 +831,7 @@ out_clr: lo->lo_device = NULL; lo->lo_backing_file = NULL; lo->lo_flags = 0; - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); invalidate_bdev(bdev, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(mapping, lo->old_gfp_mask); @@ -918,7 +917,7 @@ static int loop_clr_fd(struct loop_devic memset(lo->lo_crypt_name, 0, LO_NAME_SIZE); memset(lo->lo_file_name, 0, LO_NAME_SIZE); invalidate_bdev(bdev, 0); - set_capacity(disks[lo->lo_number], 0); + set_capacity(lo->lo_disk, 0); bd_set_size(bdev, 0); mapping_set_gfp_mask(filp->f_mapping, gfp); lo->lo_state = Lo_unbound; @@ -1322,6 +1321,23 @@ static long lo_compat_ioctl(struct file } #endif +static struct loop_device *loop_find_dev(int number) +{ + struct loop_device *lo; + int found = 0; + + spin_lock(&loop_devices_lock); + list_for_each_entry(lo, &loop_devices, lo_list) { + if (lo->lo_number == number) { + found = 1; + break; + } + } + spin_unlock(&loop_devices_lock); + return found ? lo : NULL; +} + +static struct loop_device *loop_init_one(int i); static int lo_open(struct inode *inode, struct file *file) { struct loop_device *lo = inode->i_bdev->bd_disk->private_data; @@ -1330,6 +1346,9 @@ static int lo_open(struct inode *inode, lo->lo_refcnt++; mutex_unlock(&lo->lo_ctl_mutex); + if (!loop_find_dev(lo->lo_number + 1)) + loop_init_one(lo->lo_number + 1); + return 0; } @@ -1357,8 +1376,6 @@ #endif /* * And now the modules code and kernel interface. */ -module_param(max_loop, int, 0); -MODULE_PARM_DESC(max_loop, "Maximum number of loop devices (1-256)"); MODULE_LICENSE("GPL"); MODULE_ALIAS_BLOCKDEV_MAJOR(LOOP_MAJOR); @@ -1383,7 +1400,7 @@ int loop_unregister_transfer(int number) xfer_funcs[n] = NULL; - for (lo = &loop_dev[0]; lo < &loop_dev[max_loop]; lo++) { + list_for_each_entry(lo, &loop_devices, lo_list) { mutex_lock(&lo->lo_ctl_mutex); if (lo->lo_encryption == xfer) @@ -1398,102 +1415,104 @@ int loop_unregister_transfer(int number) EXPORT_SYMBOL(loop_register_transfer); EXPORT_SYMBOL(loop_unregister_transfer); -static int __init loop_init(void) +static struct loop_device *loop_init_one(int i) { - int i; + struct loop_device *lo; + struct gendisk *disk; - if (max_loop < 1 || max_loop > 256) { - printk(KERN_WARNING "loop: invalid max_loop (must be between" - " 1 and 256), using default (8)\n"); - max_loop = 8; - } + lo = kzalloc(sizeof(*lo), GFP_KERNEL); + if (!lo) + goto out; - if (register_blkdev(LOOP_MAJOR, "loop")) - return -EIO; + lo->lo_queue = blk_alloc_queue(GFP_KERNEL); + if (!lo->lo_queue) + goto out_free_dev; + + disk = lo->lo_disk = alloc_disk(1); + if (!disk) + goto out_free_queue; + + mutex_init(&lo->lo_ctl_mutex); + lo->lo_number = i; + lo->lo_thread = NULL; + init_waitqueue_head(&lo->lo_event); + spin_lock_init(&lo->lo_lock); + disk->major = LOOP_MAJOR; + disk->first_minor = i; + disk->fops = &lo_fops; + disk->private_data = lo; + disk->queue = lo->lo_queue; + sprintf(disk->disk_name, "loop%d", i); + add_disk(disk); + spin_lock(&loop_devices_lock); + list_add_tail(&lo->lo_list, &loop_devices); + spin_unlock(&loop_devices_lock); + return lo; + +out_free_queue: + blk_cleanup_queue(lo->lo_queue); +out_free_dev: + kfree(lo); +out: + return ERR_PTR(-ENOMEM); +} - loop_dev = kmalloc(max_loop * sizeof(struct loop_device), GFP_KERNEL); - if (!loop_dev) - goto out_mem1; - memset(loop_dev, 0, max_loop * sizeof(struct loop_device)); +static void loop_del_one(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); +} - disks = kmalloc(max_loop * sizeof(struct gendisk *), GFP_KERNEL); - if (!disks) - goto out_mem2; +static struct kobject *loop_probe(dev_t dev, int *part, void *data) +{ + unsigned int number = dev & MINORMASK; + struct loop_device *lo; - for (i = 0; i < max_loop; i++) { - disks[i] = alloc_disk(1); - if (!disks[i]) - goto out_mem3; + if ((lo = loop_find_dev(number)) == NULL) { + lo = loop_init_one(number); + *part = 0; + if (IS_ERR(lo)) + return (void *)lo; } + return &lo->lo_disk->kobj; +} - for (i = 0; i < max_loop; i++) { - struct loop_device *lo = &loop_dev[i]; - struct gendisk *disk = disks[i]; - - memset(lo, 0, sizeof(*lo)); - lo->lo_queue = blk_alloc_queue(GFP_KERNEL); - if (!lo->lo_queue) - goto out_mem4; - mutex_init(&lo->lo_ctl_mutex); - lo->lo_number = i; - lo->lo_thread = NULL; - init_waitqueue_head(&lo->lo_event); - spin_lock_init(&lo->lo_lock); - disk->major = LOOP_MAJOR; - disk->first_minor = i; - disk->fops = &lo_fops; - sprintf(disk->disk_name, "loop%d", i); - disk->private_data = lo; - disk->queue = lo->lo_queue; - } +static int __init loop_init(void) +{ + struct loop_device *lo; + + if (register_blkdev(LOOP_MAJOR, "loop")) + return -EIO; + blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS, + THIS_MODULE, loop_probe, NULL, NULL); - /* We cannot fail after we call this, so another loop!*/ - for (i = 0; i < max_loop; i++) - add_disk(disks[i]); - printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop); + lo = loop_init_one(0); + if (IS_ERR(lo)) + goto out_free; + + printk(KERN_INFO "loop: loaded"); return 0; -out_mem4: - while (i--) - blk_cleanup_queue(loop_dev[i].lo_queue); - i = max_loop; -out_mem3: - while (i--) - put_disk(disks[i]); - kfree(disks); -out_mem2: - kfree(loop_dev); -out_mem1: +out_free: unregister_blkdev(LOOP_MAJOR, "loop"); printk(KERN_ERR "loop: ran out of memory\n"); return -ENOMEM; } -static void loop_exit(void) +static void __exit loop_exit(void) { - int i; + struct loop_device *lo, *next; - for (i = 0; i < max_loop; i++) { - del_gendisk(disks[i]); - blk_cleanup_queue(loop_dev[i].lo_queue); - put_disk(disks[i]); - } + list_for_each_entry_safe(lo, next, &loop_devices, lo_list) + loop_del_one(lo); + + blk_unregister_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS); if (unregister_blkdev(LOOP_MAJOR, "loop")) printk(KERN_WARNING "loop: cannot unregister blkdev\n"); - - kfree(disks); - kfree(loop_dev); } module_init(loop_init); module_exit(loop_exit); - -#ifndef MODULE -static int __init max_loop_setup(char *str) -{ - max_loop = simple_strtol(str, NULL, 0); - return 1; -} - -__setup("max_loop=", max_loop_setup); -#endif diff --git a/include/linux/loop.h b/include/linux/loop.h index 191a595..0b99b31 100644 --- a/include/linux/loop.h +++ b/include/linux/loop.h @@ -64,6 +64,8 @@ struct loop_device { wait_queue_head_t lo_event; request_queue_t *lo_queue; + struct gendisk *lo_disk; + struct list_head lo_list; }; #endif /* __KERNEL__ */ ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: max_loop limit 2007-03-22 11:37 ` Tomas M 2007-03-22 13:42 ` Eric Dumazet @ 2007-03-29 14:16 ` Bill Davidsen 1 sibling, 0 replies; 25+ messages in thread From: Bill Davidsen @ 2007-03-29 14:16 UTC (permalink / raw) To: Tomas M; +Cc: linux-kernel Tomas M wrote: >> 255 loop devices are insufficient? What kind of scenario do you have >> in mind? >> >> > > Thank you very much for replying. > > In 1981, Bill Gates said that 64KB of memory is enough for everybody. > And you know how much RAM do you have right now. :) > Actually, I believe the number was 640k, the quote included the phrase "should be," the available memory on the IBM PC. And this was after IBM decided to put the video adapter in memory at 640k, Intel decided to provide only 1MB of address space on the 8086, and was in the context of mainframes of the day, some of which could only address 1MB. And having run clients with three users on an XT with just that 640kB and UNIX, I don't think he was wrong about the memory for that time, just the O/S. BTW: anyone got a copy of PC/IX (SysIII for XT) around? I'd love to run that in a VM just for the comparison. -- Bill Davidsen <davidsen@tmr.com> "We have more to fear from the bungling of the incompetent than from the machinations of the wicked." - from Slashdot ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2007-03-29 14:16 UTC | newest] Thread overview: 25+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2007-03-22 7:57 max_loop limit Tomas M 2007-03-22 11:00 ` markus reichelt 2007-03-22 11:37 ` Tomas M 2007-03-22 13:42 ` Eric Dumazet 2007-03-22 13:42 ` Jens Axboe 2007-03-22 13:52 ` Eric Dumazet 2007-03-22 13:54 ` Jens Axboe 2007-03-22 14:11 ` William Lee Irwin III 2007-03-22 15:22 ` Arjan van de Ven 2007-03-22 16:09 ` Pádraig Brady 2007-03-28 23:34 ` Karel Zak [not found] ` <20070322151826.c1421851.dada1@cosmosbay.com> [not found] ` <20070322142306.GU19922@kernel.dk> [not found] ` <20070322153603.1f5d442d.dada1@cosmosbay.com> 2007-03-22 15:31 ` max_loop limit - paid job offer Tomas M 2007-03-22 14:33 ` max_loop limit Al Viro 2007-03-22 19:51 ` Olivier Galibert 2007-03-22 14:25 ` Tomas M 2007-03-23 1:34 ` Jan Engelhardt 2007-03-23 23:26 ` [PATCH] " Jan Engelhardt 2007-03-25 0:17 ` Ken Chen 2007-03-25 0:29 ` Ken Chen 2007-03-25 8:40 ` Tomas M 2007-03-28 23:41 ` Karel Zak 2007-03-29 3:54 ` Kyle Moffett 2007-03-29 4:16 ` [PATCH] max_loop limit, t2 Jan Engelhardt 2007-03-29 8:38 ` [PATCH] max_loop limit, loop.c final working version Tomas M 2007-03-29 14:16 ` max_loop limit Bill Davidsen
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).