NFSv4.1: Fix bug only first CB_NOTIFY_LOCK is handled
When a waiter is waked by CB_NOTIFY_LOCK, it will retry nfs4_proc_setlk(). The waiter may fail to nfs4_proc_setlk() and sleep again. However, the waiter is already removed from clp->cl_lock_waitq when handling CB_NOTIFY_LOCK in nfs4_wake_lock_waiter(). So any subsequent CB_NOTIFY_LOCK won't wake this waiter anymore. We should put the waiter back to clp->cl_lock_waitq before retrying. Cc: stable@vger.kernel.org #4.9+ Signed-off-by: Yihao Wu <wuyihao@linux.alibaba.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
52b042ab99
commit
ba851a39c9
|
@ -6987,20 +6987,22 @@ nfs4_retry_setlk(struct nfs4_state *state, int cmd, struct file_lock *request)
|
|||
init_wait(&wait);
|
||||
wait.private = &waiter;
|
||||
wait.func = nfs4_wake_lock_waiter;
|
||||
add_wait_queue(q, &wait);
|
||||
|
||||
while(!signalled()) {
|
||||
add_wait_queue(q, &wait);
|
||||
status = nfs4_proc_setlk(state, cmd, request);
|
||||
if ((status != -EAGAIN) || IS_SETLK(cmd))
|
||||
if ((status != -EAGAIN) || IS_SETLK(cmd)) {
|
||||
finish_wait(q, &wait);
|
||||
break;
|
||||
}
|
||||
|
||||
status = -ERESTARTSYS;
|
||||
freezer_do_not_count();
|
||||
wait_woken(&wait, TASK_INTERRUPTIBLE, NFS4_LOCK_MAXTIMEOUT);
|
||||
freezer_count();
|
||||
finish_wait(q, &wait);
|
||||
}
|
||||
|
||||
finish_wait(q, &wait);
|
||||
return status;
|
||||
}
|
||||
#else /* !CONFIG_NFS_V4_1 */
|
||||
|
|
Loading…
Reference in New Issue