diff options
| -rw-r--r-- | include/linux/sunrpc/xprt.h | 2 | ||||
| -rw-r--r-- | net/sunrpc/clnt.c | 52 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 21 | ||||
| -rw-r--r-- | net/sunrpc/xprtsock.c | 29 |
4 files changed, 61 insertions, 43 deletions
diff --git a/include/linux/sunrpc/xprt.h b/include/linux/sunrpc/xprt.h index e8bbe8118de8..840e47a4ccc5 100644 --- a/include/linux/sunrpc/xprt.h +++ b/include/linux/sunrpc/xprt.h | |||
| @@ -229,7 +229,7 @@ int xprt_reserve_xprt(struct rpc_task *task); | |||
| 229 | int xprt_reserve_xprt_cong(struct rpc_task *task); | 229 | int xprt_reserve_xprt_cong(struct rpc_task *task); |
| 230 | int xprt_prepare_transmit(struct rpc_task *task); | 230 | int xprt_prepare_transmit(struct rpc_task *task); |
| 231 | void xprt_transmit(struct rpc_task *task); | 231 | void xprt_transmit(struct rpc_task *task); |
| 232 | void xprt_abort_transmit(struct rpc_task *task); | 232 | void xprt_end_transmit(struct rpc_task *task); |
| 233 | int xprt_adjust_timeout(struct rpc_rqst *req); | 233 | int xprt_adjust_timeout(struct rpc_rqst *req); |
| 234 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); | 234 | void xprt_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task); |
| 235 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); | 235 | void xprt_release_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task); |
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 4ba271f892c8..d6409e757219 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -921,26 +921,43 @@ call_transmit(struct rpc_task *task) | |||
| 921 | task->tk_status = xprt_prepare_transmit(task); | 921 | task->tk_status = xprt_prepare_transmit(task); |
| 922 | if (task->tk_status != 0) | 922 | if (task->tk_status != 0) |
| 923 | return; | 923 | return; |
| 924 | task->tk_action = call_transmit_status; | ||
| 924 | /* Encode here so that rpcsec_gss can use correct sequence number. */ | 925 | /* Encode here so that rpcsec_gss can use correct sequence number. */ |
| 925 | if (rpc_task_need_encode(task)) { | 926 | if (rpc_task_need_encode(task)) { |
| 926 | task->tk_rqstp->rq_bytes_sent = 0; | 927 | BUG_ON(task->tk_rqstp->rq_bytes_sent != 0); |
| 927 | call_encode(task); | 928 | call_encode(task); |
| 928 | /* Did the encode result in an error condition? */ | 929 | /* Did the encode result in an error condition? */ |
| 929 | if (task->tk_status != 0) | 930 | if (task->tk_status != 0) |
| 930 | goto out_nosend; | 931 | return; |
| 931 | } | 932 | } |
| 932 | task->tk_action = call_transmit_status; | ||
| 933 | xprt_transmit(task); | 933 | xprt_transmit(task); |
| 934 | if (task->tk_status < 0) | 934 | if (task->tk_status < 0) |
| 935 | return; | 935 | return; |
| 936 | if (!task->tk_msg.rpc_proc->p_decode) { | 936 | /* |
| 937 | task->tk_action = rpc_exit_task; | 937 | * On success, ensure that we call xprt_end_transmit() before sleeping |
| 938 | rpc_wake_up_task(task); | 938 | * in order to allow access to the socket to other RPC requests. |
| 939 | } | 939 | */ |
| 940 | return; | 940 | call_transmit_status(task); |
| 941 | out_nosend: | 941 | if (task->tk_msg.rpc_proc->p_decode != NULL) |
| 942 | /* release socket write lock before attempting to handle error */ | 942 | return; |
| 943 | xprt_abort_transmit(task); | 943 | task->tk_action = rpc_exit_task; |
| 944 | rpc_wake_up_task(task); | ||
| 945 | } | ||
| 946 | |||
| 947 | /* | ||
| 948 | * 5a. Handle cleanup after a transmission | ||
| 949 | */ | ||
| 950 | static void | ||
| 951 | call_transmit_status(struct rpc_task *task) | ||
| 952 | { | ||
| 953 | task->tk_action = call_status; | ||
| 954 | /* | ||
| 955 | * Special case: if we've been waiting on the socket's write_space() | ||
| 956 | * callback, then don't call xprt_end_transmit(). | ||
| 957 | */ | ||
| 958 | if (task->tk_status == -EAGAIN) | ||
| 959 | return; | ||
| 960 | xprt_end_transmit(task); | ||
| 944 | rpc_task_force_reencode(task); | 961 | rpc_task_force_reencode(task); |
| 945 | } | 962 | } |
| 946 | 963 | ||
| @@ -992,18 +1009,7 @@ call_status(struct rpc_task *task) | |||
| 992 | } | 1009 | } |
| 993 | 1010 | ||
| 994 | /* | 1011 | /* |
| 995 | * 6a. Handle transmission errors. | 1012 | * 6a. Handle RPC timeout |
| 996 | */ | ||
| 997 | static void | ||
| 998 | call_transmit_status(struct rpc_task *task) | ||
| 999 | { | ||
| 1000 | if (task->tk_status != -EAGAIN) | ||
| 1001 | rpc_task_force_reencode(task); | ||
| 1002 | call_status(task); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | /* | ||
| 1006 | * 6b. Handle RPC timeout | ||
| 1007 | * We do not release the request slot, so we keep using the | 1013 | * We do not release the request slot, so we keep using the |
| 1008 | * same XID for all retransmits. | 1014 | * same XID for all retransmits. |
| 1009 | */ | 1015 | */ |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 313b68d892c6..e8c2bc4977f3 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -707,12 +707,9 @@ out_unlock: | |||
| 707 | return err; | 707 | return err; |
| 708 | } | 708 | } |
| 709 | 709 | ||
| 710 | void | 710 | void xprt_end_transmit(struct rpc_task *task) |
| 711 | xprt_abort_transmit(struct rpc_task *task) | ||
| 712 | { | 711 | { |
| 713 | struct rpc_xprt *xprt = task->tk_xprt; | 712 | xprt_release_write(task->tk_xprt, task); |
| 714 | |||
| 715 | xprt_release_write(xprt, task); | ||
| 716 | } | 713 | } |
| 717 | 714 | ||
| 718 | /** | 715 | /** |
| @@ -761,8 +758,6 @@ void xprt_transmit(struct rpc_task *task) | |||
| 761 | task->tk_status = -ENOTCONN; | 758 | task->tk_status = -ENOTCONN; |
| 762 | else if (!req->rq_received) | 759 | else if (!req->rq_received) |
| 763 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); | 760 | rpc_sleep_on(&xprt->pending, task, NULL, xprt_timer); |
| 764 | |||
| 765 | xprt->ops->release_xprt(xprt, task); | ||
| 766 | spin_unlock_bh(&xprt->transport_lock); | 761 | spin_unlock_bh(&xprt->transport_lock); |
| 767 | return; | 762 | return; |
| 768 | } | 763 | } |
| @@ -772,18 +767,8 @@ void xprt_transmit(struct rpc_task *task) | |||
| 772 | * schedq, and being picked up by a parallel run of rpciod(). | 767 | * schedq, and being picked up by a parallel run of rpciod(). |
| 773 | */ | 768 | */ |
| 774 | task->tk_status = status; | 769 | task->tk_status = status; |
| 775 | 770 | if (status == -ECONNREFUSED) | |
| 776 | switch (status) { | ||
| 777 | case -ECONNREFUSED: | ||
| 778 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); | 771 | rpc_sleep_on(&xprt->sending, task, NULL, NULL); |
| 779 | case -EAGAIN: | ||
| 780 | case -ENOTCONN: | ||
| 781 | return; | ||
| 782 | default: | ||
| 783 | break; | ||
| 784 | } | ||
| 785 | xprt_release_write(xprt, task); | ||
| 786 | return; | ||
| 787 | } | 772 | } |
| 788 | 773 | ||
| 789 | static inline void do_xprt_reserve(struct rpc_task *task) | 774 | static inline void do_xprt_reserve(struct rpc_task *task) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ee678ed13b6f..441bd53f5eca 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -414,6 +414,33 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
| 414 | } | 414 | } |
| 415 | 415 | ||
| 416 | /** | 416 | /** |
| 417 | * xs_tcp_release_xprt - clean up after a tcp transmission | ||
| 418 | * @xprt: transport | ||
| 419 | * @task: rpc task | ||
| 420 | * | ||
| 421 | * This cleans up if an error causes us to abort the transmission of a request. | ||
| 422 | * In this case, the socket may need to be reset in order to avoid confusing | ||
| 423 | * the server. | ||
| 424 | */ | ||
| 425 | static void xs_tcp_release_xprt(struct rpc_xprt *xprt, struct rpc_task *task) | ||
| 426 | { | ||
| 427 | struct rpc_rqst *req; | ||
| 428 | |||
| 429 | if (task != xprt->snd_task) | ||
| 430 | return; | ||
| 431 | if (task == NULL) | ||
| 432 | goto out_release; | ||
| 433 | req = task->tk_rqstp; | ||
| 434 | if (req->rq_bytes_sent == 0) | ||
| 435 | goto out_release; | ||
| 436 | if (req->rq_bytes_sent == req->rq_snd_buf.len) | ||
| 437 | goto out_release; | ||
| 438 | set_bit(XPRT_CLOSE_WAIT, &task->tk_xprt->state); | ||
| 439 | out_release: | ||
| 440 | xprt_release_xprt(xprt, task); | ||
| 441 | } | ||
| 442 | |||
| 443 | /** | ||
| 417 | * xs_close - close a socket | 444 | * xs_close - close a socket |
| 418 | * @xprt: transport | 445 | * @xprt: transport |
| 419 | * | 446 | * |
| @@ -1250,7 +1277,7 @@ static struct rpc_xprt_ops xs_udp_ops = { | |||
| 1250 | 1277 | ||
| 1251 | static struct rpc_xprt_ops xs_tcp_ops = { | 1278 | static struct rpc_xprt_ops xs_tcp_ops = { |
| 1252 | .reserve_xprt = xprt_reserve_xprt, | 1279 | .reserve_xprt = xprt_reserve_xprt, |
| 1253 | .release_xprt = xprt_release_xprt, | 1280 | .release_xprt = xs_tcp_release_xprt, |
| 1254 | .set_port = xs_set_port, | 1281 | .set_port = xs_set_port, |
| 1255 | .connect = xs_connect, | 1282 | .connect = xs_connect, |
| 1256 | .buf_alloc = rpc_malloc, | 1283 | .buf_alloc = rpc_malloc, |
