Commit 26d36301 authored by Trond Myklebust's avatar Trond Myklebust Committed by Anna Schumaker

NFSv4.1: Ensure we call FREE_STATEID if needed on close/delegreturn/locku

If a server returns NFS4ERR_ADMIN_REVOKED, NFS4ERR_DELEG_REVOKED
or NFS4ERR_EXPIRED on a call to close, open_downgrade, delegreturn, or
locku, we should call FREE_STATEID before attempting to recover.
Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
Tested-by: default avatarOleg Drokin <green@linuxhacker.ru>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent f0b0bf88
...@@ -328,6 +328,33 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent ...@@ -328,6 +328,33 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent
kunmap_atomic(start); kunmap_atomic(start);
} }
static void nfs4_test_and_free_stateid(struct nfs_server *server,
nfs4_stateid *stateid,
struct rpc_cred *cred)
{
const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops;
ops->test_and_free_expired(server, stateid, cred);
}
static void __nfs4_free_revoked_stateid(struct nfs_server *server,
nfs4_stateid *stateid,
struct rpc_cred *cred)
{
stateid->type = NFS4_REVOKED_STATEID_TYPE;
nfs4_test_and_free_stateid(server, stateid, cred);
}
static void nfs4_free_revoked_stateid(struct nfs_server *server,
const nfs4_stateid *stateid,
struct rpc_cred *cred)
{
nfs4_stateid tmp;
nfs4_stateid_copy(&tmp, stateid);
__nfs4_free_revoked_stateid(server, &tmp, cred);
}
static long nfs4_update_delay(long *timeout) static long nfs4_update_delay(long *timeout)
{ {
long ret; long ret;
...@@ -2985,9 +3012,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data) ...@@ -2985,9 +3012,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data)
break; break;
case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_STALE_STATEID: case -NFS4ERR_STALE_STATEID:
case -NFS4ERR_EXPIRED:
nfs4_free_revoked_stateid(server,
&calldata->arg.stateid,
task->tk_msg.rpc_cred);
case -NFS4ERR_OLD_STATEID: case -NFS4ERR_OLD_STATEID:
case -NFS4ERR_BAD_STATEID: case -NFS4ERR_BAD_STATEID:
case -NFS4ERR_EXPIRED:
if (!nfs4_stateid_match(&calldata->arg.stateid, if (!nfs4_stateid_match(&calldata->arg.stateid,
&state->open_stateid)) { &state->open_stateid)) {
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
...@@ -5479,10 +5509,13 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) ...@@ -5479,10 +5509,13 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata)
renew_lease(data->res.server, data->timestamp); renew_lease(data->res.server, data->timestamp);
case -NFS4ERR_ADMIN_REVOKED: case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_DELEG_REVOKED: case -NFS4ERR_DELEG_REVOKED:
case -NFS4ERR_EXPIRED:
nfs4_free_revoked_stateid(data->res.server,
data->args.stateid,
task->tk_msg.rpc_cred);
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:
task->tk_status = 0; task->tk_status = 0;
if (data->roc) if (data->roc)
pnfs_roc_set_barrier(data->inode, data->roc_barrier); pnfs_roc_set_barrier(data->inode, data->roc_barrier);
...@@ -5726,10 +5759,14 @@ static void nfs4_locku_done(struct rpc_task *task, void *data) ...@@ -5726,10 +5759,14 @@ static void nfs4_locku_done(struct rpc_task *task, void *data)
if (nfs4_update_lock_stateid(calldata->lsp, if (nfs4_update_lock_stateid(calldata->lsp,
&calldata->res.stateid)) &calldata->res.stateid))
break; break;
case -NFS4ERR_ADMIN_REVOKED:
case -NFS4ERR_EXPIRED:
nfs4_free_revoked_stateid(calldata->server,
&calldata->arg.stateid,
task->tk_msg.rpc_cred);
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:
if (!nfs4_stateid_match(&calldata->arg.stateid, if (!nfs4_stateid_match(&calldata->arg.stateid,
&calldata->lsp->ls_stateid)) &calldata->lsp->ls_stateid))
rpc_restart_call_prepare(task); rpc_restart_call_prepare(task);
......
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