Commit 6ea76bf5 authored by Trond Myklebust's avatar Trond Myklebust

NFSv4: Fix _nfs4_do_setlk()

The patch to fix the case where a lock request was interrupted ended up
changing default handling of errors such as NFS4ERR_DENIED and caused the
client to immediately resend the lock request. Let's do a partial revert
of that request so that the default is now to exit, but change the way
we handle resends to take into account the fact that the user may have
interrupted the request.
Reported-by: default avatarKenneth Johansson <ken@kenjo.org>
Fixes: a3cf9bca ("NFSv4: Don't add a new lock on an interrupted wait..")
Cc: Benjamin Coddington <bcodding@redhat.com>
Cc: Jeff Layton <jlayton@kernel.org>
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: default avatarJeff Layton <jlayton@kernel.org>
parent 9a97ebf7
...@@ -6466,34 +6466,34 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata) ...@@ -6466,34 +6466,34 @@ static void nfs4_lock_done(struct rpc_task *task, void *calldata)
if (data->arg.new_lock && !data->cancelled) { if (data->arg.new_lock && !data->cancelled) {
data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS); data->fl.fl_flags &= ~(FL_SLEEP | FL_ACCESS);
if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0) if (locks_lock_inode_wait(lsp->ls_state->inode, &data->fl) < 0)
break; goto out_restart;
} }
if (data->arg.new_lock_owner != 0) { if (data->arg.new_lock_owner != 0) {
nfs_confirm_seqid(&lsp->ls_seqid, 0); nfs_confirm_seqid(&lsp->ls_seqid, 0);
nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid); nfs4_stateid_copy(&lsp->ls_stateid, &data->res.stateid);
set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags); set_bit(NFS_LOCK_INITIALIZED, &lsp->ls_flags);
goto out_done; } else if (!nfs4_update_lock_stateid(lsp, &data->res.stateid))
} else if (nfs4_update_lock_stateid(lsp, &data->res.stateid)) goto out_restart;
goto out_done;
break; break;
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_OLD_STATEID: case -NFS4ERR_OLD_STATEID:
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED: case -NFS4ERR_EXPIRED:
if (data->arg.new_lock_owner != 0) { if (data->arg.new_lock_owner != 0) {
if (nfs4_stateid_match(&data->arg.open_stateid, if (!nfs4_stateid_match(&data->arg.open_stateid,
&lsp->ls_state->open_stateid)) &lsp->ls_state->open_stateid))
goto out_done; goto out_restart;
} else if (nfs4_stateid_match(&data->arg.lock_stateid, } else if (!nfs4_stateid_match(&data->arg.lock_stateid,
&lsp->ls_stateid)) &lsp->ls_stateid))
goto out_done; goto out_restart;
} }
if (!data->cancelled)
rpc_restart_call_prepare(task);
out_done: out_done:
dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status); dprintk("%s: done, ret = %d!\n", __func__, data->rpc_status);
return;
out_restart:
if (!data->cancelled)
rpc_restart_call_prepare(task);
goto out_done;
} }
static void nfs4_lock_release(void *calldata) static void nfs4_lock_release(void *calldata)
...@@ -6502,7 +6502,7 @@ static void nfs4_lock_release(void *calldata) ...@@ -6502,7 +6502,7 @@ static void nfs4_lock_release(void *calldata)
dprintk("%s: begin!\n", __func__); dprintk("%s: begin!\n", __func__);
nfs_free_seqid(data->arg.open_seqid); nfs_free_seqid(data->arg.open_seqid);
if (data->cancelled) { if (data->cancelled && data->rpc_status == 0) {
struct rpc_task *task; struct rpc_task *task;
task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp, task = nfs4_do_unlck(&data->fl, data->ctx, data->lsp,
data->arg.lock_seqid); data->arg.lock_seqid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment