aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2
diff options
context:
space:
mode:
authorSteven Whitehouse <swhiteho@redhat.com>2010-07-23 09:05:51 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2010-07-29 04:37:38 -0400
commitd5341a92416706808dc5cd847826f28c08063c8c (patch)
tree48f6680c25d2fab956c52cd5021110f47f2ddf54 /fs/gfs2
parent4244b52e18be959ced77b984f268e46a0a7654e3 (diff)
GFS2: Make "try" lock not try quite so hard
This looks like a big change, but in reality its only a single line of actual code change, the rest is just moving a function to before its new caller. The "try" flag for glocks is a rather subtle and delicate setting since it requires that the state machine tries just hard enough to ensure that it has a good chance of getting the requested lock, but no so hard that the request can land up blocked behind another. The patch adds in an additional check which will fail any queued try locks if there is another request blocking the try lock request which is not granted and compatible, nor in progress already. The check is made only after all pending locks which may be granted have been granted. I've checked this with the reproducer for the reported flock bug which this is intended to fix, and it now passes. Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2')
-rw-r--r--fs/gfs2/glock.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/fs/gfs2/glock.c b/fs/gfs2/glock.c
index 0898f3ec8212..717531d1b2a8 100644
--- a/fs/gfs2/glock.c
+++ b/fs/gfs2/glock.c
@@ -328,6 +328,30 @@ static void gfs2_holder_wake(struct gfs2_holder *gh)
328} 328}
329 329
330/** 330/**
331 * do_error - Something unexpected has happened during a lock request
332 *
333 */
334
335static inline void do_error(struct gfs2_glock *gl, const int ret)
336{
337 struct gfs2_holder *gh, *tmp;
338
339 list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
340 if (test_bit(HIF_HOLDER, &gh->gh_iflags))
341 continue;
342 if (ret & LM_OUT_ERROR)
343 gh->gh_error = -EIO;
344 else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
345 gh->gh_error = GLR_TRYFAILED;
346 else
347 continue;
348 list_del_init(&gh->gh_list);
349 trace_gfs2_glock_queue(gh, 0);
350 gfs2_holder_wake(gh);
351 }
352}
353
354/**
331 * do_promote - promote as many requests as possible on the current queue 355 * do_promote - promote as many requests as possible on the current queue
332 * @gl: The glock 356 * @gl: The glock
333 * 357 *
@@ -375,36 +399,13 @@ restart:
375 } 399 }
376 if (gh->gh_list.prev == &gl->gl_holders) 400 if (gh->gh_list.prev == &gl->gl_holders)
377 return 1; 401 return 1;
402 do_error(gl, 0);
378 break; 403 break;
379 } 404 }
380 return 0; 405 return 0;
381} 406}
382 407
383/** 408/**
384 * do_error - Something unexpected has happened during a lock request
385 *
386 */
387
388static inline void do_error(struct gfs2_glock *gl, const int ret)
389{
390 struct gfs2_holder *gh, *tmp;
391
392 list_for_each_entry_safe(gh, tmp, &gl->gl_holders, gh_list) {
393 if (test_bit(HIF_HOLDER, &gh->gh_iflags))
394 continue;
395 if (ret & LM_OUT_ERROR)
396 gh->gh_error = -EIO;
397 else if (gh->gh_flags & (LM_FLAG_TRY | LM_FLAG_TRY_1CB))
398 gh->gh_error = GLR_TRYFAILED;
399 else
400 continue;
401 list_del_init(&gh->gh_list);
402 trace_gfs2_glock_queue(gh, 0);
403 gfs2_holder_wake(gh);
404 }
405}
406
407/**
408 * find_first_waiter - find the first gh that's waiting for the glock 409 * find_first_waiter - find the first gh that's waiting for the glock
409 * @gl: the glock 410 * @gl: the glock
410 */ 411 */