Skip to content

Commit a892b12

Browse files
author
Andreas Gruenbacher
committed
gfs2: Expect -EBUSY after canceling dlm locking requests
Due to the asynchronous nature of the dlm api, when we request a pending locking request to be canceled with dlm_unlock(DLM_LKF_CANCEL), the locking request will either complete before it could be canceled, or the cancellation will succeed. In either case, gdlm_ast will be called once and the status will indicate the outcome of the locking request, with -DLM_ECANCEL indicating a canceled request. Inside dlm, when a locking request completes before its cancel request could be processed, gdlm_ast will be called, but the lock will still be considered busy until a DLM_MSG_CANCEL_REPLY message completes the cancel request. During that time, successive dlm_lock() or dlm_unlock() requests for that lock will return -EBUSY. In other words, waiting for the gdlm_ast call before issuing the next locking request is not enough. There is no way of waiting for a cancel request to actually complete, either. We rarely cancel locking requests, but when we do, we don't know when the next locking request for that lock will occur. This means that any dlm_lock() or dlm_unlock() call can potentially return -EBUSY. When that happens, this patch simply repeats the request after a short pause. This workaround could be improved upon by tracking for which dlm locks cancel requests have been issued, but that isn't strictly necessary and it would complicate the code. We haven't seen -EBUSY errors from dlm without cancel requests. Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com>
1 parent 7336905 commit a892b12

1 file changed

Lines changed: 14 additions & 1 deletion

File tree

fs/gfs2/lock_dlm.c

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
261261
int req;
262262
u32 lkf;
263263
char strname[GDLM_STRNAME_BYTES] = "";
264+
int error;
264265

265266
req = make_mode(gl->gl_name.ln_sbd, req_state);
266267
lkf = make_flags(gl, flags, req);
@@ -279,8 +280,14 @@ static int gdlm_lock(struct gfs2_glock *gl, unsigned int req_state,
279280
* Submit the actual lock request.
280281
*/
281282

282-
return dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
283+
again:
284+
error = dlm_lock(ls->ls_dlm, req, &gl->gl_lksb, lkf, strname,
283285
GDLM_STRNAME_BYTES - 1, 0, gdlm_ast, gl, gdlm_bast);
286+
if (error == -EBUSY) {
287+
msleep(20);
288+
goto again;
289+
}
290+
return error;
284291
}
285292

286293
static void gdlm_put_lock(struct gfs2_glock *gl)
@@ -312,8 +319,14 @@ static void gdlm_put_lock(struct gfs2_glock *gl)
312319
return;
313320
}
314321

322+
again:
315323
error = dlm_unlock(ls->ls_dlm, gl->gl_lksb.sb_lkid, DLM_LKF_VALBLK,
316324
NULL, gl);
325+
if (error == -EBUSY) {
326+
msleep(20);
327+
goto again;
328+
}
329+
317330
if (error) {
318331
fs_err(sdp, "gdlm_unlock %x,%llx err=%d\n",
319332
gl->gl_name.ln_type,

0 commit comments

Comments
 (0)