public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [patch] remove artificial software max_loop limit
@ 2007-04-01  9:16 devzero
  0 siblings, 0 replies; 29+ messages in thread
From: devzero @ 2007-04-01  9:16 UTC (permalink / raw)
  To: linux-kernel

>Remove artificial maximum 256 loop device that can be created due to a
>legacy device number limit.  Searching through lkml archive, there are
>several instances where users complained about the artificial limit
>that the loop driver impose.  There is no reason to have such limit.

Hey, i was one of those :)

Nice to see, that it`s solved now, thanks very much!

I never expected this to happen and put all my hope into dm-loop instead.
Did you mind that Bryn m. Reeves from redhat will suffer a serious depression now? ( ->  http://sources.redhat.com/lvm2/wiki/DMLoop ) ;)

regards
roland

_______________________________________________________________
SMS schreiben mit WEB.DE FreeMail - einfach, schnell und
kostenguenstig. Jetzt gleich testen! http://f.web.de/?mc=021192


^ permalink raw reply	[flat|nested] 29+ messages in thread
* Re: [patch] remove artificial software max_loop limit
@ 2007-04-01 18:54 devzero
  0 siblings, 0 replies; 29+ messages in thread
From: devzero @ 2007-04-01 18:54 UTC (permalink / raw)
  To: Kyle Moffett; +Cc: Ken Chen, linux-kernel

> Well, the point of an upper limit might be to keep loop devices from  
> chewing up too much memory on a system.  IE: To fail allocating more  
> loopdevs before you run OOM and start killing random userspace  
> processes.

ok, sounds reasonable. 

but - not very sure here, but don`t you need to be root for creating loop devices and don`t you have many other ways to chew up too  much memory then, anyway ?


> -----Ursprüngliche Nachricht-----
> Von: Kyle Moffett <mrmacman_g4@mac.com>
> Gesendet: 01.04.07 20:44:04
> An: devzero@web.de
> CC: Ken Chen <kenchen@google.com>, linux-kernel@vger.kernel.org
> Betreff: Re: [patch] remove artificial software max_loop limit


> On Apr 01, 2007, at 14:36:11, devzero@web.de wrote:
> >> Blame on the dual meaning of max_loop that it uses currently: to
> >> initialize a set of loop devices and as a side effect, it also sets
> >> the upper limit.  People are complaining about the former constrain,
> >> isn't it?  Does anyone uses the 2nd meaning of upper limit?
> >>
> >> - Ken
> >
> > what sense would it make to set an upper limit at all?
> >
> > we`re so happy to have none anymore :)
> 
> Well, the point of an upper limit might be to keep loop devices from  
> chewing up too much memory on a system.  IE: To fail allocating more  
> loopdevs before you run OOM and start killing random userspace  
> processes.
> 
> Cheers,
> Kyle Moffett
> 
> 


_______________________________________________________________
SMS schreiben mit WEB.DE FreeMail - einfach, schnell und
kostenguenstig. Jetzt gleich testen! http://f.web.de/?mc=021192


^ permalink raw reply	[flat|nested] 29+ messages in thread
* Re: [patch] remove artificial software max_loop limit
@ 2007-04-01 18:36 devzero
  2007-04-01 18:43 ` Kyle Moffett
  0 siblings, 1 reply; 29+ messages in thread
From: devzero @ 2007-04-01 18:36 UTC (permalink / raw)
  To: Ken Chen; +Cc: linux-kernel

>Blame on the dual meaning of max_loop that it uses currently: to
>initialize a set of loop devices and as a side effect, it also sets
>the upper limit.  People are complaining about the former constrain,
>isn't it?  Does anyone uses the 2nd meaning of upper limit?
>
>- Ken

what sense would it make to set an upper limit at all?

we`re so happy to have none anymore :)

i think andrew`s suggestion is just good:

>So if we're worried about not breaking existing setups, we should retain
>this module parameter as a do-nothing thing, maybe with a
>this-is-going-away warning printk, too.


roland



_______________________________________________________________
SMS schreiben mit WEB.DE FreeMail - einfach, schnell und
kostenguenstig. Jetzt gleich testen! http://f.web.de/?mc=021192


^ permalink raw reply	[flat|nested] 29+ messages in thread
* Re: [patch] remove artificial software max_loop limit
@ 2007-04-01 10:53 devzero
  2007-04-01 18:03 ` Ken Chen
  2007-04-01 19:00 ` Jeff Dike
  0 siblings, 2 replies; 29+ messages in thread
From: devzero @ 2007-04-01 10:53 UTC (permalink / raw)
  To: linux-kernel; +Cc: jdike

not sure if this is a real issue and if it`s UML or loop related -  but how is low-memory situations being handled when creating loop devices ?

should losetup or dmesg tell "out of memory" if there is not enough memory left ?

i fired up my 2.6.20 UML and tried to create lots of loop-devices.

this crashed my UML very soon , just around 200 devices - then i saw my "mistake" that my UML had only 32MB of RAM.

then i gave my UML mem=256M and now i can setup many more loop-devices, but still crashes in the end:

setting up loop-device 1962 with losetup
Kernel panic - not syncing: do_fork failed in kernel_thread, errno = -11

EIP: 0073:[<ffffe410>] CPU: 0 Not tainted ESP: 007b:b7e6ffb0 EFLAGS: 00000246
    Not tainted
