Skip to content

Commit b3603fc

Browse files
committed
Merge tag 'dlm-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm
Pull dlm updates from David Teigland: - Fix mistaken variable assignment that caused a refcounting problem - Revert a recent change that began using atomic counters where they were not needed (for lkb wait_count) - Add comments around forced state reset for waiting lock operations during recovery * tag 'dlm-6.9' of git://git.kernel.org/pub/scm/linux/kernel/git/teigland/linux-dlm: dlm: add comments about forced waiters reset dlm: revert atomic_t lkb_wait_count dlm: fix user space lkb refcounting
2 parents 6207b37 + c53309b commit b3603fc

File tree

3 files changed

+81
-39
lines changed

3 files changed

+81
-39
lines changed

fs/dlm/dlm_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ struct dlm_lkb {
246246
int8_t lkb_highbast; /* highest mode bast sent for */
247247

248248
int8_t lkb_wait_type; /* type of reply waiting for */
249-
atomic_t lkb_wait_count;
249+
int8_t lkb_wait_count;
250250
int lkb_wait_nodeid; /* for debugging */
251251

252252
struct list_head lkb_statequeue; /* rsb g/c/w list */

fs/dlm/lock.c

Lines changed: 75 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,7 +1407,6 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
14071407
{
14081408
struct dlm_ls *ls = lkb->lkb_resource->res_ls;
14091409
int error = 0;
1410-
int wc;
14111410

14121411
mutex_lock(&ls->ls_waiters_mutex);
14131412

@@ -1429,17 +1428,20 @@ static int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid)
14291428
error = -EBUSY;
14301429
goto out;
14311430
}
1432-
wc = atomic_inc_return(&lkb->lkb_wait_count);
1431+
lkb->lkb_wait_count++;
14331432
hold_lkb(lkb);
14341433

14351434
log_debug(ls, "addwait %x cur %d overlap %d count %d f %x",
1436-
lkb->lkb_id, lkb->lkb_wait_type, mstype, wc,
1437-
dlm_iflags_val(lkb));
1435+
lkb->lkb_id, lkb->lkb_wait_type, mstype,
1436+
lkb->lkb_wait_count, dlm_iflags_val(lkb));
14381437
goto out;
14391438
}
14401439

1441-
wc = atomic_fetch_inc(&lkb->lkb_wait_count);
1442-
DLM_ASSERT(!wc, dlm_print_lkb(lkb); printk("wait_count %d\n", wc););
1440+
DLM_ASSERT(!lkb->lkb_wait_count,
1441+
dlm_print_lkb(lkb);
1442+
printk("wait_count %d\n", lkb->lkb_wait_count););
1443+
1444+
lkb->lkb_wait_count++;
14431445
lkb->lkb_wait_type = mstype;
14441446
lkb->lkb_wait_nodeid = to_nodeid; /* for debugging */
14451447
hold_lkb(lkb);
@@ -1502,7 +1504,7 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype,
15021504
log_debug(ls, "remwait %x convert_reply zap overlap_cancel",
15031505
lkb->lkb_id);
15041506
lkb->lkb_wait_type = 0;
1505-
atomic_dec(&lkb->lkb_wait_count);
1507+
lkb->lkb_wait_count--;
15061508
unhold_lkb(lkb);
15071509
goto out_del;
15081510
}
@@ -1529,15 +1531,16 @@ static int _remove_from_waiters(struct dlm_lkb *lkb, int mstype,
15291531
if (overlap_done && lkb->lkb_wait_type) {
15301532
log_error(ls, "remwait error %x reply %d wait_type %d overlap",
15311533
lkb->lkb_id, mstype, lkb->lkb_wait_type);
1532-
atomic_dec(&lkb->lkb_wait_count);
1534+
lkb->lkb_wait_count--;
15331535
unhold_lkb(lkb);
15341536
lkb->lkb_wait_type = 0;
15351537
}
15361538

1537-
DLM_ASSERT(atomic_read(&lkb->lkb_wait_count), dlm_print_lkb(lkb););
1539+
DLM_ASSERT(lkb->lkb_wait_count, dlm_print_lkb(lkb););
15381540

15391541
clear_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags);
1540-
if (atomic_dec_and_test(&lkb->lkb_wait_count))
1542+
lkb->lkb_wait_count--;
1543+
if (!lkb->lkb_wait_count)
15411544
list_del_init(&lkb->lkb_wait_reply);
15421545
unhold_lkb(lkb);
15431546
return 0;
@@ -2666,7 +2669,7 @@ static int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb,
26662669
goto out;
26672670

