Patchwork [3.5.y.z,extended,stable] Patch "xfs: fix stray dquot unlock when reclaiming dquots" has been added to staging queue

login
register
mail settings
Submitter Herton Ronaldo Krzesinski
Date Jan. 7, 2013, 8:35 p.m.
Message ID <1357590935-19709-1-git-send-email-herton.krzesinski@canonical.com>
Download mbox | patch
Permalink /patch/210173/
State New
Headers show

Comments

Herton Ronaldo Krzesinski - Jan. 7, 2013, 8:35 p.m.
This is a note to let you know that I have just added a patch titled

    xfs: fix stray dquot unlock when reclaiming dquots

to the linux-3.5.y-queue branch of the 3.5.y.z extended stable tree 
which can be found at:

 http://kernel.ubuntu.com/git?p=ubuntu/linux.git;a=shortlog;h=refs/heads/linux-3.5.y-queue

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.5.y.z tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Herton

------

From 5ff4894eb72f5aa70ab0ed4de1c45296335da955 Mon Sep 17 00:00:00 2001
From: Dave Chinner <dchinner@redhat.com>
Date: Wed, 28 Nov 2012 13:01:02 +1100
Subject: [PATCH] xfs: fix stray dquot unlock when reclaiming dquots

commit b870553cdecb26d5291af09602352b763e323df2 upstream.

When we fail to get a dquot lock during reclaim, we jump to an error
handler that unlocks the dquot. This is wrong as we didn't lock the
dquot, and unlocking it means who-ever is holding the lock has had
it silently taken away, and hence it results in a lock imbalance.

Found by inspection while modifying the code for the numa-lru
patchset. This fixes a random hang I've been seeing on xfstest 232
for the past several months.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Ben Myers <bpm@sgi.com>
Signed-off-by: Herton Ronaldo Krzesinski <herton.krzesinski@canonical.com>
---
 fs/xfs/xfs_qm.c |   15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

--
1.7.9.5

Patch

diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 249db19..92eb490 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -1453,7 +1453,7 @@  xfs_qm_dqreclaim_one(
 	int			error;

 	if (!xfs_dqlock_nowait(dqp))
-		goto out_busy;
+		goto out_move_tail;

 	/*
 	 * This dquot has acquired a reference in the meantime remove it from
@@ -1476,7 +1476,7 @@  xfs_qm_dqreclaim_one(
 	 * getting flushed to disk, we don't want to reclaim it.
 	 */
 	if (!xfs_dqflock_nowait(dqp))
-		goto out_busy;
+		goto out_unlock_move_tail;

 	if (XFS_DQ_IS_DIRTY(dqp)) {
 		struct xfs_buf	*bp = NULL;
@@ -1487,7 +1487,7 @@  xfs_qm_dqreclaim_one(
 		if (error) {
 			xfs_warn(mp, "%s: dquot %p flush failed",
 				 __func__, dqp);
-			goto out_busy;
+			goto out_unlock_move_tail;
 		}

 		xfs_buf_delwri_queue(bp, buffer_list);
@@ -1496,7 +1496,7 @@  xfs_qm_dqreclaim_one(
 		 * Give the dquot another try on the freelist, as the
 		 * flushing will take some time.
 		 */
-		goto out_busy;
+		goto out_unlock_move_tail;
 	}
 	xfs_dqfunlock(dqp);

@@ -1515,14 +1515,13 @@  xfs_qm_dqreclaim_one(
 	XFS_STATS_INC(xs_qm_dqreclaims);
 	return;

-out_busy:
-	xfs_dqunlock(dqp);
-
 	/*
 	 * Move the dquot to the tail of the list so that we don't spin on it.
 	 */
+out_unlock_move_tail:
+	xfs_dqunlock(dqp);
+out_move_tail:
 	list_move_tail(&dqp->q_lru, &qi->qi_lru_list);
-
 	trace_xfs_dqreclaim_busy(dqp);
 	XFS_STATS_INC(xs_qm_dqreclaim_misses);
 }