diff options
Diffstat (limited to 'net/sunrpc/clnt.c')
-rw-r--r-- | net/sunrpc/clnt.c | 107 |
1 files changed, 60 insertions, 47 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 61c3abeaccae..5530ac8c6df9 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -374,19 +374,23 @@ out: | |||
374 | * Default callback for async RPC calls | 374 | * Default callback for async RPC calls |
375 | */ | 375 | */ |
376 | static void | 376 | static void |
377 | rpc_default_callback(struct rpc_task *task) | 377 | rpc_default_callback(struct rpc_task *task, void *data) |
378 | { | 378 | { |
379 | } | 379 | } |
380 | 380 | ||
381 | static const struct rpc_call_ops rpc_default_ops = { | ||
382 | .rpc_call_done = rpc_default_callback, | ||
383 | }; | ||
384 | |||
381 | /* | 385 | /* |
382 | * Export the signal mask handling for synchronous code that | 386 | * Export the signal mask handling for synchronous code that |
383 | * sleeps on RPC calls | 387 | * sleeps on RPC calls |
384 | */ | 388 | */ |
385 | #define RPC_INTR_SIGNALS (sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGKILL)) | 389 | #define RPC_INTR_SIGNALS (sigmask(SIGHUP) | sigmask(SIGINT) | sigmask(SIGQUIT) | sigmask(SIGTERM)) |
386 | 390 | ||
387 | static void rpc_save_sigmask(sigset_t *oldset, int intr) | 391 | static void rpc_save_sigmask(sigset_t *oldset, int intr) |
388 | { | 392 | { |
389 | unsigned long sigallow = 0; | 393 | unsigned long sigallow = sigmask(SIGKILL); |
390 | sigset_t sigmask; | 394 | sigset_t sigmask; |
391 | 395 | ||
392 | /* Block all signals except those listed in sigallow */ | 396 | /* Block all signals except those listed in sigallow */ |
@@ -432,7 +436,7 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
432 | BUG_ON(flags & RPC_TASK_ASYNC); | 436 | BUG_ON(flags & RPC_TASK_ASYNC); |
433 | 437 | ||
434 | status = -ENOMEM; | 438 | status = -ENOMEM; |
435 | task = rpc_new_task(clnt, NULL, flags); | 439 | task = rpc_new_task(clnt, flags, &rpc_default_ops, NULL); |
436 | if (task == NULL) | 440 | if (task == NULL) |
437 | goto out; | 441 | goto out; |
438 | 442 | ||
@@ -442,14 +446,15 @@ int rpc_call_sync(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) | |||
442 | rpc_call_setup(task, msg, 0); | 446 | rpc_call_setup(task, msg, 0); |
443 | 447 | ||
444 | /* Set up the call info struct and execute the task */ | 448 | /* Set up the call info struct and execute the task */ |
445 | if (task->tk_status == 0) { | 449 | status = task->tk_status; |
450 | if (status == 0) { | ||
451 | atomic_inc(&task->tk_count); | ||
446 | status = rpc_execute(task); | 452 | status = rpc_execute(task); |
447 | } else { | 453 | if (status == 0) |
448 | status = task->tk_status; | 454 | status = task->tk_status; |
449 | rpc_release_task(task); | ||
450 | } | 455 | } |
451 | |||
452 | rpc_restore_sigmask(&oldset); | 456 | rpc_restore_sigmask(&oldset); |
457 | rpc_release_task(task); | ||
453 | out: | 458 | out: |
454 | return status; | 459 | return status; |
455 | } | 460 | } |
@@ -459,7 +464,7 @@ out: | |||
459 | */ | 464 | */ |
460 | int | 465 | int |
461 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | 466 | rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, |
462 | rpc_action callback, void *data) | 467 | const struct rpc_call_ops *tk_ops, void *data) |
463 | { | 468 | { |
464 | struct rpc_task *task; | 469 | struct rpc_task *task; |
465 | sigset_t oldset; | 470 | sigset_t oldset; |
@@ -472,12 +477,9 @@ rpc_call_async(struct rpc_clnt *clnt, struct rpc_message *msg, int flags, | |||
472 | flags |= RPC_TASK_ASYNC; | 477 | flags |= RPC_TASK_ASYNC; |
473 | 478 | ||
474 | /* Create/initialize a new RPC task */ | 479 | /* Create/initialize a new RPC task */ |
475 | if (!callback) | ||
476 | callback = rpc_default_callback; | ||
477 | status = -ENOMEM; | 480 | status = -ENOMEM; |
478 | if (!(task = rpc_new_task(clnt, callback, flags))) | 481 | if (!(task = rpc_new_task(clnt, flags, tk_ops, data))) |
479 | goto out; | 482 | goto out; |
480 | task->tk_calldata = data; | ||
481 | 483 | ||
482 | /* Mask signals on GSS_AUTH upcalls */ | 484 | /* Mask signals on GSS_AUTH upcalls */ |
483 | rpc_task_sigmask(task, &oldset); | 485 | rpc_task_sigmask(task, &oldset); |
@@ -511,7 +513,7 @@ rpc_call_setup(struct rpc_task *task, struct rpc_message *msg, int flags) | |||
511 | if (task->tk_status == 0) | 513 | if (task->tk_status == 0) |
512 | task->tk_action = call_start; | 514 | task->tk_action = call_start; |
513 | else | 515 | else |
514 | task->tk_action = NULL; | 516 | task->tk_action = rpc_exit_task; |
515 | } | 517 | } |
516 | 518 | ||
517 | void | 519 | void |
@@ -536,6 +538,18 @@ size_t rpc_max_payload(struct rpc_clnt *clnt) | |||
536 | } | 538 | } |
537 | EXPORT_SYMBOL(rpc_max_payload); | 539 | EXPORT_SYMBOL(rpc_max_payload); |
538 | 540 | ||
541 | /** | ||
542 | * rpc_force_rebind - force transport to check that remote port is unchanged | ||
543 | * @clnt: client to rebind | ||
544 | * | ||
545 | */ | ||
546 | void rpc_force_rebind(struct rpc_clnt *clnt) | ||
547 | { | ||
548 | if (clnt->cl_autobind) | ||
549 | clnt->cl_port = 0; | ||
550 | } | ||
551 | EXPORT_SYMBOL(rpc_force_rebind); | ||
552 | |||
539 | /* | 553 | /* |
540 | * Restart an (async) RPC call. Usually called from within the | 554 | * Restart an (async) RPC call. Usually called from within the |
541 | * exit handler. | 555 | * exit handler. |
@@ -642,24 +656,26 @@ call_reserveresult(struct rpc_task *task) | |||
642 | 656 | ||
643 | /* | 657 | /* |
644 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. | 658 | * 2. Allocate the buffer. For details, see sched.c:rpc_malloc. |
645 | * (Note: buffer memory is freed in rpc_task_release). | 659 | * (Note: buffer memory is freed in xprt_release). |
646 | */ | 660 | */ |
647 | static void | 661 | static void |
648 | call_allocate(struct rpc_task *task) | 662 | call_allocate(struct rpc_task *task) |
649 | { | 663 | { |
664 | struct rpc_rqst *req = task->tk_rqstp; | ||
665 | struct rpc_xprt *xprt = task->tk_xprt; | ||
650 | unsigned int bufsiz; | 666 | unsigned int bufsiz; |
651 | 667 | ||
652 | dprintk("RPC: %4d call_allocate (status %d)\n", | 668 | dprintk("RPC: %4d call_allocate (status %d)\n", |
653 | task->tk_pid, task->tk_status); | 669 | task->tk_pid, task->tk_status); |
654 | task->tk_action = call_bind; | 670 | task->tk_action = call_bind; |
655 | if (task->tk_buffer) | 671 | if (req->rq_buffer) |
656 | return; | 672 | return; |
657 | 673 | ||
658 | /* FIXME: compute buffer requirements more exactly using | 674 | /* FIXME: compute buffer requirements more exactly using |
659 | * auth->au_wslack */ | 675 | * auth->au_wslack */ |
660 | bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE; | 676 | bufsiz = task->tk_msg.rpc_proc->p_bufsiz + RPC_SLACK_SPACE; |
661 | 677 | ||
662 | if (rpc_malloc(task, bufsiz << 1) != NULL) | 678 | if (xprt->ops->buf_alloc(task, bufsiz << 1) != NULL) |
663 | return; | 679 | return; |
664 | printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); | 680 | printk(KERN_INFO "RPC: buffer allocation failed for task %p\n", task); |
665 | 681 | ||
@@ -702,14 +718,14 @@ call_encode(struct rpc_task *task) | |||
702 | task->tk_pid, task->tk_status); | 718 | task->tk_pid, task->tk_status); |
703 | 719 | ||
704 | /* Default buffer setup */ | 720 | /* Default buffer setup */ |
705 | bufsiz = task->tk_bufsize >> 1; | 721 | bufsiz = req->rq_bufsize >> 1; |
706 | sndbuf->head[0].iov_base = (void *)task->tk_buffer; | 722 | sndbuf->head[0].iov_base = (void *)req->rq_buffer; |
707 | sndbuf->head[0].iov_len = bufsiz; | 723 | sndbuf->head[0].iov_len = bufsiz; |
708 | sndbuf->tail[0].iov_len = 0; | 724 | sndbuf->tail[0].iov_len = 0; |
709 | sndbuf->page_len = 0; | 725 | sndbuf->page_len = 0; |
710 | sndbuf->len = 0; | 726 | sndbuf->len = 0; |
711 | sndbuf->buflen = bufsiz; | 727 | sndbuf->buflen = bufsiz; |
712 | rcvbuf->head[0].iov_base = (void *)((char *)task->tk_buffer + bufsiz); | 728 | rcvbuf->head[0].iov_base = (void *)((char *)req->rq_buffer + bufsiz); |
713 | rcvbuf->head[0].iov_len = bufsiz; | 729 | rcvbuf->head[0].iov_len = bufsiz; |
714 | rcvbuf->tail[0].iov_len = 0; | 730 | rcvbuf->tail[0].iov_len = 0; |
715 | rcvbuf->page_len = 0; | 731 | rcvbuf->page_len = 0; |
@@ -849,8 +865,7 @@ call_connect_status(struct rpc_task *task) | |||
849 | } | 865 | } |
850 | 866 | ||
851 | /* Something failed: remote service port may have changed */ | 867 | /* Something failed: remote service port may have changed */ |
852 | if (clnt->cl_autobind) | 868 | rpc_force_rebind(clnt); |
853 | clnt->cl_port = 0; | ||
854 | 869 | ||
855 | switch (status) { | 870 | switch (status) { |
856 | case -ENOTCONN: | 871 | case -ENOTCONN: |
@@ -892,7 +907,7 @@ call_transmit(struct rpc_task *task) | |||
892 | if (task->tk_status < 0) | 907 | if (task->tk_status < 0) |
893 | return; | 908 | return; |
894 | if (!task->tk_msg.rpc_proc->p_decode) { | 909 | if (!task->tk_msg.rpc_proc->p_decode) { |
895 | task->tk_action = NULL; | 910 | task->tk_action = rpc_exit_task; |
896 | rpc_wake_up_task(task); | 911 | rpc_wake_up_task(task); |
897 | } | 912 | } |
898 | return; | 913 | return; |
@@ -931,8 +946,7 @@ call_status(struct rpc_task *task) | |||
931 | break; | 946 | break; |
932 | case -ECONNREFUSED: | 947 | case -ECONNREFUSED: |
933 | case -ENOTCONN: | 948 | case -ENOTCONN: |
934 | if (clnt->cl_autobind) | 949 | rpc_force_rebind(clnt); |
935 | clnt->cl_port = 0; | ||
936 | task->tk_action = call_bind; | 950 | task->tk_action = call_bind; |
937 | break; | 951 | break; |
938 | case -EAGAIN: | 952 | case -EAGAIN: |
@@ -943,8 +957,7 @@ call_status(struct rpc_task *task) | |||
943 | rpc_exit(task, status); | 957 | rpc_exit(task, status); |
944 | break; | 958 | break; |
945 | default: | 959 | default: |
946 | if (clnt->cl_chatty) | 960 | printk("%s: RPC call returned error %d\n", |
947 | printk("%s: RPC call returned error %d\n", | ||
948 | clnt->cl_protname, -status); | 961 | clnt->cl_protname, -status); |
949 | rpc_exit(task, status); | 962 | rpc_exit(task, status); |
950 | break; | 963 | break; |
@@ -979,20 +992,18 @@ call_timeout(struct rpc_task *task) | |||
979 | 992 | ||
980 | dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid); | 993 | dprintk("RPC: %4d call_timeout (major)\n", task->tk_pid); |
981 | if (RPC_IS_SOFT(task)) { | 994 | if (RPC_IS_SOFT(task)) { |
982 | if (clnt->cl_chatty) | 995 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", |
983 | printk(KERN_NOTICE "%s: server %s not responding, timed out\n", | ||
984 | clnt->cl_protname, clnt->cl_server); | 996 | clnt->cl_protname, clnt->cl_server); |
985 | rpc_exit(task, -EIO); | 997 | rpc_exit(task, -EIO); |
986 | return; | 998 | return; |
987 | } | 999 | } |
988 | 1000 | ||
989 | if (clnt->cl_chatty && !(task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1001 | if (!(task->tk_flags & RPC_CALL_MAJORSEEN)) { |
990 | task->tk_flags |= RPC_CALL_MAJORSEEN; | 1002 | task->tk_flags |= RPC_CALL_MAJORSEEN; |
991 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", | 1003 | printk(KERN_NOTICE "%s: server %s not responding, still trying\n", |
992 | clnt->cl_protname, clnt->cl_server); | 1004 | clnt->cl_protname, clnt->cl_server); |
993 | } | 1005 | } |
994 | if (clnt->cl_autobind) | 1006 | rpc_force_rebind(clnt); |
995 | clnt->cl_port = 0; | ||
996 | 1007 | ||
997 | retry: | 1008 | retry: |
998 | clnt->cl_stats->rpcretrans++; | 1009 | clnt->cl_stats->rpcretrans++; |
@@ -1014,7 +1025,7 @@ call_decode(struct rpc_task *task) | |||
1014 | dprintk("RPC: %4d call_decode (status %d)\n", | 1025 | dprintk("RPC: %4d call_decode (status %d)\n", |
1015 | task->tk_pid, task->tk_status); | 1026 | task->tk_pid, task->tk_status); |
1016 | 1027 | ||
1017 | if (clnt->cl_chatty && (task->tk_flags & RPC_CALL_MAJORSEEN)) { | 1028 | if (task->tk_flags & RPC_CALL_MAJORSEEN) { |
1018 | printk(KERN_NOTICE "%s: server %s OK\n", | 1029 | printk(KERN_NOTICE "%s: server %s OK\n", |
1019 | clnt->cl_protname, clnt->cl_server); | 1030 | clnt->cl_protname, clnt->cl_server); |
1020 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; | 1031 | task->tk_flags &= ~RPC_CALL_MAJORSEEN; |
@@ -1039,13 +1050,14 @@ call_decode(struct rpc_task *task) | |||
1039 | sizeof(req->rq_rcv_buf)) != 0); | 1050 | sizeof(req->rq_rcv_buf)) != 0); |
1040 | 1051 | ||
1041 | /* Verify the RPC header */ | 1052 | /* Verify the RPC header */ |
1042 | if (!(p = call_verify(task))) { | 1053 | p = call_verify(task); |
1043 | if (task->tk_action == NULL) | 1054 | if (IS_ERR(p)) { |
1044 | return; | 1055 | if (p == ERR_PTR(-EAGAIN)) |
1045 | goto out_retry; | 1056 | goto out_retry; |
1057 | return; | ||
1046 | } | 1058 | } |
1047 | 1059 | ||
1048 | task->tk_action = NULL; | 1060 | task->tk_action = rpc_exit_task; |
1049 | 1061 | ||
1050 | if (decode) | 1062 | if (decode) |
1051 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, | 1063 | task->tk_status = rpcauth_unwrap_resp(task, decode, req, p, |
@@ -1138,7 +1150,7 @@ call_verify(struct rpc_task *task) | |||
1138 | 1150 | ||
1139 | if ((n = ntohl(*p++)) != RPC_REPLY) { | 1151 | if ((n = ntohl(*p++)) != RPC_REPLY) { |
1140 | printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); | 1152 | printk(KERN_WARNING "call_verify: not an RPC reply: %x\n", n); |
1141 | goto out_retry; | 1153 | goto out_garbage; |
1142 | } | 1154 | } |
1143 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { | 1155 | if ((n = ntohl(*p++)) != RPC_MSG_ACCEPTED) { |
1144 | if (--len < 0) | 1156 | if (--len < 0) |
@@ -1168,7 +1180,7 @@ call_verify(struct rpc_task *task) | |||
1168 | task->tk_pid); | 1180 | task->tk_pid); |
1169 | rpcauth_invalcred(task); | 1181 | rpcauth_invalcred(task); |
1170 | task->tk_action = call_refresh; | 1182 | task->tk_action = call_refresh; |
1171 | return NULL; | 1183 | goto out_retry; |
1172 | case RPC_AUTH_BADCRED: | 1184 | case RPC_AUTH_BADCRED: |
1173 | case RPC_AUTH_BADVERF: | 1185 | case RPC_AUTH_BADVERF: |
1174 | /* possibly garbled cred/verf? */ | 1186 | /* possibly garbled cred/verf? */ |
@@ -1178,7 +1190,7 @@ call_verify(struct rpc_task *task) | |||
1178 | dprintk("RPC: %4d call_verify: retry garbled creds\n", | 1190 | dprintk("RPC: %4d call_verify: retry garbled creds\n", |
1179 | task->tk_pid); | 1191 | task->tk_pid); |
1180 | task->tk_action = call_bind; | 1192 | task->tk_action = call_bind; |
1181 | return NULL; | 1193 | goto out_retry; |
1182 | case RPC_AUTH_TOOWEAK: | 1194 | case RPC_AUTH_TOOWEAK: |
1183 | printk(KERN_NOTICE "call_verify: server requires stronger " | 1195 | printk(KERN_NOTICE "call_verify: server requires stronger " |
1184 | "authentication.\n"); | 1196 | "authentication.\n"); |
@@ -1193,7 +1205,7 @@ call_verify(struct rpc_task *task) | |||
1193 | } | 1205 | } |
1194 | if (!(p = rpcauth_checkverf(task, p))) { | 1206 | if (!(p = rpcauth_checkverf(task, p))) { |
1195 | printk(KERN_WARNING "call_verify: auth check failed\n"); | 1207 | printk(KERN_WARNING "call_verify: auth check failed\n"); |
1196 | goto out_retry; /* bad verifier, retry */ | 1208 | goto out_garbage; /* bad verifier, retry */ |
1197 | } | 1209 | } |
1198 | len = p - (u32 *)iov->iov_base - 1; | 1210 | len = p - (u32 *)iov->iov_base - 1; |
1199 | if (len < 0) | 1211 | if (len < 0) |
@@ -1230,23 +1242,24 @@ call_verify(struct rpc_task *task) | |||
1230 | /* Also retry */ | 1242 | /* Also retry */ |
1231 | } | 1243 | } |
1232 | 1244 | ||
1233 | out_retry: | 1245 | out_garbage: |
1234 | task->tk_client->cl_stats->rpcgarbage++; | 1246 | task->tk_client->cl_stats->rpcgarbage++; |
1235 | if (task->tk_garb_retry) { | 1247 | if (task->tk_garb_retry) { |
1236 | task->tk_garb_retry--; | 1248 | task->tk_garb_retry--; |
1237 | dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); | 1249 | dprintk("RPC %s: retrying %4d\n", __FUNCTION__, task->tk_pid); |
1238 | task->tk_action = call_bind; | 1250 | task->tk_action = call_bind; |
1239 | return NULL; | 1251 | out_retry: |
1252 | return ERR_PTR(-EAGAIN); | ||
1240 | } | 1253 | } |
1241 | printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); | 1254 | printk(KERN_WARNING "RPC %s: retry failed, exit EIO\n", __FUNCTION__); |
1242 | out_eio: | 1255 | out_eio: |
1243 | error = -EIO; | 1256 | error = -EIO; |
1244 | out_err: | 1257 | out_err: |
1245 | rpc_exit(task, error); | 1258 | rpc_exit(task, error); |
1246 | return NULL; | 1259 | return ERR_PTR(error); |
1247 | out_overflow: | 1260 | out_overflow: |
1248 | printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); | 1261 | printk(KERN_WARNING "RPC %s: server reply was truncated.\n", __FUNCTION__); |
1249 | goto out_retry; | 1262 | goto out_garbage; |
1250 | } | 1263 | } |
1251 | 1264 | ||
1252 | static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) | 1265 | static int rpcproc_encode_null(void *rqstp, u32 *data, void *obj) |