aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:37:59 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:37:59 -0400
commitc8485e4d634f6df155040293928707f127f0d06d (patch)
tree72ec8a7ea829e4f7df4648e646353c55a037e50e
parent40d2549db5f515e415894def98b49db7d4c56714 (diff)
SUNRPC: Handle ECONNREFUSED correctly in xprt_transmit()
If we get an ECONNREFUSED error, we currently go to sleep on the 'xprt->sending' wait queue. The problem is that no timeout is set there, and there is nothing else that will wake the task up later. We should deal with ECONNREFUSED in call_status, given that is where we also deal with -EHOSTDOWN, and friends. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--net/sunrpc/clnt.c7
-rw-r--r--net/sunrpc/xprt.c38
-rw-r--r--net/sunrpc/xprtsock.c26
3 files changed, 34 insertions, 37 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 07e9b05321e6..145715b53115 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1117,10 +1117,12 @@ call_transmit_status(struct rpc_task *task)
1117 * then hold onto the transport lock. 1117 * then hold onto the transport lock.
1118 */ 1118 */
1119 case -ECONNREFUSED: 1119 case -ECONNREFUSED:
1120 case -ECONNRESET:
1120 case -ENOTCONN: 1121 case -ENOTCONN:
1121 case -EHOSTDOWN: 1122 case -EHOSTDOWN:
1122 case -EHOSTUNREACH: 1123 case -EHOSTUNREACH:
1123 case -ENETUNREACH: 1124 case -ENETUNREACH:
1125 case -EPIPE:
1124 rpc_task_force_reencode(task); 1126 rpc_task_force_reencode(task);
1125 } 1127 }
1126} 1128}
@@ -1162,9 +1164,12 @@ call_status(struct rpc_task *task)
1162 xprt_conditional_disconnect(task->tk_xprt, 1164 xprt_conditional_disconnect(task->tk_xprt,
1163 req->rq_connect_cookie); 1165 req->rq_connect_cookie);
1164 break; 1166 break;
1167 case -ECONNRESET:
1165 case -ECONNREFUSED: 1168 case -ECONNREFUSED:
1166 case -ENOTCONN:
1167 rpc_force_rebind(clnt); 1169 rpc_force_rebind(clnt);
1170 rpc_delay(task, 3*HZ);
1171 case -EPIPE:
1172 case -ENOTCONN:
1168 task->tk_action = call_bind; 1173 task->tk_action = call_bind;
1169 break; 1174 break;
1170 case -EAGAIN: 1175 case -EAGAIN:
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index d1afec640394..d588e755e107 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -901,32 +901,26 @@ void xprt_transmit(struct rpc_task *task)
901 req->rq_connect_cookie = xprt->connect_cookie; 901 req->rq_connect_cookie = xprt->connect_cookie;
902 req->rq_xtime = jiffies; 902 req->rq_xtime = jiffies;
903 status = xprt->ops->send_request(task); 903 status = xprt->ops->send_request(task);
904 if (status == 0) { 904 if (status != 0) {
905 dprintk("RPC: %5u xmit complete\n", task->tk_pid); 905 task->tk_status = status;
906 spin_lock_bh(&xprt->transport_lock); 906 return;
907 }
907 908
908 xprt->ops->set_retrans_timeout(task); 909 dprintk("RPC: %5u xmit complete\n", task->tk_pid);
910 spin_lock_bh(&xprt->transport_lock);
909 911
910 xprt->stat.sends++; 912 xprt->ops->set_retrans_timeout(task);
911 xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
912 xprt->stat.bklog_u += xprt->backlog.qlen;
913 913
914 /* Don't race with disconnect */ 914 xprt->stat.sends++;
915 if (!xprt_connected(xprt)) 915 xprt->stat.req_u += xprt->stat.sends - xprt->stat.recvs;
916 task->tk_status = -ENOTCONN; 916 xprt->stat.bklog_u += xprt->backlog.qlen;
917 else if (!req->rq_received)
918 rpc_sleep_on(&xprt->pending, task, xprt_timer);
919 spin_unlock_bh(&xprt->transport_lock);
920 return;
921 }
922 917
923 /* Note: at this point, task->tk_sleeping has not yet been set, 918 /* Don't race with disconnect */
924 * hence there is no danger of the waking up task being put on 919 if (!xprt_connected(xprt))
925 * schedq, and being picked up by a parallel run of rpciod(). 920 task->tk_status = -ENOTCONN;
926 */ 921 else if (!req->rq_received)
927 task->tk_status = status; 922 rpc_sleep_on(&xprt->pending, task, xprt_timer);
928 if (status == -ECONNREFUSED) 923 spin_unlock_bh(&xprt->transport_lock);
929 rpc_sleep_on(&xprt->sending, task, NULL);
930} 924}
931 925
932static inline void do_xprt_reserve(struct rpc_task *task) 926static inline void do_xprt_reserve(struct rpc_task *task)
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 9d1898f6ee87..5e8198bede81 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -594,6 +594,8 @@ static int xs_udp_send_request(struct rpc_task *task)
594 /* Still some bytes left; set up for a retry later. */ 594 /* Still some bytes left; set up for a retry later. */
595 status = -EAGAIN; 595 status = -EAGAIN;
596 } 596 }
597 if (!transport->sock)
598 goto out;
597 599
598 switch (status) { 600 switch (status) {
599 case -ENOTSOCK: 601 case -ENOTSOCK:
@@ -603,19 +605,17 @@ static int xs_udp_send_request(struct rpc_task *task)
603 case -EAGAIN: 605 case -EAGAIN:
604 xs_nospace(task); 606 xs_nospace(task);
605 break; 607 break;
608 default:
609 dprintk("RPC: sendmsg returned unrecognized error %d\n",
610 -status);
606 case -ENETUNREACH: 611 case -ENETUNREACH:
607 case -EPIPE: 612 case -EPIPE:
608 case -ECONNREFUSED: 613 case -ECONNREFUSED:
609 /* When the server has died, an ICMP port unreachable message 614 /* When the server has died, an ICMP port unreachable message
610 * prompts ECONNREFUSED. */ 615 * prompts ECONNREFUSED. */
611 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); 616 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
612 break;
613 default:
614 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
615 dprintk("RPC: sendmsg returned unrecognized error %d\n",
616 -status);
617 } 617 }
618 618out:
619 return status; 619 return status;
620} 620}
621 621
@@ -697,6 +697,8 @@ static int xs_tcp_send_request(struct rpc_task *task)
697 status = -EAGAIN; 697 status = -EAGAIN;
698 break; 698 break;
699 } 699 }
700 if (!transport->sock)
701 goto out;
700 702
701 switch (status) { 703 switch (status) {
702 case -ENOTSOCK: 704 case -ENOTSOCK:
@@ -706,21 +708,17 @@ static int xs_tcp_send_request(struct rpc_task *task)
706 case -EAGAIN: 708 case -EAGAIN:
707 xs_nospace(task); 709 xs_nospace(task);
708 break; 710 break;
711 default:
712 dprintk("RPC: sendmsg returned unrecognized error %d\n",
713 -status);
709 case -ECONNRESET: 714 case -ECONNRESET:
710 xs_tcp_shutdown(xprt); 715 xs_tcp_shutdown(xprt);
711 case -ECONNREFUSED: 716 case -ECONNREFUSED:
712 case -ENOTCONN: 717 case -ENOTCONN:
713 case -EPIPE: 718 case -EPIPE:
714 status = -ENOTCONN;
715 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
716 break;
717 default:
718 dprintk("RPC: sendmsg returned unrecognized error %d\n",
719 -status);
720 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags); 719 clear_bit(SOCK_ASYNC_NOSPACE, &transport->sock->flags);
721 xs_tcp_shutdown(xprt);
722 } 720 }
723 721out:
724 return status; 722 return status;
725} 723}
726 724