Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 27922b4260f65d317aabda37e42bbbff > files > 1006

kernel-2.6.18-238.el5.src.rpm

From: Eric Sandeen <sandeen@redhat.com>
Date: Thu, 8 May 2008 15:09:30 -0500
Subject: [fs] ext3: unmount hang when quota-enabled goes error-RO
Message-id: 48235DFA.8080504@redhat.com
O-Subject: [PATCH RHEL5.3] ext3: fix unmount hangs when quota-enabled fs goes error-RO
Bugzilla: 429054
RH-Acked-by: Larry Woodman <lwoodman@redhat.com>
RH-Acked-by: Josef Bacik <jbacik@redhat.com>
RH-Acked-by: Stephen C. Tweedie <sct@redhat.com>

For - Bug 429054: soft lockup while unmounting a read-only filesystem with errors

If the filesystem goes remount-readonly due to an error, new transactions cannot
be started, but unmounting the filesystem tries to do just that for
ext3_release_dquot().  This fails and leads to a loop in dqput.

This is a combination of the following 2 upstream patches to resolve the problem.
(actually the earlier patch addresses it in ext3_release_dquot(), the 2nd patch
is related and worth picking up).

Tested with something like:

mkfs.ext3 /dev/sdb5
mount -o quota /dev/sdb5 /mnt/test
quotacheck /mnt/test
setquota -u root 10000 10000 10000 10000 /mnt/test
quotaon /mnt/test
cd /mnt/test
cp ../linux-2.6.25.1.tar .
tar xvf linux-2.6.25.1.tar
sync
cd
mount -o remount,abort /mnt/test
sleep 10
umount /mnt/test

Thanks,

-Eric

---------------------

Date: Tue, 11 Sep 2007 22:23:29 +0000 (-0700)
Subject: quota: fix infinite loop
X-Git-Tag: v2.6.23-rc7~94
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9c3013e9b91ad23ecae88e45405e98208cce455d
quota: fix infinite loop

If we fail to start a transaction when releasing dquot, we have to call
dquot_release() anyway to mark dquot structure as inactive.  Otherwise we
end in an infinite loop inside dqput().

Signed-off-by: Jan Kara <jack@suse.cz>
Cc: xb <xavier.bru@bull.net>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Date: Mon, 28 Apr 2008 09:16:13 +0000 (-0700)
Subject: ext3: fix hang on umount with quotas when journal is aborted
X-Git-Tag: v2.6.26-rc1~747
X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=07c9938a4e2c92b796b163dc70e99d3d1870aaee
ext3: fix hang on umount with quotas when journal is aborted

Call dquot_drop() from ext3_dquot_drop() even if we fail to start a
transaction.  Otherwise we never get to dropping references to quota
structures from the inode and umount will hang indefinitely.  Thanks to
Payphone LIOU for spotting the problem.

Signed-off-by: Jan Kara <jack@suse.cz>
Cc: Payphone LIOU <lioupayphone@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

 fs/ext3/super.c |   19 +++++++++++++++++--
 1 files changed, 17 insertions(+), 2 deletions(-)

diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 49ff567..c828b0b 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2497,8 +2497,14 @@ static int ext3_dquot_drop(struct inode *inode)
 
 	/* We may delete quota structure so we need to reserve enough blocks */
 	handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb));
-	if (IS_ERR(handle))
+	if (IS_ERR(handle)) {
+		/*
+		 * We call dquot_drop() anyway to at least release references
+		 * to quota structures so that umount does not hang.
+		 */
+		dquot_drop(inode);
 		return PTR_ERR(handle);
+	}
 	ret = dquot_drop(inode);
 	err = ext3_journal_stop(handle);
 	if (!ret)
@@ -2547,8 +2553,11 @@ static int ext3_release_dquot(struct dquot *dquot)
 
 	handle = ext3_journal_start(dquot_to_inode(dquot),
 					EXT3_QUOTA_DEL_BLOCKS(dquot->dq_sb));
-	if (IS_ERR(handle))
+	if (IS_ERR(handle)) {
+		/* Release dquot anyway to avoid endless cycle in dqput() */
+		dquot_release(dquot);
 		return PTR_ERR(handle);
+	}
 	ret = dquot_release(dquot);
 	err = ext3_journal_stop(handle);
 	if (!ret)
@@ -2681,6 +2690,12 @@ static ssize_t ext3_quota_write(struct super_block *sb, int type,
 	struct buffer_head *bh;
 	handle_t *handle = journal_current_handle();
 
+	if (!handle) {
+		printk(KERN_WARNING "EXT3-fs: Quota write (off=%Lu, len=%Lu)"
+			" cancelled because transaction is not started.\n",
+			(unsigned long long)off, (unsigned long long)len);
+		return -EIO;
+	}
 	mutex_lock_nested(&inode->i_mutex, I_MUTEX_QUOTA);
 	while (towrite > 0) {
 		tocopy = sb->s_blocksize - offset < towrite ?