aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-06-16 09:52:25 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-06-22 13:24:01 -0400
commitaa5190d0ed7d042c6d7d89fe8101558a912eee73 (patch)
treed9fe1cc0bdd8c22f96dfa748d7ce0d6d90deda1a /fs/nfs
parentd185a334c748b3ca9de1f3a293fd8a9cf68378ab (diff)
NFSv4: Kill nfs4_async_handle_error() abuses by NFSv4.1
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/nfs4proc.c78
1 files changed, 41 insertions, 37 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fc653c3bc557..a00932c1215e 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -3457,9 +3457,11 @@ static int nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t buflen
3457} 3457}
3458 3458
3459static int 3459static int
3460_nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs_client *clp, struct nfs4_state *state) 3460nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
3461{ 3461{
3462 if (!clp || task->tk_status >= 0) 3462 struct nfs_client *clp = server->nfs_client;
3463
3464 if (task->tk_status >= 0)
3463 return 0; 3465 return 0;
3464 switch(task->tk_status) { 3466 switch(task->tk_status) {
3465 case -NFS4ERR_ADMIN_REVOKED: 3467 case -NFS4ERR_ADMIN_REVOKED:
@@ -3491,8 +3493,7 @@ _nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server,
3491 return -EAGAIN; 3493 return -EAGAIN;
3492#endif /* CONFIG_NFS_V4_1 */ 3494#endif /* CONFIG_NFS_V4_1 */
3493 case -NFS4ERR_DELAY: 3495 case -NFS4ERR_DELAY:
3494 if (server) 3496 nfs_inc_server_stats(server, NFSIOS_DELAY);
3495 nfs_inc_server_stats(server, NFSIOS_DELAY);
3496 case -NFS4ERR_GRACE: 3497 case -NFS4ERR_GRACE:
3497 case -EKEYEXPIRED: 3498 case -EKEYEXPIRED:
3498 rpc_delay(task, NFS4_POLL_RETRY_MAX); 3499 rpc_delay(task, NFS4_POLL_RETRY_MAX);
@@ -3513,12 +3514,6 @@ do_state_recovery:
3513 return -EAGAIN; 3514 return -EAGAIN;
3514} 3515}
3515 3516
3516static int
3517nfs4_async_handle_error(struct rpc_task *task, const struct nfs_server *server, struct nfs4_state *state)
3518{
3519 return _nfs4_async_handle_error(task, server, server->nfs_client, state);
3520}
3521
3522int nfs4_proc_setclientid(struct nfs_client *clp, u32 program, 3517int nfs4_proc_setclientid(struct nfs_client *clp, u32 program,
3523 unsigned short port, struct rpc_cred *cred, 3518 unsigned short port, struct rpc_cred *cred,
3524 struct nfs4_setclientid_res *res) 3519 struct nfs4_setclientid_res *res)
@@ -5088,6 +5083,19 @@ static void nfs41_sequence_release(void *data)
5088 kfree(calldata); 5083 kfree(calldata);
5089} 5084}
5090 5085
5086static int nfs41_sequence_handle_errors(struct rpc_task *task, struct nfs_client *clp)
5087{
5088 switch(task->tk_status) {
5089 case -NFS4ERR_DELAY:
5090 case -EKEYEXPIRED:
5091 rpc_delay(task, NFS4_POLL_RETRY_MAX);
5092 return -EAGAIN;
5093 default:
5094 nfs4_schedule_state_recovery(clp);
5095 }
5096 return 0;
5097}
5098
5091static void nfs41_sequence_call_done(struct rpc_task *task, void *data) 5099static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5092{ 5100{
5093 struct nfs4_sequence_data *calldata = data; 5101 struct nfs4_sequence_data *calldata = data;
@@ -5100,9 +5108,8 @@ static void nfs41_sequence_call_done(struct rpc_task *task, void *data)
5100 if (atomic_read(&clp->cl_count) == 1) 5108 if (atomic_read(&clp->cl_count) == 1)
5101 goto out; 5109 goto out;
5102 5110
5103 if (_nfs4_async_handle_error(task, NULL, clp, NULL) 5111 if (nfs41_sequence_handle_errors(task, clp) == -EAGAIN) {
5104 == -EAGAIN) { 5112 rpc_restart_call_prepare(task);
5105 nfs_restart_rpc(task, clp);
5106 return; 5113 return;
5107 } 5114 }
5108 } 5115 }
@@ -5175,6 +5182,23 @@ static void nfs4_reclaim_complete_prepare(struct rpc_task *task, void *data)
5175 rpc_call_start(task); 5182 rpc_call_start(task);
5176} 5183}
5177 5184
5185static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nfs_client *clp)
5186{
5187 switch(task->tk_status) {
5188 case 0:
5189 case -NFS4ERR_COMPLETE_ALREADY:
5190 case -NFS4ERR_WRONG_CRED: /* What to do here? */
5191 break;
5192 case -NFS4ERR_DELAY:
5193 case -EKEYEXPIRED:
5194 rpc_delay(task, NFS4_POLL_RETRY_MAX);
5195 return -EAGAIN;
5196 default:
5197 nfs4_schedule_state_recovery(clp);
5198 }
5199 return 0;
5200}
5201
5178static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data) 5202static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
5179{ 5203{
5180 struct nfs4_reclaim_complete_data *calldata = data; 5204 struct nfs4_reclaim_complete_data *calldata = data;
@@ -5183,31 +5207,11 @@ static void nfs4_reclaim_complete_done(struct rpc_task *task, void *data)
5183 5207
5184 dprintk("--> %s\n", __func__); 5208 dprintk("--> %s\n", __func__);
5185 nfs41_sequence_done(res); 5209 nfs41_sequence_done(res);
5186 switch (task->tk_status) {
5187 case 0:
5188 case -NFS4ERR_COMPLETE_ALREADY:
5189 break;
5190 case -NFS4ERR_BADSESSION:
5191 case -NFS4ERR_DEADSESSION:
5192 /*
5193 * Handle the session error, but do not retry the operation, as
5194 * we have no way of telling whether the clientid had to be
5195 * reset before we got our reply. If reset, a new wave of
5196 * reclaim operations will follow, containing their own reclaim
5197 * complete. We don't want our retry to get on the way of
5198 * recovery by incorrectly indicating to the server that we're
5199 * done reclaiming state since the process had to be restarted.
5200 */
5201 _nfs4_async_handle_error(task, NULL, clp, NULL);
5202 break;
5203 default:
5204 if (_nfs4_async_handle_error(
5205 task, NULL, clp, NULL) == -EAGAIN) {
5206 rpc_restart_call_prepare(task);
5207 return;
5208 }
5209 }
5210 5210
5211 if (nfs41_reclaim_complete_handle_errors(task, clp) == -EAGAIN) {
5212 rpc_restart_call_prepare(task);
5213 return;
5214 }
5211 dprintk("<-- %s\n", __func__); 5215 dprintk("<-- %s\n", __func__);
5212} 5216}
5213 5217