aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/sched.h3
-rw-r--r--net/sunrpc/clnt.c32
-rw-r--r--net/sunrpc/pmap_clnt.c8
-rw-r--r--net/sunrpc/sched.c31
4 files changed, 34 insertions, 40 deletions
diff --git a/include/linux/sunrpc/sched.h b/include/linux/sunrpc/sched.h
index 4d77e90d0b30..4c4b2dc8aca5 100644
--- a/include/linux/sunrpc/sched.h
+++ b/include/linux/sunrpc/sched.h
@@ -233,6 +233,7 @@ struct rpc_task *rpc_new_child(struct rpc_clnt *, struct rpc_task *parent);
233void rpc_init_task(struct rpc_task *, struct rpc_clnt *, 233void rpc_init_task(struct rpc_task *, struct rpc_clnt *,
234 rpc_action exitfunc, int flags); 234 rpc_action exitfunc, int flags);
235void rpc_release_task(struct rpc_task *); 235void rpc_release_task(struct rpc_task *);
236void rpc_exit_task(struct rpc_task *);
236void rpc_killall_tasks(struct rpc_clnt *); 237void rpc_killall_tasks(struct rpc_clnt *);
237int rpc_execute(struct rpc_task *); 238int rpc_execute(struct rpc_task *);
238void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, 239void rpc_run_child(struct rpc_task *parent, struct rpc_task *child,
@@ -259,7 +260,7 @@ void rpc_destroy_mempool(void);
259static inline void rpc_exit(struct rpc_task *task, int status) 260static inline void rpc_exit(struct rpc_task *task, int status)
260{ 261{
261 task->tk_status = status; 262 task->tk_status = status;
262 task->tk_action = NULL; 263 task->tk_action = rpc_exit_task;
263} 264}
264 265
265#ifdef RPC_DEBUG 266#ifdef RPC_DEBUG
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 61c3abeaccae..6ab4cbd8a901 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -511,7 +511,7 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags)
511 if (task->tk_status == 0) 511 if (task->tk_status == 0)
512 task->tk_action = call_start; 512 task->tk_action = call_start;
513 else 513 else
514 task->tk_action = NULL; 514 task->tk_action = rpc_exit_task;
515} 515}
516 516
517void 517void
@@ -892,7 +892,7 @@ call_transmit(struct rpc_task *task)
892 if (task->tk_status < 0) 892 if (task->tk_status < 0)
893 return; 893 return;
894 if (!task->tk_msg.rpc_proc->p_decode) { 894 if (!task->tk_msg.rpc_proc->p_decode) {
895 task->tk_action = NULL; 895 task->tk_action = rpc_exit_task;
896 rpc_wake_up_task(task); 896 rpc_wake_up_task(task);
897 } 897 }
898 return; 898 return;
@@ -1039,13 +1039,14 @@ call_decode(struct rpc_task *task)
1039 sizeof(req->rq_rcv_buf)) != 0); 1039 sizeof(req->rq_rcv_buf)) != 0);
1040 1040
1041 /* Verify the RPC header */ 1041 /* Verify the RPC header */
1042 if (!(p = call_verify(task))) { 1042 p = call_verify(task);
1043 if (task->tk_action == NULL) 1043 if (IS_ERR(p)) {
1044 return; 1044 if (p == ERR_PTR(-EAGAIN))
1045 goto out_retry; 1045 goto out_retry;
1046 return;
1046 } 1047 }
1047 1048
1048 task->tk_action = NULL; 1049 task->tk_action = rpc_exit_task;
1049 1050
1050 if (decode) 1051 if (decode)
1051 task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, 1052 task->tk_status = rpcauth_unwrap_resp(task, decode, req, p,
@@ -1138,7 +1139,7 @@ call_verify(struct rpc_task *task)
1138 1139
1139 if ((n = ntohl(*p++)) != RPC_REPLY) { 1140 if ((n = ntohl(*p++)) != RPC_REPLY) {
1140 printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); 1141 printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n);
1141 goto out_retry; 1142 goto out_garbage;
1142 } 1143 }
1143 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { 1144 if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) {
1144 if (--len < 0) 1145 if (--len < 0)
@@ -1168,7 +1169,7 @@ call_verify(struct rpc_task *task)
1168 task->tk_pid); 1169 task->tk_pid);
1169 rpcauth_invalcred(task); 1170 rpcauth_invalcred(task);
1170 task->tk_action = call_refresh; 1171 task->tk_action = call_refresh;
1171 return NULL; 1172 goto out_retry;
1172 case RPC_AUTH_BADCRED: 1173 case RPC_AUTH_BADCRED:
1173 case RPC_AUTH_BADVERF: 1174 case RPC_AUTH_BADVERF:
1174 /* possibly garbled cred/verf? */ 1175 /* possibly garbled cred/verf? */
@@ -1178,7 +1179,7 @@ call_verify(struct rpc_task *task)
1178 dprintk("RPC: %4d call_verify: retry garbled creds\n", 1179 dprintk("RPC: %4d call_verify: retry garbled creds\n",
1179 task->tk_pid); 1180 task->tk_pid);
1180 task->tk_action = call_bind; 1181 task->tk_action = call_bind;
1181 return NULL; 1182 goto out_retry;
1182 case RPC_AUTH_TOOWEAK: 1183 case RPC_AUTH_TOOWEAK:
1183 printk(KERN_NOTICE "call_verify: server requires stronger " 1184 printk(KERN_NOTICE "call_verify: server requires stronger "
1184 "authentication.\n"); 1185 "authentication.\n");
@@ -1193,7 +1194,7 @@ call_verify(struct rpc_task *task)
1193 } 1194 }
1194 if (!(p = rpcauth_checkverf(task, p))) { 1195 if (!(p = rpcauth_checkverf(task, p))) {
1195 printk(KERN_WARNING "call_verify: auth check failed\n"); 1196 printk(KERN_WARNING "call_verify: auth check failed\n");
1196 goto out_retry; /* bad verifier, retry */ 1197 goto out_garbage; /* bad verifier, retry */
1197 } 1198 }
1198 len = p - (u32 *)iov->iov_base - 1; 1199 len = p - (u32 *)iov->iov_base - 1;
1199 if (len < 0) 1200 if (len < 0)
@@ -1230,23 +1231,24 @@ call_verify(struct rpc_task *task)
1230 /* Also retry */ 1231 /* Also retry */
1231 } 1232 }
1232 1233
1233out_retry: 1234out_garbage:
1234 task->tk_client->cl_stats->rpcgarbage++; 1235 task->tk_client->cl_stats->rpcgarbage++;
1235 if (task->tk_garb_retry) { 1236 if (task->tk_garb_retry) {
1236 task->tk_garb_retry--; 1237 task->tk_garb_retry--;
1237 dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); 1238 dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid);
1238 task->tk_action = call_bind; 1239 task->tk_action = call_bind;
1239 return NULL; 1240out_retry:
1241 return ERR_PTR(-EAGAIN);
1240 } 1242 }
1241 printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); 1243 printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__);
1242out_eio: 1244out_eio:
1243 error = -EIO; 1245 error = -EIO;
1244out_err: 1246out_err:
1245 rpc_exit(task, error); 1247 rpc_exit(task, error);
1246 return NULL; 1248 return ERR_PTR(error);
1247out_overflow: 1249out_overflow:
1248 printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); 1250 printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__);
1249 goto out_retry; 1251 goto out_garbage;
1250} 1252}
1251 1253
1252static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) 1254static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj)
diff --git a/net/sunrpc/pmap_clnt.c b/net/sunrpc/pmap_clnt.c
index a398575f94b8..cad4568fbbe2 100644
--- a/net/sunrpc/pmap_clnt.c
+++ b/net/sunrpc/pmap_clnt.c
@@ -90,8 +90,7 @@ bailout:
90 map->pm_binding = 0; 90 map->pm_binding = 0;
91 rpc_wake_up(&map->pm_bindwait); 91 rpc_wake_up(&map->pm_bindwait);
92 spin_unlock(&pmap_lock); 92 spin_unlock(&pmap_lock);
93 task->tk_status = -EIO; 93 rpc_exit(task, -EIO);
94 task->tk_action = NULL;
95} 94}
96 95
97#ifdef CONFIG_ROOT_NFS 96#ifdef CONFIG_ROOT_NFS
@@ -138,11 +137,10 @@ pmap_getport_done(struct rpc_task *task)
138 task->tk_pid, task->tk_status, clnt->cl_port); 137 task->tk_pid, task->tk_status, clnt->cl_port);
139 if (task->tk_status < 0) { 138 if (task->tk_status < 0) {
140 /* Make the calling task exit with an error */ 139 /* Make the calling task exit with an error */
141 task->tk_action = NULL; 140 task->tk_action = rpc_exit_task;
142 } else if (clnt->cl_port == 0) { 141 } else if (clnt->cl_port == 0) {
143 /* Program not registered */ 142 /* Program not registered */
144 task->tk_status = -EACCES; 143 rpc_exit(task, -EACCES);
145 task->tk_action = NULL;
146 } else { 144 } else {
147 /* byte-swap port number first */ 145 /* byte-swap port number first */
148 clnt->cl_port = htons(clnt->cl_port); 146 clnt->cl_port = htons(clnt->cl_port);
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index 54e60a657500..3fcf7b0e1f6c 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -555,28 +555,22 @@ __rpc_atrun(struct rpc_task *task)
555} 555}
556 556
557/* 557/*
558 * Helper that calls task->tk_exit if it exists and then returns 558 * Helper that calls task->tk_exit if it exists
559 * true if we should exit __rpc_execute.
560 */ 559 */
561static inline int __rpc_do_exit(struct rpc_task *task) 560void rpc_exit_task(struct rpc_task *task)
562{ 561{
562 task->tk_action = NULL;
563 if (task->tk_exit != NULL) { 563 if (task->tk_exit != NULL) {
564 lock_kernel();
565 task->tk_exit(task); 564 task->tk_exit(task);
566 unlock_kernel();
567 /* If tk_action is non-null, we should restart the call */
568 if (task->tk_action != NULL) { 565 if (task->tk_action != NULL) {
569 if (!RPC_ASSASSINATED(task)) { 566 WARN_ON(RPC_ASSASSINATED(task));
570 /* Release RPC slot and buffer memory */ 567 /* Always release the RPC slot and buffer memory */
571 xprt_release(task); 568 xprt_release(task);
572 rpc_free(task); 569 rpc_free(task);
573 return 0;
574 }
575 printk(KERN_ERR "RPC: dead task tried to walk away.\n");
576 } 570 }
577 } 571 }
578 return 1;
579} 572}
573EXPORT_SYMBOL(rpc_exit_task);
580 574
581static int rpc_wait_bit_interruptible(void *word) 575static int rpc_wait_bit_interruptible(void *word)
582{ 576{
@@ -631,12 +625,11 @@ static int __rpc_execute(struct rpc_task *task)
631 * by someone else. 625 * by someone else.
632 */ 626 */
633 if (!RPC_IS_QUEUED(task)) { 627 if (!RPC_IS_QUEUED(task)) {
634 if (task->tk_action != NULL) { 628 if (task->tk_action == NULL)
635 lock_kernel();
636 task->tk_action(task);
637 unlock_kernel();
638 } else if (__rpc_do_exit(task))
639 break; 629 break;
630 lock_kernel();
631 task->tk_action(task);
632 unlock_kernel();
640 } 633 }
641 634
642 /* 635 /*