Sophie

Sophie

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

kernel-2.6.18-238.el5.src.rpm

From: Benjamin Marzinski <bmarzins@redhat.com>
Date: Mon, 22 Jun 2009 19:56:21 -0500
Subject: [gfs2] always queue work after after setting GLF_LOCK
Message-id: 20090623005621.GE3172@ether.msp.redhat.com
O-Subject: [RHEL-5.4 PATCH] BZ#506140 gfs2: Always queue work after after setting GLF_LOCK
Bugzilla: 506140
RH-Acked-by: Steven Whitehouse <swhiteho@redhat.com>

When GFS2 decides whether to remove a glock from its cache, it locks the
GLF_LOCK gl_flags bit.  GFS2 assumes that any process who locks this bit
will either process the outstanding work on the glock, or schedule the
glock_workqueue to do it later.  This wasn't happening for glocks that
were getting checked, but weren't getting remove from the cache, causing
gfs2 to hang with processes waiting to acquire locks, but nothing
scheduled to actually grant them the lock.This patch fixes this.

It is a trivial RHEL5 port of a fix that is scheduled to go upstream.
However, since Steve Whitehouse is on vacation, it is not actually
upstream yet.

This patch has been tested on the BIGI performance test bed, and fixes
that filesystem hang that was being seen with specsfs.

Signed-off-by: Benjamin Marzinski <bmarzins@redhat.com>

diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 60b60a5..cbeb0c1 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1420,7 +1420,6 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
 	struct gfs2_glock *gl;
 	int may_demote;
 	int nr_skipped = 0;
-	int got_ref = 0;
 	LIST_HEAD(skipped);
 
 	if (nr == 0)
@@ -1438,7 +1437,6 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
 		/* Test for being demotable */
 		if (!test_and_set_bit(GLF_LOCK, &gl->gl_flags)) {
 			gfs2_glock_hold(gl);
-			got_ref = 1;
 			spin_unlock(&lru_lock);
 			spin_lock(&gl->gl_spin);
 			may_demote = demote_ok(gl);
@@ -1447,25 +1445,14 @@ static int gfs2_shrink_glock_memory(int nr, gfp_t gfp_mask)
 			if (may_demote) {
 				handle_callback(gl, LM_ST_UNLOCKED, 0);
 				nr--;
-				if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
-					gfs2_glock_put(gl);
-				got_ref = 0;
 			}
+			if (queue_delayed_work(glock_workqueue, &gl->gl_work, 0) == 0)
+				gfs2_glock_put(gl);
 			spin_lock(&lru_lock);
-			if (may_demote)
-				continue;
-		}
-		if (list_empty(&gl->gl_lru) &&
-		    (atomic_read(&gl->gl_ref) <= (2 + got_ref))) {
-			nr_skipped++;
-			list_add(&gl->gl_lru, &skipped);
-		}
-		if (got_ref) {
-			spin_unlock(&lru_lock);
-			gfs2_glock_put(gl);
-			spin_lock(&lru_lock);
-			got_ref = 0;
+			continue;
 		}
+		nr_skipped++;
+		list_add(&gl->gl_lru, &skipped);
 	}
 	list_splice(&skipped, &lru_list);
 	atomic_add(nr_skipped, &lru_count);