loop is 2.6.0-test3 is broken making mkinitrd non-functional. please apply 
attached patch (courtsy of Andrew Morton)
From [EMAIL PROTECTED] Mon Aug 11 06:55:02 2003
From [EMAIL PROTECTED] Mon Aug 11 06:54:57 2003
Return-path: <[EMAIL PROTECTED]>
Received: from [65.172.181.6] (port=55596 helo=mail.osdl.org)
	by mx3.mail.ru with esmtp 
	id 19m2pk-00031Q-00
	for [EMAIL PROTECTED]; Mon, 11 Aug 2003 06:54:56 +0400
Received: from mnm (build.pdx.osdl.net [172.20.1.2])
	by mail.osdl.org (8.11.6/8.11.6) with ESMTP id h7B2sro10599
	for <[EMAIL PROTECTED]>; Sun, 10 Aug 2003 19:54:54 -0700
Date: Sun, 10 Aug 2003 19:55:02 -0700
From: Andrew Morton <[EMAIL PROTECTED]>
To: Andrey Borzenkov <[EMAIL PROTECTED]>
Subject: Re: Fw: Various problems with 2.6.0-test3-mm1
Message-Id: <[EMAIL PROTECTED]>
In-Reply-To: <[EMAIL PROTECTED]>
References: <[EMAIL PROTECTED]>
	<[EMAIL PROTECTED]>
X-Mailer: Sylpheed version 0.9.4 (GTK+ 1.2.10; i686-pc-linux-gnu)
Mime-Version: 1.0
Content-Type: text/plain;
  charset=US-ASCII
Content-Transfer-Encoding: 7bit
X-Spam: Not detected
Status: R 
X-Status: N
X-KMail-EncryptionState:  
X-KMail-SignatureState:  

Andrey Borzenkov <[EMAIL PROTECTED]> wrote:
>
> let's make a deal :) You save my mkinitrd that I have lost with test3. See 
>  "[BUG] 2.6.0-test3 - loop oopses" I can reproduce it every time by doing
> 
>  dd if=/dev/zero of=image count=32000
>  mke2fs image
>  mount -o loop image /mnt/foo
>  ls /mnt/foo
>  umount /mnt/foo
> 
>  this results in oops in umount usually in filemap_fdatawrite and soon bdflush 
>  oopses leaving system dead.

Like this?



loop-on-file oopses during unmount.  This is because lo_queue is now freed
during lo_ioctl(LOOP_CLR_FD).  I think the scenario is:

1: umount(8) opens /dev/loop0

2: umount(8) runs lo_ioctl(LOOP_CLR_FD) (this frees the queue)

3: umount(8) closes the /dev/loop0 handle.  The blockdev layer syncs the
   blockdev, but its mapping->backing_dev_info now points into la-la-land.

We shouldn't be freeing the queue until all refs to it have gone away.  This
patch gives the queue the same lifetime as the controlling loop_device
itself.

It would be better to free the queue when the device is not in use, but I'm
not sure how we can hook into the blockdev layer to do that.



 drivers/block/loop.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff -puN drivers/block/loop.c~loop-oops-fix drivers/block/loop.c
--- 25/drivers/block/loop.c~loop-oops-fix	2003-08-10 18:27:21.000000000 -0700
+++ 25-akpm/drivers/block/loop.c	2003-08-10 18:33:58.000000000 -0700
@@ -736,15 +736,6 @@ static int loop_set_fd(struct loop_devic
 
 	lo->lo_bio = lo->lo_biotail = NULL;
 
-	lo->lo_queue = blk_alloc_queue(GFP_KERNEL);
-	if (!lo->lo_queue) {
-		error = -ENOMEM;
-		fput(file);
-		goto out_putf;
-	}
-
-	disks[lo->lo_number]->queue = lo->lo_queue;
-
 	/*
 	 * set queue make_request_fn, and add limits based on lower level
 	 * device
@@ -858,7 +849,6 @@ static int loop_clr_fd(struct loop_devic
 	mapping_set_gfp_mask(filp->f_dentry->d_inode->i_mapping, gfp);
 	lo->lo_state = Lo_unbound;
 	fput(filp);
-	blk_put_queue(lo->lo_queue);
 	/* This is safe: open() is still holding a reference. */
 	module_put(THIS_MODULE);
 	return 0;
@@ -1187,6 +1177,7 @@ int __init loop_init(void)
 	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)
@@ -1203,7 +1194,12 @@ int __init loop_init(void)
 	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;
+		disks[i]->queue = lo->lo_queue;
 		init_MUTEX(&lo->lo_ctl_mutex);
 		init_MUTEX_LOCKED(&lo->lo_sem);
 		init_MUTEX_LOCKED(&lo->lo_bh_mutex);
@@ -1221,6 +1217,10 @@ int __init loop_init(void)
 	printk(KERN_INFO "loop: loaded (max %d devices)\n", max_loop);
 	return 0;
 
+out_mem4:
+	while (i--)
+		blk_put_queue(loop_dev[i].lo_queue);
+	i = max_loop;
 out_mem3:
 	while (i--)
 		put_disk(disks[i]);
@@ -1238,6 +1238,7 @@ void loop_exit(void)
 	int i;
 
 	for (i = 0; i < max_loop; i++) {
+		blk_put_queue(loop_dev[i].lo_queue);
 		del_gendisk(disks[i]);
 		put_disk(disks[i]);
 	}

_



Reply via email to