aboutsummaryrefslogtreecommitdiffstats
path: root/fs/dlm
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2012-06-05 16:55:19 -0400
committerDavid Teigland <teigland@redhat.com>2012-07-16 15:18:22 -0400
commitc503a62103c46d56447f56306b52be6f844689ba (patch)
treecfc821efb8d7cd73e411d25251607428769e6e9e /fs/dlm
parent6d768177c282637a7943e72b4b2b148e7553ecf1 (diff)
dlm: fix conversion deadlock from recovery
The process of rebuilding locks on a new master during recovery could re-order the locks on the convert queue, creating an "in place" conversion deadlock that would not be resolved. Fix this by not considering queue order when granting conversions after recovery. Signed-off-by: David Teigland <teigland@redhat.com>
Diffstat (limited to 'fs/dlm')
-rw-r--r--fs/dlm/lock.c55
-rw-r--r--fs/dlm/recover.c10
2 files changed, 48 insertions, 17 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c
index c7c6cf9e8685..04e3f15aa0cc 100644
--- a/fs/dlm/lock.c
+++ b/fs/dlm/lock.c
@@ -2279,10 +2279,14 @@ static int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2)
2279 * immediate request, it is 0 if called later, after the lock has been 2279 * immediate request, it is 0 if called later, after the lock has been
2280 * queued. 2280 * queued.
2281 * 2281 *
2282 * recover is 1 if dlm_recover_grant() is trying to grant conversions
2283 * after recovery.
2284 *
2282 * References are from chapter 6 of "VAXcluster Principles" by Roy Davis 2285 * References are from chapter 6 of "VAXcluster Principles" by Roy Davis
2283 */ 2286 */
2284 2287
2285static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now) 2288static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
2289 int recover)
2286{ 2290{
2287 int8_t conv = (lkb->lkb_grmode != DLM_LOCK_IV); 2291 int8_t conv = (lkb->lkb_grmode != DLM_LOCK_IV);
2288 2292
@@ -2314,7 +2318,7 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
2314 */ 2318 */
2315 2319
2316 if (queue_conflict(&r->res_grantqueue, lkb)) 2320 if (queue_conflict(&r->res_grantqueue, lkb))
2317 goto out; 2321 return 0;
2318 2322
2319 /* 2323 /*
2320 * 6-3: By default, a conversion request is immediately granted if the 2324 * 6-3: By default, a conversion request is immediately granted if the
@@ -2323,7 +2327,24 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
2323 */ 2327 */
2324 2328
2325 if (queue_conflict(&r->res_convertqueue, lkb)) 2329 if (queue_conflict(&r->res_convertqueue, lkb))
2326 goto out; 2330 return 0;
2331
2332 /*
2333 * The RECOVER_GRANT flag means dlm_recover_grant() is granting
2334 * locks for a recovered rsb, on which lkb's have been rebuilt.
2335 * The lkb's may have been rebuilt on the queues in a different
2336 * order than they were in on the previous master. So, granting
2337 * queued conversions in order after recovery doesn't make sense
2338 * since the order hasn't been preserved anyway. The new order
2339 * could also have created a new "in place" conversion deadlock.
2340 * (e.g. old, failed master held granted EX, with PR->EX, NL->EX.
2341 * After recovery, there would be no granted locks, and possibly
2342 * NL->EX, PR->EX, an in-place conversion deadlock.) So, after
2343 * recovery, grant conversions without considering order.
2344 */
2345
2346 if (conv && recover)
2347 return 1;
2327 2348
2328 /* 2349 /*
2329 * 6-5: But the default algorithm for deciding whether to grant or 2350 * 6-5: But the default algorithm for deciding whether to grant or
@@ -2360,7 +2381,7 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
2360 if (list_empty(&r->res_convertqueue)) 2381 if (list_empty(&r->res_convertqueue))
2361 return 1; 2382 return 1;
2362 else 2383 else
2363 goto out; 2384 return 0;
2364 } 2385 }
2365 2386
2366 /* 2387 /*
@@ -2406,12 +2427,12 @@ static int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now)
2406 if (!now && !conv && list_empty(&r->res_convertqueue) && 2427 if (!now && !conv && list_empty(&r->res_convertqueue) &&
2407 first_in_list(lkb, &r->res_waitqueue)) 2428 first_in_list(lkb, &r->res_waitqueue))
2408 return 1; 2429 return 1;
2409 out: 2430
2410 return 0; 2431 return 0;
2411} 2432}
2412 2433
2413static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, 2434static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
2414 int *err) 2435 int recover, int *err)
2415{ 2436{
2416 int rv; 2437 int rv;
2417 int8_t alt = 0, rqmode = lkb->lkb_rqmode; 2438 int8_t alt = 0, rqmode = lkb->lkb_rqmode;
@@ -2420,7 +2441,7 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
2420 if (err) 2441 if (err)
2421 *err = 0; 2442 *err = 0;
2422 2443
2423 rv = _can_be_granted(r, lkb, now); 2444 rv = _can_be_granted(r, lkb, now, recover);
2424 if (rv) 2445 if (rv)
2425 goto out; 2446 goto out;
2426 2447
@@ -2461,7 +2482,7 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now,
2461 2482
2462 if (alt) { 2483 if (alt) {
2463 lkb->lkb_rqmode = alt; 2484 lkb->lkb_rqmode = alt;
2464 rv = _can_be_granted(r, lkb, now); 2485 rv = _can_be_granted(r, lkb, now, 0);
2465 if (rv) 2486 if (rv)
2466 lkb->lkb_sbflags |= DLM_SBF_ALTMODE; 2487 lkb->lkb_sbflags |= DLM_SBF_ALTMODE;
2467 else 2488 else
@@ -2485,6 +2506,7 @@ static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw,
2485 unsigned int *count) 2506 unsigned int *count)
2486{ 2507{
2487 struct dlm_lkb *lkb, *s; 2508 struct dlm_lkb *lkb, *s;
2509 int recover = rsb_flag(r, RSB_RECOVER_GRANT);
2488 int hi, demoted, quit, grant_restart, demote_restart; 2510 int hi, demoted, quit, grant_restart, demote_restart;
2489 int deadlk; 2511 int deadlk;
2490 2512
@@ -2498,7 +2520,7 @@ static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw,
2498 demoted = is_demoted(lkb); 2520 demoted = is_demoted(lkb);
2499 deadlk = 0; 2521 deadlk = 0;
2500 2522
2501 if (can_be_granted(r, lkb, 0, &deadlk)) { 2523 if (can_be_granted(r, lkb, 0, recover, &deadlk)) {
2502 grant_lock_pending(r, lkb); 2524 grant_lock_pending(r, lkb);
2503 grant_restart = 1; 2525 grant_restart = 1;
2504 if (count) 2526 if (count)
@@ -2542,7 +2564,7 @@ static int grant_pending_wait(struct dlm_rsb *r, int high, int *cw,
2542 struct dlm_lkb *lkb, *s; 2564 struct dlm_lkb *lkb, *s;
2543 2565
2544 list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) { 2566 list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) {
2545 if (can_be_granted(r, lkb, 0, NULL)) { 2567 if (can_be_granted(r, lkb, 0, 0, NULL)) {
2546 grant_lock_pending(r, lkb); 2568 grant_lock_pending(r, lkb);
2547 if (count) 2569 if (count)
2548 (*count)++; 2570 (*count)++;
@@ -3042,7 +3064,7 @@ static int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb)
3042{ 3064{
3043 int error = 0; 3065 int error = 0;
3044 3066
3045 if (can_be_granted(r, lkb, 1, NULL)) { 3067 if (can_be_granted(r, lkb, 1, 0, NULL)) {
3046 grant_lock(r, lkb); 3068 grant_lock(r, lkb);
3047 queue_cast(r, lkb, 0); 3069 queue_cast(r, lkb, 0);
3048 goto out; 3070 goto out;
@@ -3082,7 +3104,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
3082 3104
3083 /* changing an existing lock may allow others to be granted */ 3105 /* changing an existing lock may allow others to be granted */
3084 3106
3085 if (can_be_granted(r, lkb, 1, &deadlk)) { 3107 if (can_be_granted(r, lkb, 1, 0, &deadlk)) {
3086 grant_lock(r, lkb); 3108 grant_lock(r, lkb);
3087 queue_cast(r, lkb, 0); 3109 queue_cast(r, lkb, 0);
3088 goto out; 3110 goto out;
@@ -3108,7 +3130,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb)
3108 3130
3109 if (is_demoted(lkb)) { 3131 if (is_demoted(lkb)) {
3110 grant_pending_convert(r, DLM_LOCK_IV, NULL, NULL); 3132 grant_pending_convert(r, DLM_LOCK_IV, NULL, NULL);
3111 if (_can_be_granted(r, lkb, 1)) { 3133 if (_can_be_granted(r, lkb, 1, 0)) {
3112 grant_lock(r, lkb); 3134 grant_lock(r, lkb);
3113 queue_cast(r, lkb, 0); 3135 queue_cast(r, lkb, 0);
3114 goto out; 3136 goto out;
@@ -5373,9 +5395,10 @@ static struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket)
5373 5395
5374 if (!rsb_flag(r, RSB_RECOVER_GRANT)) 5396 if (!rsb_flag(r, RSB_RECOVER_GRANT))
5375 continue; 5397 continue;
5376 rsb_clear_flag(r, RSB_RECOVER_GRANT); 5398 if (!is_master(r)) {
5377 if (!is_master(r)) 5399 rsb_clear_flag(r, RSB_RECOVER_GRANT);
5378 continue; 5400 continue;
5401 }
5379 hold_rsb(r); 5402 hold_rsb(r);
5380 spin_unlock(&ls->ls_rsbtbl[bucket].lock); 5403 spin_unlock(&ls->ls_rsbtbl[bucket].lock);
5381 return r; 5404 return r;
@@ -5420,7 +5443,9 @@ void dlm_recover_grant(struct dlm_ls *ls)
5420 rsb_count++; 5443 rsb_count++;
5421 count = 0; 5444 count = 0;
5422 lock_rsb(r); 5445 lock_rsb(r);
5446 /* the RECOVER_GRANT flag is checked in the grant path */
5423 grant_pending_locks(r, &count); 5447 grant_pending_locks(r, &count);
5448 rsb_clear_flag(r, RSB_RECOVER_GRANT);
5424 lkb_count += count; 5449 lkb_count += count;
5425 confirm_master(r, 0); 5450 confirm_master(r, 0);
5426 unlock_rsb(r); 5451 unlock_rsb(r);
diff --git a/fs/dlm/recover.c b/fs/dlm/recover.c
index 12702cc533b3..4a7a76e42fc3 100644
--- a/fs/dlm/recover.c
+++ b/fs/dlm/recover.c
@@ -804,6 +804,7 @@ static void recover_lvb(struct dlm_rsb *r)
804 804
805static void recover_conversion(struct dlm_rsb *r) 805static void recover_conversion(struct dlm_rsb *r)
806{ 806{
807 struct dlm_ls *ls = r->res_ls;
807 struct dlm_lkb *lkb; 808 struct dlm_lkb *lkb;
808 int grmode = -1; 809 int grmode = -1;
809 810
@@ -818,10 +819,15 @@ static void recover_conversion(struct dlm_rsb *r)
818 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) { 819 list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) {
819 if (lkb->lkb_grmode != DLM_LOCK_IV) 820 if (lkb->lkb_grmode != DLM_LOCK_IV)
820 continue; 821 continue;
821 if (grmode == -1) 822 if (grmode == -1) {
823 log_debug(ls, "recover_conversion %x set gr to rq %d",
824 lkb->lkb_id, lkb->lkb_rqmode);
822 lkb->lkb_grmode = lkb->lkb_rqmode; 825 lkb->lkb_grmode = lkb->lkb_rqmode;
823 else 826 } else {
827 log_debug(ls, "recover_conversion %x set gr %d",
828 lkb->lkb_id, grmode);
824 lkb->lkb_grmode = grmode; 829 lkb->lkb_grmode = grmode;
830 }
825 } 831 }
826} 832}
827 833