26682671
/* lock not allowed if there's any op in progress */
2669-
if (lkb->lkb_wait_type || atomic_read(&lkb->lkb_wait_count))
2672+
if (lkb->lkb_wait_type || lkb->lkb_wait_count)
26702673
goto out;
26712674

26722675
if (is_overlap(lkb))
@@ -2728,7 +2731,7 @@ static int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args)
27282731

27292732
/* normal unlock not allowed if there's any op in progress */
27302733
if (!(args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) &&
2731-
(lkb->lkb_wait_type || atomic_read(&lkb->lkb_wait_count)))
2734+
(lkb->lkb_wait_type || lkb->lkb_wait_count))
27322735
goto out;
27332736

27342737
/* an lkb may be waiting for an rsb lookup to complete where the
@@ -5011,21 +5014,32 @@ static struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls)
50115014
return lkb;
50125015
}
50135016

5014-
/* Deal with lookups and lkb's marked RESEND from _pre. We may now be the
5015-
master or dir-node for r. Processing the lkb may result in it being placed
5016-
back on waiters. */
5017-
5018-
/* We do this after normal locking has been enabled and any saved messages
5019-
(in requestqueue) have been processed. We should be confident that at
5020-
this point we won't get or process a reply to any of these waiting
5021-
operations. But, new ops may be coming in on the rsbs/locks here from
5022-
userspace or remotely. */
5023-
5024-
/* there may have been an overlap unlock/cancel prior to recovery or after
5025-
recovery. if before, the lkb may still have a pos wait_count; if after, the
5026-
overlap flag would just have been set and nothing new sent. we can be
5027-
confident here than any replies to either the initial op or overlap ops
5028-
prior to recovery have been received. */
5017+
/*
5018+
* Forced state reset for locks that were in the middle of remote operations
5019+
* when recovery happened (i.e. lkbs that were on the waiters list, waiting
5020+
* for a reply from a remote operation.) The lkbs remaining on the waiters
5021+
* list need to be reevaluated; some may need resending to a different node
5022+
* than previously, and some may now need local handling rather than remote.
5023+
*
5024+
* First, the lkb state for the voided remote operation is forcibly reset,
5025+
* equivalent to what remove_from_waiters() would normally do:
5026+
* . lkb removed from ls_waiters list
5027+
* . lkb wait_type cleared
5028+
* . lkb waiters_count cleared
5029+
* . lkb ref count decremented for each waiters_count (almost always 1,
5030+
* but possibly 2 in case of cancel/unlock overlapping, which means
5031+
* two remote replies were being expected for the lkb.)
5032+
*
5033+
* Second, the lkb is reprocessed like an original operation would be,
5034+
* by passing it to _request_lock or _convert_lock, which will either
5035+
* process the lkb operation locally, or send it to a remote node again
5036+
* and put the lkb back onto the waiters list.
5037+
*
5038+
* When reprocessing the lkb, we may find that it's flagged for an overlapping
5039+
* force-unlock or cancel, either from before recovery began, or after recovery
5040+
* finished. If this is the case, the unlock/cancel is done directly, and the
5041+
* original operation is not initiated again (no _request_lock/_convert_lock.)
5042+
*/
50295043

50305044
int dlm_recover_waiters_post(struct dlm_ls *ls)
50315045
{
@@ -5040,6 +5054,11 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
50405054
break;
50415055
}
50425056

5057+
/*
5058+
* Find an lkb from the waiters list that's been affected by
5059+
* recovery node changes, and needs to be reprocessed. Does
5060+
* hold_lkb(), adding a refcount.
5061+
*/
50435062
lkb = find_resend_waiter(ls);
50445063
if (!lkb)
50455064
break;
@@ -5048,6 +5067,11 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
50485067
hold_rsb(r);
50495068
lock_rsb(r);
50505069

