All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrey Borzenkov <arvidjaar@mail.ru>
To: Uwe Bugla <uwe.bugla@gmx.de>
Cc: Ken Chen <kenchen@google.com>,
	linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	Michal Piotrowski <michal.k.k.piotrowski@gmail.com>
Subject: Re: bug in 2.6.22-rc2: loop mount limited to one single iso image
Date: Sun, 20 May 2007 08:45:42 +0400	[thread overview]
Message-ID: <200705200845.43621.arvidjaar@mail.ru> (raw)
In-Reply-To: <200705200124.13026.uwe.bugla@gmx.de>

[-- Attachment #1: Type: text/plain, Size: 11933 bytes --]

On Sunday 20 May 2007, Uwe Bugla wrote:
> Am Samstag, 19. Mai 2007 21:17 schrieben Sie:
> > Ray Lee wrote:
> > > Hey there,
> > >
> > > On 5/19/07, Uwe Bugla <uwe.bugla@gmx.de> wrote:
> > >  > I am running Debian Etch 4.0 stable in connection with udev.
> > >  >
> > >  > In kernel 2.6.22-rc2 the number of available loop mounts is reduced
> > >  > from 8 (conventional standard of preceding 2.6 kernels) to 1.
> > >  >
> > >  > Symptom: If you try to mount more than one single iso-image with
> > >  > the loop parameter you are receiving the following message during
> > >  > system boot:
> > >  >
> > >  > "mount: could not find any free loop device"
> > >  >
> > >  > Kernel 2.6.20.11 does not show that problem.
> > >  >
> > >  > Question: Can someone reading this confirm and reproduce that
> > >  > problem?
> > >
> > > I can reproduce the problem pretty trivially with:
> > >
> > > mkdir a m1 m2
> > > touch a/1
> > > genisoimage -o cd1.iso a || mkisofs -o cd1.iso a
> > > cp cd1.iso cd2.iso
> > > sudo mount -o loop cd1.iso m1
> > > sudo mount -o loop cd2.iso m2
> > >
> > > ...and the last mount fails. That used to work, at least as of 2.6.15,
> > > which is the only other 2.6 kernel I have running on a machine that I
> > > can log into at the moment.
> >
> > This is unfortunate case of user-space breakage.
> >
> > Now when we do not have specific loop device limit, we also do not
> > pre-register loop devices:
> >
> > {pts/0}% LC_ALL=C ll /dev/loop*
> > brw-rw---- 1 root disk 7, 0 May 19 20:33 /dev/loop0
> >
> > (I wonder where loop0 comes from at all :) but losetup & Co unfortunately
> > need preexisting device node :(
> >
> > Trivial workaround for those who need it now - wrapper that creates node
> > and calls real losetup. I am not sure this actually works with loop mount
> > though.
> >
> > Real fix is to add special control node and change losetup to use it
> > instead (or in addition) to opening /dev/loop%d. But as it stands now I'd
> > call it big regression.
> >
> > -andrey
> >
> > > Looking at the changelogs between 2.6.20 and current tip shows at least
> > > three significant patches to loop.c. The first was supposedly tested
> > > heavily, so we'll leave that alone for now. (They all were applied
> > > after 2.6.21 was released, so it's probably fine.)
> > >
> > > Anyway, could you try reverting the two patches below (in order: the
> > > first, then the second) and see if that fixes it? The second one looks
> > > iffy to me, but if this fixes it then I'm sure Al can sort out why.
> > >
> > > Ray
> > >
> > >
> > >
> > > commit 705962ccc9d21a08b74b6b6e1d3cf10f98968a67
> > > Author: Al Viro <viro@zeniv.linux.org.uk>
> > > Date:   Sun May 13 05:52:32 2007 -0400
> > >
> > >      fix deadlock in loop.c
> > >
> > >      ... doh
> > >
> > >      Jeremy Fitzhardinge noted that the recent loop.c cleanups worked,
> > > but cause lockdep to complain.
> > >
> > >      Ouch.  OK, the deadlock is real and yes, I'm an idiot.  Speaking
> > > of which, we probably want to s/lock/pin/ in drivers/base/map.c to
> > > avoid such
> > >      brainos again.  And yes, this stuff needs clear documentation. 
> > > Will try to put one together once I get some sleep...
> > >
> > >      Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> > >      Cc: Jeremy Fitzhardinge <jeremy@goop.org>
> > >      Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> > >
> > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> > > index e2fc4b6..5526ead 100644
> > > --- a/drivers/block/loop.c
> > > +++ b/drivers/block/loop.c
> > > @@ -1399,6 +1399,11 @@ static struct loop_device *loop_init_one(int i)
> > >   struct loop_device *lo;
> > >   struct gendisk *disk;
> > >
> > > +     list_for_each_entry(lo, &loop_devices, lo_list) {
> > > +             if (lo->lo_number == i)
> > > +                     return lo;
> > > +     }
> > > +
> > >   lo = kzalloc(sizeof(*lo), GFP_KERNEL);
> > >   if (!lo)
> > >   goto out;
> > > @@ -1443,17 +1448,13 @@ static void loop_del_one(struct loop_device
> > > *lo) kfree(lo);
> > >   }
> > >
> > > -static int loop_lock(dev_t dev, void *data)
> > > -{
> > > -     mutex_lock(&loop_devices_mutex);
> > > -     return 0;
> > > -}
> > > -
> > >   static struct kobject *loop_probe(dev_t dev, int *part, void *data)
> > >   {
> > > -     struct loop_device *lo = loop_init_one(dev & MINORMASK);
> > > +     struct loop_device *lo;
> > >   struct kobject *kobj;
> > >
> > > +     mutex_lock(&loop_devices_mutex);
> > > +     lo = loop_init_one(dev & MINORMASK);
> > >   kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
> > >   mutex_unlock(&loop_devices_mutex);
> > >
> > > @@ -1466,7 +1467,7 @@ static int __init loop_init(void)
> > >   if (register_blkdev(LOOP_MAJOR, "loop"))
> > >   return -EIO;
> > >   blk_register_region(MKDEV(LOOP_MAJOR, 0), 1UL << MINORBITS,
> > > -                               THIS_MODULE, loop_probe, loop_lock,
> > > NULL); +                               THIS_MODULE, loop_probe, NULL,
> > > NULL);
> > >
> > >   if (max_loop) {
> > >   printk(KERN_INFO "loop: the max_loop option is obsolete "
> > >
> > >
> > >
> > >
> > >
> > > commit 07002e995638b83a6987180f43722a0eb39d4932
> > > Author: Al Viro <viro@zeniv.linux.org.uk>
> > > Date:   Sat May 12 16:23:15 2007 -0400
> > >
> > >      fix the dynamic allocation and probe in loop.c
> > >
> > >      Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
> > >      Acked-by: Ken Chen <kenchen@google.com>
> > >      Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> > >
> > > diff --git a/drivers/block/loop.c b/drivers/block/loop.c
> > > index 18cdd8c..e2fc4b6 100644
> > > --- a/drivers/block/loop.c
> > > +++ b/drivers/block/loop.c
> > > @@ -1317,18 +1317,6 @@ static long lo_compat_ioctl(struct file *file,
> > > unsigned int cmd, unsigned long a
> > >   }
> > >   #endif
> > >
> > > -static struct loop_device *loop_find_dev(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(int i);
> > >   static int lo_open(struct inode *inode, struct file *file)
> > >   {
> > >   struct loop_device *lo = inode->i_bdev->bd_disk->private_data;
> > > @@ -1337,11 +1325,6 @@ static int lo_open(struct inode *inode, struct
> > > file *file)
> > >   lo->lo_refcnt++;
> > >   mutex_unlock(&lo->lo_ctl_mutex);
> > >
> > > -     mutex_lock(&loop_devices_mutex);
> > > -     if (!loop_find_dev(lo->lo_number + 1))
> > > -             loop_init_one(lo->lo_number + 1);
> > > -     mutex_unlock(&loop_devices_mutex);
> > > -
> > >   return 0;
> > >   }
> > >
> > > @@ -1448,7 +1431,7 @@ out_free_queue:
> > >   out_free_dev:
> > >   kfree(lo);
> > >   out:
> > > -     return ERR_PTR(-ENOMEM);
> > > +     return NULL;
> > >   }
> > >
> > >   static void loop_del_one(struct loop_device *lo)
> > > @@ -1460,36 +1443,30 @@ static void loop_del_one(struct loop_device
> > > *lo) kfree(lo);
> > >   }
> > >
> > > +static int loop_lock(dev_t dev, void *data)
> > > +{
> > > +     mutex_lock(&loop_devices_mutex);
> > > +     return 0;
> > > +}
> > > +
> > >   static struct kobject *loop_probe(dev_t dev, int *part, void *data)
> > >   {
> > > -     unsigned int number = dev & MINORMASK;
> > > -     struct loop_device *lo;
> > > +     struct loop_device *lo = loop_init_one(dev & MINORMASK);
> > > +     struct kobject *kobj;
> > >
> > > -     mutex_lock(&loop_devices_mutex);
> > > -     lo = loop_find_dev(number);
> > > -     if (lo == NULL)
> > > -             lo = loop_init_one(number);
> > > +     kobj = lo ? get_disk(lo->lo_disk) : ERR_PTR(-ENOMEM);
> > >   mutex_unlock(&loop_devices_mutex);
> > >
> > >   *part = 0;
> > > -     if (IS_ERR(lo))
> > > -             return (void *)lo;
> > > -     else
> > > -             return &lo->lo_disk->kobj;
> > > +     return kobj;
> > >   }
> > >
> > >   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);
> > > -
> > > -     lo = loop_init_one(0);
> > > -     if (IS_ERR(lo))
> > > -             goto out;
> > > +                               THIS_MODULE, loop_probe, loop_lock,
> > > NULL);
> > >
> > >   if (max_loop) {
> > >   printk(KERN_INFO "loop: the max_loop option is obsolete "
> > > @@ -1498,11 +1475,6 @@ static int __init loop_init(void)
> > >   }
> > >   printk(KERN_INFO "loop: module loaded\n");
> > >   return 0;
> > > -
> > > -out:
> > > -     unregister_blkdev(LOOP_MAJOR, "loop");
> > > -     printk(KERN_ERR "loop: ran out of memory\n");
> > > -     return -ENOMEM;
> > >   }
> > >
> > >   static void __exit loop_exit(void)
>
> Hello Ray, hello Andrey,
>
> First of all, thank you deeply for your contributions / reproduction /
> ideas!
>
> unfortunately it does not make any difference if I simply rip out the
> changes of patch-2.6.22-rc2 or patch-2.6.21 in connection with patch
> 2.6.22-rc2 regarding module loop.c.
>