EAX: 00000000 EBX: 000072b3 ECX: 00000013 EDX: 000072b3
ESI: 000072af EDI: 00000011 EBP: 00000000 DS: 007b ES: 007b
087e7eac:  [<0807ca7b>] notifier_call_chain+0x1d/0x33
087e7ec8:  [<08071416>] panic+0x52/0xdd
087e7ee4:  [<0805cd74>] kernel_thread+0x5d/0x5f
087e7ef4:  [<0808217f>] keventd_create_kthread+0x1a/0x48
087e7ef8:  [<080820cb>] kthread+0x0/0x9a
087e7f10:  [<0807f5fb>] run_workqueue+0x8a/0x11f
087e7f18:  [<08082165>] keventd_create_kthread+0x0/0x48
087e7f1c:  [<08068351>] set_signals+0x1d/0x32
087e7f2c:  [<0807f690>] worker_thread+0x0/0x14e
087e7f30:  [<0807f7a1>] worker_thread+0x111/0x14e
087e7f74:  [<0806e771>] default_wake_function+0x0/0x12
087e7f98:  [<0808213f>] kthread+0x74/0x9a
087e7fbc:  [<080679bf>] run_kernel_thread+0x38/0x41
087e7fd8:  [<080679a2>] run_kernel_thread+0x1b/0x41
087e7fe4:  [<0805f92f>] new_thread_handler+0x53/0x79
087e7fe8:  [<080820cb>] kthread+0x0/0x9a


regards
roland






> -----Ursprüngliche Nachricht-----
> Von: devzero@web.de
> Gesendet: 01.04.07 11:16:14
> An: linux-kernel@vger.kernel.org
> Betreff: Re: [patch] remove artificial software max_loop limit 


> >Remove artificial maximum 256 loop device that can be created due to a
> >legacy device number limit.  Searching through lkml archive, there are
> >several instances where users complained about the artificial limit
> >that the loop driver impose.  There is no reason to have such limit.
> 
> Hey, i was one of those :)
> 
> Nice to see, that it`s solved now, thanks very much!
> 
> I never expected this to happen and put all my hope into dm-loop instead.
> Did you mind that Bryn m. Reeves from redhat will suffer a serious depression now? ( ->  http://sources.redhat.com/lvm2/wiki/DMLoop ) ;)
> 
> regards
> roland
> 


_______________________________________________________________
SMS schreiben mit WEB.DE FreeMail - einfach, schnell und
kostenguenstig. Jetzt gleich testen! http://f.web.de/?mc=021192


^ permalink raw reply	[flat|nested] 29+ messages in thread
* [patch] remove artificial software max_loop limit
@ 2007-03-30  7:53 Ken Chen
  2007-03-30  8:48 ` Ken Chen
  0 siblings, 1 reply; 29+ messages in thread
From: Ken Chen @ 2007-03-30  7:53 UTC (permalink / raw)
  To: Linux Kernel Mailing List, Andrew Morton

Remove artificial maximum 256 loop device that can be created due to a
legacy device number limit.  Searching through lkml archive, there are
several instances where users complained about the artificial limit
that the loop driver impose.  There is no reason to have such limit.

This patch rid the limit entirely and make loop device and associated
block queue instantiation on demand.  With on-demand instantiation, it
also gives the benefit of not wasting memory if these devices are not
in use (compare to current implementation that always create 8 loop
devices), a net improvement in both areas.  This version is both
tested with creation of large number of loop devices and is compatible
with existing losetup/mount user land tools.

There are a number of people who worked on this and provided valuable
suggestions, in no particular order, by:

Jens Axboe
Jan Engelhardt
Christoph Hellwig
Thomas M

Signed-off-by: Ken Chen <kenchen@google.com>

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 related	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2007-04-07 16:32 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-04-01  9:16 [patch] remove artificial software max_loop limit devzero
  -- strict thread matches above, loose matches on Subject: below --
2007-04-01 18:54 devzero
2007-04-01 18:36 devzero
2007-04-01 18:43 ` Kyle Moffett
2007-04-01 10:53 devzero
2007-04-01 18:03 ` Ken Chen
2007-04-01 19:00 ` Jeff Dike
2007-03-30  7:53 Ken Chen
2007-03-30  8:48 ` Ken Chen
2007-03-30  9:07   ` Jan Engelhardt
2007-03-30  9:25     ` Ken Chen
2007-03-30 16:16       ` Jan Engelhardt
2007-03-30 21:15       ` Andrew Morton
2007-03-30 22:06         ` Ken Chen
2007-03-30 22:50           ` Andrew Morton
2007-03-31 17:07         ` Greg KH
2007-03-31 17:41           ` Andrew Morton
2007-04-01  4:16             ` Ken Chen
2007-04-04 10:31               ` Tomas M
2007-04-04 18:47                 ` Andrew Morton
2007-04-01 16:53         ` Tomas M
2007-04-01 16:57           ` Tomas M
2007-04-01 18:10             ` Ken Chen
2007-04-01 19:06               ` Jan Engelhardt
2007-04-06 20:33                 ` Bill Davidsen
2007-04-07 16:18                   ` Valdis.Kletnieks
2007-04-07 16:34                     ` Bill Davidsen
2007-03-30 21:46       ` Andrew Morton
2007-03-30 21:52         ` Jan Engelhardt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox