Skip to content

Commit dfe5a6c

Browse files
Alexander Aringteigland
authored andcommitted
dlm: make add_to_waiters() that it can't fail
If add_to_waiters() fails we have a problem because the previous called functions such as validate_lock_args() or validate_unlock_args() sets specific lkb values that are set for a request, there exists no way back to revert those changes. When there is a pending lock request the original request arguments will be overwritten with unknown consequences. The good news are that I believe those cases that we fail in add_to_waiters() can't happen or very unlikely to happen (only if the DLM user does stupid API things), but if so we have the above mentioned problem. There are two conditions that will be removed here. The first one is the -EINVAL case which contains is_overlap_unlock() or (is_overlap_cancel() and mstype == DLM_MSG_CANCEL). The is_overlap_unlock() is missing for the normal UNLOCK case which is moved to validate_unlock_args(). The is_overlap_cancel() already happens in validate_unlock_args() when DLM_LKF_CANCEL is set. In case of validate_lock_args() we check on is_overlap() when it is not a new request, on a new request the lkb is always new and does not have those values set. The -EBUSY check can't happen in case as for non new lock requests (when DLM_LKF_CONVERT is set) we already check in validate_lock_args() for lkb_wait_type and is_overlap(). Then there is only validate_unlock_args() that will never hit the default case because dlm_unlock() will produce DLM_MSG_UNLOCK and DLM_MSG_CANCEL messages. Signed-off-by: Alexander Aring <aahringo@redhat.com> Signed-off-by: David Teigland <teigland@redhat.com>
1 parent cc5580b commit dfe5a6c

File tree

1 file changed

+14
-29
lines changed

1 file changed

+14
-29
lines changed

fs/dlm/lock.c

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1703,19 +1703,11 @@ static int msg_reply_type(int mstype)
17031703
/* add/remove lkb from global waiters list of lkb's waiting for
17041704
a reply from a remote node */
17051705

1706-
static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
1706+
static void add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
17071707
{
17081708
struct dlm_ls *ls = lkb->lkb_resource->res_ls;
1709-
int error = 0;
17101709

17111710
spin_lock_bh(&ls->ls_waiters_lock);
1712-
1713-
if (is_overlap_unlock(lkb) ||
1714-
(is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL))) {
1715-
error = -EINVAL;
1716-
goto out;
1717-
}
1718-
17191711
if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) {
17201712
switch (mstype) {
17211713
case DLM_MSG_UNLOCK:
@@ -1725,7 +1717,11 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
17251717
set_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags);
17261718
break;
17271719
default:
1728-
error = -EBUSY;
1720+
/* should never happen as validate_lock_args() checks
1721+
* on lkb_wait_type and validate_unlock_args() only
1722+
* creates UNLOCK or CANCEL messages.
1723+
*/
1724+
WARN_ON_ONCE(1);
17291725
goto out;
17301726
}
17311727
lkb->lkb_wait_count++;
@@ -1747,12 +1743,7 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
17471743
hold_lkb(lkb);
17481744
list_add(&lkb->lkb_wait_reply, &ls->ls_waiters);
17491745
out:
1750-
if (error)
1751-
log_error(ls, "addwait error %x %d flags %x %d %d %s",
1752-
lkb->lkb_id, error, dlm_iflags_val(lkb), mstype,
1753-
lkb->lkb_wait_type, lkb->lkb_resource->res_name);
17541746
spin_unlock_bh(&ls->ls_waiters_lock);
1755-
return error;
17561747
}
17571748

17581749
/* We clear the RESEND flag because we might be taking an lkb off the waiters
@@ -2926,13 +2917,16 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
29262917
goto out;
29272918
}
29282919

2920+
if (is_overlap_unlock(lkb))
2921+
goto out;
2922+
29292923
/* cancel not allowed with another cancel/unlock in progress */
29302924

29312925
if (args->flags & DLM_LKF_CANCEL) {
29322926
if (lkb->lkb_exflags & DLM_LKF_CANCEL)
29332927
goto out;
29342928

2935-
if (is_overlap(lkb))
2929+
if (is_overlap_cancel(lkb))
29362930
goto out;
29372931

29382932
if (test_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags)) {
@@ -2970,9 +2964,6 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
29702964
if (lkb->lkb_exflags & DLM_LKF_FORCEUNLOCK)
29712965
goto out;
29722966

2973-
if (is_overlap_unlock(lkb))
2974-
goto out;
2975-
29762967
if (test_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags)) {
29772968
set_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags);
29782969
rv = -EBUSY;
@@ -3608,10 +3599,7 @@ static int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype)
36083599

36093600
to_nodeid = r->res_nodeid;
36103601

3611-
error = add_to_waiters(lkb, mstype, to_nodeid);
3612-
if (error)
3613-
return error;
3614-
3602+
add_to_waiters(lkb, mstype, to_nodeid);
36153603
error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh);
36163604
if (error)
36173605
goto fail;
@@ -3714,10 +3702,7 @@ static int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb)
37143702

37153703
to_nodeid = dlm_dir_nodeid(r);
37163704

3717-
error = add_to_waiters(lkb, DLM_MSG_LOOKUP, to_nodeid);
3718-
if (error)
3719-
return error;
3720-
3705+
add_to_waiters(lkb, DLM_MSG_LOOKUP, to_nodeid);
37213706
error = create_message(r, NULL, to_nodeid, DLM_MSG_LOOKUP, &ms, &mh);
37223707
if (error)
37233708
goto fail;
@@ -6342,8 +6327,8 @@ int dlm_debug_add_lkb_to_waiters(struct dlm_ls *ls, uint32_t lkb_id,
63426327
if (error)
63436328
return error;
63446329

6345-
error = add_to_waiters(lkb, mstype, to_nodeid);
6330+
add_to_waiters(lkb, mstype, to_nodeid);
63466331
dlm_put_lkb(lkb);
6347-
return error;
6332+
return 0;
63486333
}
63496334

0 commit comments

Comments
 (0)