because they are just followup to the real cause. This is causes by commit

commit 73285082745045bcd64333c1fbaa88f8490f2626
Author: Ken Chen <kenchen@google.com>
Date:   Tue May 8 00:28:20 2007 -0700

    remove artificial software max_loop limit


look what it did (abridged):

-static int __init loop_init(void)
[...]
-       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]);

So before this commit we got /dev/loop%d up to max_loop when loop was loaded. 
After this commit we get nothing (I still wonder wheher lone loop0 comes from 
after reboot, because reloading module leaves me without /dev/loop%n 
alltogether).

This is a real regression because on udev-enabled system (probably 99% of 
distributions now) losetup as available in current util-linux simply stops 
working.

-andrey

> In all mentioned cases I get nothing but an incompilable kernel 2.6.22-rc2.
>
> As I stated already the mentioned loop-mount-problem does not exist in
> Kernel 2.6.20.11, who is, at least for the performance level on my machine,
> nothing but a bad compromise.
>
> I hope that Al Viro will supply a solution for this horrible kernel
> regression. And I do not think that Al Viro is an idiot - he is just a
> human, as all of us are.
>
> Yours sincerely
>
> Uwe



[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

  parent reply	other threads:[~2007-05-20  4:46 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-05-19 18:33 bug in 2.6.22-rc2: loop mount limited to one single iso image Ray Lee
2007-05-19 19:17 ` Andrey Borzenkov
     [not found]   ` <200705200124.13026.uwe.bugla@gmx.de>
2007-05-20  4:45     ` Andrey Borzenkov [this message]
2007-05-20  6:16       ` Ray Lee
2007-05-20  6:28         ` Al Viro
2007-05-20  6:58           ` Andrey Borzenkov
2007-05-20 14:52             ` Uwe Bugla
2007-05-20 15:26               ` Ray Lee
2007-05-20 15:22           ` Ray Lee
2007-05-20 15:54             ` Kay Sievers
2007-05-20 16:02               ` Andrey Borzenkov
2007-05-20 16:23                 ` Andreas Schwab
2007-05-20 16:10               ` Ray Lee
2007-05-20 16:16                 ` Kay Sievers
2007-05-20 16:29                   ` Uwe Bugla
2007-05-20 19:53                     ` Michael Mauch
2007-05-21 16:11                   ` Linus Torvalds
2007-05-21 16:27                     ` Ken Chen
2007-05-21 16:35                       ` Ray Lee
2007-05-21 16:37                       ` Ken Chen
2007-05-21 16:50                         ` Uwe Bugla
2007-05-21 17:11                           ` Kay Sievers
2007-05-21 17:51                             ` Andrey Borzenkov
2007-05-21 17:04                         ` Linus Torvalds
2007-05-21 20:48                         ` Ken Chen
2007-05-21 21:20                           ` Uwe Bugla
2007-05-21 22:04                             ` Andrew Morton
2007-05-22  0:10                     ` Al Viro
2007-05-22  0:13                       ` Al Viro
2007-05-20 16:09             ` Andrey Borzenkov
2007-05-20 16:14               ` Ray Lee
2007-05-22 20:18           ` Jan Engelhardt
2007-05-22 21:35             ` Uwe Bugla
2007-05-21  6:08         ` Ken Chen
2007-05-21  6:40           ` Ray Lee
2007-05-21  7:59             ` Uwe Bugla
  -- strict thread matches above, loose matches on Subject: below --
2007-05-19 13:53 Uwe Bugla

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=200705200845.43621.arvidjaar@mail.ru \
    --to=arvidjaar@mail.ru \
    --cc=akpm@linux-foundation.org \
    --cc=kenchen@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michal.k.k.piotrowski@gmail.com \
    --cc=uwe.bugla@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.