diff options
-rw-r--r-- | include/linux/sunrpc/sched.h | 3 | ||||
-rw-r--r-- | net/sunrpc/clnt.c | 32 | ||||
-rw-r--r-- | net/sunrpc/pmap_clnt.c | 8 | ||||
-rw-r--r-- | net/sunrpc/sched.c | 31 |
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); | |||
233 | void rpc_init_task(struct rpc_task *, struct rpc_clnt *, | 233 | void rpc_init_task(struct rpc_task *, struct rpc_clnt *, |
234 | rpc_action exitfunc, int flags); | 234 | rpc_action exitfunc, int flags); |
235 | void rpc_release_task(struct rpc_task *); | 235 | void rpc_release_task(struct rpc_task *); |
236 | void rpc_exit_task(struct rpc_task *); | ||
236 | void rpc_killall_tasks(struct rpc_clnt *); | 237 | void rpc_killall_tasks(struct rpc_clnt *); |
237 | int rpc_execute(struct rpc_task *); | 238 | int rpc_execute(struct rpc_task *); |
238 | void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, | 239 | void rpc_run_child(struct rpc_task *parent, struct rpc_task *child, |
@@ -259,7 +260,7 @@ void rpc_destroy_mempool(void); | |||
259 | static inline void rpc_exit(struct rpc_task *task, int status) | 260 | static 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 | ||
517 | void | 517 | void |
@@ -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 | ||
1233 | out_retry: | 1234 | out_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; | 1240 | out_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__); |
1242 | out_eio: | 1244 | out_eio: |
1243 | error = -EIO; | 1245 | error = -EIO; |
1244 | out_err: | 1246 | out_err: |
1245 | rpc_exit(task, error); | 1247 | rpc_exit(task, error); |
1246 | return NULL; | 1248 | return ERR_PTR(error); |
1247 | out_overflow: | 1249 | out_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 | ||
1252 | static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) | 1254 | static 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 | */ |
561 | static inline int __rpc_do_exit(struct rpc_task *task) | 560 | void 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 | } |
573 | EXPORT_SYMBOL(rpc_exit_task); | ||
580 | 574 | ||
581 | static int rpc_wait_bit_interruptible(void *word) | 575 | static 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 | /* |