diff options
author | tsutomu.owa@toshiba.co.jp <tsutomu.owa@toshiba.co.jp> | 2017-09-15 15:17:23 -0400 |
---|---|---|
committer | David Teigland <teigland@redhat.com> | 2017-09-25 13:45:21 -0400 |
commit | 294e7e458763dc1d229cbbe7147a6034bfc6e39a (patch) | |
tree | 5b5d3cda6d51e5f5c8a4817b7f4446a2c181515f | |
parent | 173a31fe2b23b3ccc45d0b70edb225b1d836c31d (diff) |
DLM: fix conversion deadlock when DLM_LKF_NODLCKWT flag is set
When the DLM_LKF_NODLCKWT flag was set, even if conversion deadlock
was detected, the caller of can_be_granted() was unknown.
We change the behavior of can_be_granted() and change it to detect
conversion deadlock regardless of whether the DLM_LKF_NODLCKWT flag
is set or not. And depending on whether the DLM_LKF_NODLCKWT flag
is set or not, we change the behavior at the caller of can_be_granted().
This fix has no effect except when using DLM_LKF_NODLCKWT flag.
Currently, ocfs2 uses the DLM_LKF_NODLCKWT flag and does not expect a
cancel operation from conversion deadlock when calling dlm_lock().
ocfs2 is implemented to perform a cancel operation by requesting
BASTs (callback).
Signed-off-by: Tadashi Miyauchi <miyauchi@toshiba-tops.co.jp>
Signed-off-by: Tsutomu Owa <tsutomu.owa@toshiba.co.jp>
Signed-off-by: David Teigland <teigland@redhat.com>
-rw-r--r-- | fs/dlm/lock.c | 42 |
1 files changed, 23 insertions, 19 deletions
diff --git a/fs/dlm/lock.c b/fs/dlm/lock.c index d4aaddec1b16..f145a2a9d6cb 100644 --- a/fs/dlm/lock.c +++ b/fs/dlm/lock.c | |||
@@ -2465,14 +2465,12 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, | |||
2465 | if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) { | 2465 | if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) { |
2466 | lkb->lkb_grmode = DLM_LOCK_NL; | 2466 | lkb->lkb_grmode = DLM_LOCK_NL; |
2467 | lkb->lkb_sbflags |= DLM_SBF_DEMOTED; | 2467 | lkb->lkb_sbflags |= DLM_SBF_DEMOTED; |
2468 | } else if (!(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) { | 2468 | } else if (err) { |
2469 | if (err) | 2469 | *err = -EDEADLK; |
2470 | *err = -EDEADLK; | 2470 | } else { |
2471 | else { | 2471 | log_print("can_be_granted deadlock %x now %d", |
2472 | log_print("can_be_granted deadlock %x now %d", | 2472 | lkb->lkb_id, now); |
2473 | lkb->lkb_id, now); | 2473 | dlm_dump_rsb(r); |
2474 | dlm_dump_rsb(r); | ||
2475 | } | ||
2476 | } | 2474 | } |
2477 | goto out; | 2475 | goto out; |
2478 | } | 2476 | } |
@@ -2501,13 +2499,6 @@ static int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, | |||
2501 | return rv; | 2499 | return rv; |
2502 | } | 2500 | } |
2503 | 2501 | ||
2504 | /* FIXME: I don't think that can_be_granted() can/will demote or find deadlock | ||
2505 | for locks pending on the convert list. Once verified (watch for these | ||
2506 | log_prints), we should be able to just call _can_be_granted() and not | ||
2507 | bother with the demote/deadlk cases here (and there's no easy way to deal | ||
2508 | with a deadlk here, we'd have to generate something like grant_lock with | ||
2509 | the deadlk error.) */ | ||
2510 | |||
2511 | /* Returns the highest requested mode of all blocked conversions; sets | 2502 | /* Returns the highest requested mode of all blocked conversions; sets |
2512 | cw if there's a blocked conversion to DLM_LOCK_CW. */ | 2503 | cw if there's a blocked conversion to DLM_LOCK_CW. */ |
2513 | 2504 | ||
@@ -2545,9 +2536,22 @@ static int grant_pending_convert(struct dlm_rsb *r, int high, int *cw, | |||
2545 | } | 2536 | } |
2546 | 2537 | ||
2547 | if (deadlk) { | 2538 | if (deadlk) { |
2548 | log_print("WARN: pending deadlock %x node %d %s", | 2539 | /* |
2549 | lkb->lkb_id, lkb->lkb_nodeid, r->res_name); | 2540 | * If DLM_LKB_NODLKWT flag is set and conversion |
2550 | dlm_dump_rsb(r); | 2541 | * deadlock is detected, we request blocking AST and |
2542 | * down (or cancel) conversion. | ||
2543 | */ | ||
2544 | if (lkb->lkb_exflags & DLM_LKF_NODLCKWT) { | ||
2545 | if (lkb->lkb_highbast < lkb->lkb_rqmode) { | ||
2546 | queue_bast(r, lkb, lkb->lkb_rqmode); | ||
2547 | lkb->lkb_highbast = lkb->lkb_rqmode; | ||
2548 | } | ||
2549 | } else { | ||
2550 | log_print("WARN: pending deadlock %x node %d %s", | ||
2551 | lkb->lkb_id, lkb->lkb_nodeid, | ||
2552 | r->res_name); | ||
2553 | dlm_dump_rsb(r); | ||
2554 | } | ||
2551 | continue; | 2555 | continue; |
2552 | } | 2556 | } |
2553 | 2557 | ||
@@ -3123,7 +3127,7 @@ static int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) | |||
3123 | deadlock, so we leave it on the granted queue and return EDEADLK in | 3127 | deadlock, so we leave it on the granted queue and return EDEADLK in |
3124 | the ast for the convert. */ | 3128 | the ast for the convert. */ |
3125 | 3129 | ||
3126 | if (deadlk) { | 3130 | if (deadlk && !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) { |
3127 | /* it's left on the granted queue */ | 3131 | /* it's left on the granted queue */ |
3128 | revert_lock(r, lkb); | 3132 | revert_lock(r, lkb); |
3129 | queue_cast(r, lkb, -EDEADLK); | 3133 | queue_cast(r, lkb, -EDEADLK); |