5070+
/*
5071+
* If the lkb has been flagged for a force unlock or cancel,
5072+
* then the reprocessing below will be replaced by just doing
5073+
* the unlock/cancel directly.
5074+
*/
50515075
mstype = lkb->lkb_wait_type;
50525076
oc = test_and_clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT,
50535077
&lkb->lkb_iflags);
@@ -5061,22 +5085,40 @@ int dlm_recover_waiters_post(struct dlm_ls *ls)
50615085
r->res_nodeid, lkb->lkb_nodeid, lkb->lkb_wait_nodeid,
50625086
dlm_dir_nodeid(r), oc, ou);
50635087

5064-
/* At this point we assume that we won't get a reply to any
5065-
previous op or overlap op on this lock. First, do a big
5066-
remove_from_waiters() for all previous ops. */
5088+
/*
5089+
* No reply to the pre-recovery operation will now be received,
5090+
* so a forced equivalent of remove_from_waiters() is needed to
5091+
* reset the waiters state that was in place before recovery.
5092+
*/
50675093

50685094
clear_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags);
5095+
5096+
/* Forcibly clear wait_type */
50695097
lkb->lkb_wait_type = 0;
5070-
/* drop all wait_count references we still
5071-
* hold a reference for this iteration.
5098+
5099+
/*
5100+
* Forcibly reset wait_count and associated refcount. The
5101+
* wait_count will almost always be 1, but in case of an
5102+
* overlapping unlock/cancel it could be 2: see where
5103+
* add_to_waiters() finds the lkb is already on the waiters
5104+
* list and does lkb_wait_count++; hold_lkb().
50725105
*/
5073-
while (!atomic_dec_and_test(&lkb->lkb_wait_count))
5106+
while (lkb->lkb_wait_count) {
5107+
lkb->lkb_wait_count--;
50745108
unhold_lkb(lkb);
5109+
}
50755110

5111+
/* Forcibly remove from waiters list */
50765112
mutex_lock(&ls->ls_waiters_mutex);
50775113
list_del_init(&lkb->lkb_wait_reply);
50785114
mutex_unlock(&ls->ls_waiters_mutex);
50795115

5116+
/*
5117+
* The lkb is now clear of all prior waiters state and can be
5118+
* processed locally, or sent to remote node again, or directly
5119+
* cancelled/unlocked.
5120+
*/
5121+
50805122
if (oc || ou) {
50815123
/* do an unlock or cancel instead of resending */
50825124
switch (mstype) {

fs/dlm/user.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
806806
struct dlm_lkb *lkb;
807807
DECLARE_WAITQUEUE(wait, current);
808808
struct dlm_callback *cb;
809-
int rv, copy_lvb = 0;
809+
int rv, ret, copy_lvb = 0;
810810
int old_mode, new_mode;
811811

812812
if (count == sizeof(struct dlm_device_version)) {
@@ -906,17 +906,17 @@ static ssize_t device_read(struct file *file, char __user *buf, size_t count,
906906
trace_dlm_ast(lkb->lkb_resource->res_ls, lkb);
907907
}
908908

909-
rv = copy_result_to_user(lkb->lkb_ua,
910-
test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
911-
cb->flags, cb->mode, copy_lvb, buf, count);
909+
ret = copy_result_to_user(lkb->lkb_ua,
910+
test_bit(DLM_PROC_FLAGS_COMPAT, &proc->flags),
911+
cb->flags, cb->mode, copy_lvb, buf, count);
912912

913913
kref_put(&cb->ref, dlm_release_callback);
914914

915915
/* removes ref for proc->asts, may cause lkb to be freed */
916916
if (rv == DLM_DEQUEUE_CALLBACK_LAST)
917917
dlm_put_lkb(lkb);
918918

919-
return rv;
919+
return ret;
920920
}
921921

922922
static __poll_t device_poll(struct file *file, poll_table *wait)

0 commit comments

Comments
 (0)