diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-09-22 13:39:05 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-09-27 14:34:27 -0400 |
commit | 26d36301bd653df6481fd38f3e1435a1f15e56d1 (patch) | |
tree | 7997e2199b3d616b531d5386df507d3fe302450c /fs/nfs | |
parent | f0b0bf8826145f2da8b13f375177e907ae44b796 (diff) |
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: Trond Myklebust <trond.myklebust@primarydata.com>
Tested-by: Oleg Drokin <green@linuxhacker.ru>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r-- | fs/nfs/nfs4proc.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1741e6454684..ee1fd4c5e646 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
@@ -328,6 +328,33 @@ static void nfs4_setup_readdir(u64 cookie, __be32 *verifier, struct dentry *dent | |||
328 | kunmap_atomic(start); | 328 | kunmap_atomic(start); |
329 | } | 329 | } |
330 | 330 | ||
331 | static void nfs4_test_and_free_stateid(struct nfs_server *server, | ||
332 | nfs4_stateid *stateid, | ||
333 | struct rpc_cred *cred) | ||
334 | { | ||
335 | const struct nfs4_minor_version_ops *ops = server->nfs_client->cl_mvops; | ||
336 | |||
337 | ops->test_and_free_expired(server, stateid, cred); | ||
338 | } | ||
339 | |||
340 | static void __nfs4_free_revoked_stateid(struct nfs_server *server, | ||
341 | nfs4_stateid *stateid, | ||
342 | struct rpc_cred *cred) | ||
343 | { | ||
344 | stateid->type = NFS4_REVOKED_STATEID_TYPE; | ||
345 | nfs4_test_and_free_stateid(server, stateid, cred); | ||
346 | } | ||
347 | |||
348 | static void nfs4_free_revoked_stateid(struct nfs_server *server, | ||
349 | const nfs4_stateid *stateid, | ||
350 | struct rpc_cred *cred) | ||
351 | { | ||
352 | nfs4_stateid tmp; | ||
353 | |||
354 | nfs4_stateid_copy(&tmp, stateid); | ||
355 | __nfs4_free_revoked_stateid(server, &tmp, cred); | ||
356 | } | ||
357 | |||
331 | static long nfs4_update_delay(long *timeout) | 358 | static long nfs4_update_delay(long *timeout) |
332 | { | 359 | { |
333 | long ret; | 360 | long ret; |
@@ -2985,9 +3012,12 @@ static void nfs4_close_done(struct rpc_task *task, void *data) | |||
2985 | break; | 3012 | break; |
2986 | case -NFS4ERR_ADMIN_REVOKED: | 3013 | case -NFS4ERR_ADMIN_REVOKED: |
2987 | case -NFS4ERR_STALE_STATEID: | 3014 | case -NFS4ERR_STALE_STATEID: |
3015 | case -NFS4ERR_EXPIRED: | ||
3016 | nfs4_free_revoked_stateid(server, | ||
3017 | &calldata->arg.stateid, | ||
3018 | task->tk_msg.rpc_cred); | ||
2988 | case -NFS4ERR_OLD_STATEID: | 3019 | case -NFS4ERR_OLD_STATEID: |
2989 | case -NFS4ERR_BAD_STATEID: | 3020 | case -NFS4ERR_BAD_STATEID: |
2990 | case -NFS4ERR_EXPIRED: | ||
2991 | if (!nfs4_stateid_match(&calldata->arg.stateid, | 3021 | if (!nfs4_stateid_match(&calldata->arg.stateid, |
2992 | &state->open_stateid)) { | 3022 | &state->open_stateid)) { |
2993 | rpc_restart_call_prepare(task); | 3023 | rpc_restart_call_prepare(task); |
@@ -5479,10 +5509,13 @@ static void nfs4_delegreturn_done(struct rpc_task *task, void *calldata) | |||
5479 | renew_lease(data->res.server, data->timestamp); | 5509 | renew_lease(data->res.server, data->timestamp); |
5480 | case -NFS4ERR_ADMIN_REVOKED: | 5510 | case -NFS4ERR_ADMIN_REVOKED: |
5481 | case -NFS4ERR_DELEG_REVOKED: | 5511 | case -NFS4ERR_DELEG_REVOKED: |
5512 | case -NFS4ERR_EXPIRED: | ||
5513 | nfs4_free_revoked_stateid(data->res.server, | ||
5514 | data->args.stateid, | ||
5515 | task->tk_msg.rpc_cred); | ||
5482 | case -NFS4ERR_BAD_STATEID: | 5516 | case -NFS4ERR_BAD_STATEID: |
5483 | case -NFS4ERR_OLD_STATEID: | 5517 | case -NFS4ERR_OLD_STATEID: |
5484 | case -NFS4ERR_STALE_STATEID: | 5518 | case -NFS4ERR_STALE_STATEID: |
5485 | case -NFS4ERR_EXPIRED: | ||
5486 | task->tk_status = 0; | 5519 | task->tk_status = 0; |
5487 | if (data->roc) | 5520 | if (data->roc) |
5488 | pnfs_roc_set_barrier(data->inode, data->roc_barrier); | 5521 | 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 | if (nfs4_update_lock_stateid(calldata->lsp, | 5759 | if (nfs4_update_lock_stateid(calldata->lsp, |
5727 | &calldata->res.stateid)) | 5760 | &calldata->res.stateid)) |
5728 | break; | 5761 | break; |
5762 | case -NFS4ERR_ADMIN_REVOKED: | ||
5763 | case -NFS4ERR_EXPIRED: | ||
5764 | nfs4_free_revoked_stateid(calldata->server, | ||
5765 | &calldata->arg.stateid, | ||
5766 | task->tk_msg.rpc_cred); | ||
5729 | case -NFS4ERR_BAD_STATEID: | 5767 | case -NFS4ERR_BAD_STATEID: |
5730 | case -NFS4ERR_OLD_STATEID: | 5768 | case -NFS4ERR_OLD_STATEID: |
5731 | case -NFS4ERR_STALE_STATEID: | 5769 | case -NFS4ERR_STALE_STATEID: |
5732 | case -NFS4ERR_EXPIRED: | ||
5733 | if (!nfs4_stateid_match(&calldata->arg.stateid, | 5770 | if (!nfs4_stateid_match(&calldata->arg.stateid, |
5734 | &calldata->lsp->ls_stateid)) | 5771 | &calldata->lsp->ls_stateid)) |
5735 | rpc_restart_call_prepare(task); | 5772 | rpc_restart_call_prepare(task); |