Patch "ocfs2/dlm: fix race between convert and recovery" has been added to the 3.14-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
ocfs2/dlm: fix race between convert and recovery
to the 3.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
ocfs2-dlm-fix-race-between-convert-and-recovery.patch
and it can be found in the queue-3.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
ac7cf246dfdbec3d8fed296c7bf30e16f5099dacMon Sep 17 00:00:00 2001
From: Joseph Qi <[email protected]>
Date: Fri, 25 Mar 2016 14:21:26 -0700
Subject: ocfs2/dlm: fix race between convert and recovery
From: Joseph Qi <[email protected]>
commit ac7cf246dfdbec3d8fed296c7bf30e16f5099dac upstream.
There is a race window between dlmconvert_remote and dlm_move_lockres_to_recovery_list, which will cause a lock with OCFS2_LOCK_BUSY in grant list, thus system hangs.
dlmconvert_remote
{
spin_lock(&res->spinlock);
list_move_tail(&lock->list, &res->converting);
lock->convert_pending = 1;
spin_unlock(&res->spinlock);
status = dlm_send_remote_convert_request();
>>>>>> race window, master has queued ast and return DLM_NORMAL,
and then down before sending ast.
this node detects master down and calls
dlm_move_lockres_to_recovery_list, which will revert the
lock to grant list.
Then OCFS2_LOCK_BUSY won't be cleared as new master won't
send ast any more because it thinks already be authorized.
spin_lock(&res->spinlock);
lock->convert_pending = 0;
if (status != DLM_NORMAL)
dlm_revert_pending_convert(res, lock);
spin_unlock(&res->spinlock);
}In this case, check if res->state has DLM_LOCK_RES_RECOVERING bit set (res is still in recovering) or res master changed (new master has finished recovery), reset the status to DLM_RECOVERING, then it will retry convert.
--- fs/ocfs2/dlm/dlmconvert.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
fs/ocfs2/dlm/dlmconvert.c +10 -1
@@ -262,6 +262,7 @@ enum dlm_status dlmconvert_remote(struct struct dlm_lock *lock, int flags, int type) { enum dlm_status status; +u8 old_owner = res->owner;mlog (0 ,"type=%d, convert_type=%d, busy=%d\n" , lock->ml.type, lock->ml.convert_type, res->state &DLM_LOCK_RES_IN_PROGRESS );
@@ -316,11 +317,19 @@ enum dlm_status dlmconvert_remote(structspin_lock (&res->spinlock); res->state &= ~DLM_LOCK_RES_IN_PROGRESS ; lock->convert_pending =0 ; -/* if it failed, move it back to granted queue */ +/* if it failed, move it back to granted queue. +* if master returns DLM_NORMAL and then down before sending ast, +* it may have already been moved to granted queue, reset to +* DLM_RECOVERING and retry convert */ if (status !=DLM_NORMAL ) {if (status !=DLM_NOTQUEUED )dlm_error (status);dlm_revert_pending_convert (res, lock); + }else if ((res->state &DLM_LOCK_RES_RECOVERING ) || + (old_owner != res->owner)) { +mlog (0 ,"res %.*s is in recovering or has been recovered.\n" , + res->lockname.len, res->lockname.name); + status =DLM_RECOVERING ; } bail:spin_unlock (&res->spinlock);
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/ocfs2-dlm-fix-bug-in-dlm_move_lockres_to_recovery_list.patch queue-3.14/ocfs2-dlm-fix-race-between-convert-and-recovery.patch