aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/glock.c
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2010-08-02 05:15:17 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2010-08-02 05:15:17 -0400
commit0809f6ec18bbce54c996f5c36f4b9d371075c98b (patch)
tree66aa0c523f0e7ab5b35504123b5238e5f81ea309 /fs/gfs2/glock.c
parentc639d5d8f69f37e24ed0354373f61fcbde4b9354 (diff)
GFS2: Fix recovery stuck bug (try #2)
This is a clean up of the code which deals with LM_FLAG_NOEXP which aims to remove any possible race conditions by using gl_spin to cover the gap between testing for the LM_FLAG_NOEXP and the GL_FROZEN flag. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/glock.c')
-rw-r--r--fs/gfs2/glock.c46
1 files changed, 39 insertions, 7 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 2b3d8f8a8393..9adf8f924e08 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -1063,6 +1063,9 @@ int gfs2_glock_nq(struct gfs2_holder *gh)
1063 1063
1064 spin_lock(&gl->gl_spin); 1064 spin_lock(&gl->gl_spin);
1065 add_to_queue(gh); 1065 add_to_queue(gh);
1066 if ((LM_FLAG_NOEXP & gh->gh_flags) &&
1067 test_and_clear_bit(GLF_FROZEN, &gl->gl_flags))
1068 set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
1066 run_queue(gl, 1); 1069 run_queue(gl, 1);
1067 spin_unlock(&gl->gl_spin); 1070 spin_unlock(&gl->gl_spin);
1068 1071
@@ -1320,6 +1323,36 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
1320} 1323}
1321 1324
1322/** 1325/**
1326 * gfs2_should_freeze - Figure out if glock should be frozen
1327 * @gl: The glock in question
1328 *
1329 * Glocks are not frozen if (a) the result of the dlm operation is
1330 * an error, (b) the locking operation was an unlock operation or
1331 * (c) if there is a "noexp" flagged request anywhere in the queue
1332 *
1333 * Returns: 1 if freezing should occur, 0 otherwise
1334 */
1335
1336static int gfs2_should_freeze(const struct gfs2_glock *gl)
1337{
1338 const struct gfs2_holder *gh;
1339
1340 if (gl->gl_reply & ~LM_OUT_ST_MASK)
1341 return 0;
1342 if (gl->gl_target == LM_ST_UNLOCKED)
1343 return 0;
1344
1345 list_for_each_entry(gh, &gl->gl_holders, gh_list) {
1346 if (test_bit(HIF_HOLDER, &gh->gh_iflags))
1347 continue;
1348 if (LM_FLAG_NOEXP & gh->gh_flags)
1349 return 0;
1350 }
1351
1352 return 1;
1353}
1354
1355/**
1323 * gfs2_glock_complete - Callback used by locking 1356 * gfs2_glock_complete - Callback used by locking
1324 * @gl: Pointer to the glock 1357 * @gl: Pointer to the glock
1325 * @ret: The return value from the dlm 1358 * @ret: The return value from the dlm
@@ -1329,18 +1362,17 @@ void gfs2_glock_cb(struct gfs2_glock *gl, unsigned int state)
1329void gfs2_glock_complete(struct gfs2_glock *gl, int ret) 1362void gfs2_glock_complete(struct gfs2_glock *gl, int ret)
1330{ 1363{
1331 struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct; 1364 struct lm_lockstruct *ls = &gl->gl_sbd->sd_lockstruct;
1365
1332 gl->gl_reply = ret; 1366 gl->gl_reply = ret;
1367
1333 if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) { 1368 if (unlikely(test_bit(DFL_BLOCK_LOCKS, &ls->ls_flags))) {
1334 struct gfs2_holder *gh;
1335 spin_lock(&gl->gl_spin); 1369 spin_lock(&gl->gl_spin);
1336 gh = find_first_waiter(gl); 1370 if (gfs2_should_freeze(gl)) {
1337 if ((!(gh && (gh->gh_flags & LM_FLAG_NOEXP)) &&
1338 (gl->gl_target != LM_ST_UNLOCKED)) ||
1339 ((ret & ~LM_OUT_ST_MASK) != 0))
1340 set_bit(GLF_FROZEN, &gl->gl_flags); 1371 set_bit(GLF_FROZEN, &gl->gl_flags);
1341 spin_unlock(&gl->gl_spin); 1372 spin_unlock(&gl->gl_spin);
1342 if (test_bit(GLF_FROZEN, &gl->gl_flags))
1343 return; 1373 return;
1374 }
1375 spin_unlock(&gl->gl_spin);
1344 } 1376 }
1345 set_bit(GLF_REPLY_PENDING, &gl->gl_flags); 1377 set_bit(GLF_REPLY_PENDING, &gl->gl_flags);
1346 gfs2_glock_hold(gl); 1378 gfs2_glock_hold(gl);