aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:38:00 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2009-03-11 14:38:00 -0400
commit2a4919919a97911b0aa4b9f5ac1eab90ba87652b (patch)
treec12eb42c34f0d0b79130ae93ebd56159e8366ee8 /net
parent482f32e65d31cbf88d08306fa5d397cc945c3c26 (diff)
SUNRPC: Return EAGAIN instead of ENOTCONN when waking up xprt->pending
While we should definitely return socket errors to the task that is currently trying to send data, there is no need to propagate the same error to all the other tasks on xprt->pending. Doing so actually slows down recovery, since it causes more than one tasks to attempt socket recovery. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/clnt.c15
-rw-r--r--net/sunrpc/xprt.c20
-rw-r--r--net/sunrpc/xprtsock.c58
3 files changed, 41 insertions, 52 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 145715b53115..5abab094441f 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1032,27 +1032,20 @@ call_connect_status(struct rpc_task *task)
1032 dprint_status(task); 1032 dprint_status(task);
1033 1033
1034 task->tk_status = 0; 1034 task->tk_status = 0;
1035 if (status >= 0) { 1035 if (status >= 0 || status == -EAGAIN) {
1036 clnt->cl_stats->netreconn++; 1036 clnt->cl_stats->netreconn++;
1037 task->tk_action = call_transmit; 1037 task->tk_action = call_transmit;
1038 return; 1038 return;
1039 } 1039 }
1040 1040
1041 /* Something failed: remote service port may have changed */
1042 rpc_force_rebind(clnt);
1043
1044 switch (status) { 1041 switch (status) {
1045 case -ENOTCONN:
1046 case -EAGAIN:
1047 task->tk_action = call_bind;
1048 if (!RPC_IS_SOFT(task))
1049 return;
1050 /* if soft mounted, test if we've timed out */ 1042 /* if soft mounted, test if we've timed out */
1051 case -ETIMEDOUT: 1043 case -ETIMEDOUT:
1052 task->tk_action = call_timeout; 1044 task->tk_action = call_timeout;
1053 return; 1045 break;
1046 default:
1047 rpc_exit(task, -EIO);
1054 } 1048 }
1055 rpc_exit(task, -EIO);
1056} 1049}
1057 1050
1058/* 1051/*
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index d588e755e107..a0bfe53f1621 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -611,7 +611,7 @@ void xprt_disconnect_done(struct rpc_xprt *xprt)
611 dprintk("RPC: disconnected transport %p\n", xprt); 611 dprintk("RPC: disconnected transport %p\n", xprt);
612 spin_lock_bh(&xprt->transport_lock); 612 spin_lock_bh(&xprt->transport_lock);
613 xprt_clear_connected(xprt); 613 xprt_clear_connected(xprt);
614 xprt_wake_pending_tasks(xprt, -ENOTCONN); 614 xprt_wake_pending_tasks(xprt, -EAGAIN);
615 spin_unlock_bh(&xprt->transport_lock); 615 spin_unlock_bh(&xprt->transport_lock);
616} 616}
617EXPORT_SYMBOL_GPL(xprt_disconnect_done); 617EXPORT_SYMBOL_GPL(xprt_disconnect_done);
@@ -629,7 +629,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
629 /* Try to schedule an autoclose RPC call */ 629 /* Try to schedule an autoclose RPC call */
630 if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) 630 if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
631 queue_work(rpciod_workqueue, &xprt->task_cleanup); 631 queue_work(rpciod_workqueue, &xprt->task_cleanup);
632 xprt_wake_pending_tasks(xprt, -ENOTCONN); 632 xprt_wake_pending_tasks(xprt, -EAGAIN);
633 spin_unlock_bh(&xprt->transport_lock); 633 spin_unlock_bh(&xprt->transport_lock);
634} 634}
635 635
@@ -656,7 +656,7 @@ void xprt_conditional_disconnect(struct rpc_xprt *xprt, unsigned int cookie)
656 /* Try to schedule an autoclose RPC call */ 656 /* Try to schedule an autoclose RPC call */
657 if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0) 657 if (test_and_set_bit(XPRT_LOCKED, &xprt->state) == 0)
658 queue_work(rpciod_workqueue, &xprt->task_cleanup); 658 queue_work(rpciod_workqueue, &xprt->task_cleanup);
659 xprt_wake_pending_tasks(xprt, -ENOTCONN); 659 xprt_wake_pending_tasks(xprt, -EAGAIN);
660out: 660out:
661 spin_unlock_bh(&xprt->transport_lock); 661 spin_unlock_bh(&xprt->transport_lock);
662} 662}
@@ -726,9 +726,8 @@ static void xprt_connect_status(struct rpc_task *task)
726 } 726 }
727 727
728 switch (task->tk_status) { 728 switch (task->tk_status) {
729 case -ENOTCONN: 729 case -EAGAIN:
730 dprintk("RPC: %5u xprt_connect_status: connection broken\n", 730 dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid);
731 task->tk_pid);
732 break; 731 break;
733 case -ETIMEDOUT: 732 case -ETIMEDOUT:
734 dprintk("RPC: %5u xprt_connect_status: connect attempt timed " 733 dprintk("RPC: %5u xprt_connect_status: connect attempt timed "
@@ -849,15 +848,8 @@ int xprt_prepare_transmit(struct rpc_task *task)
849 err = req->rq_received; 848 err = req->rq_received;
850 goto out_unlock; 849 goto out_unlock;
851 } 850 }
852 if (!xprt->ops->reserve_xprt(task)) { 851 if (!xprt->ops->reserve_xprt(task))
853 err = -EAGAIN; 852 err = -EAGAIN;
854 goto out_unlock;
855 }
856
857 if (!xprt_connected(xprt)) {
858 err = -ENOTCONN;
859 goto out_unlock;
860 }
861out_unlock: 853out_unlock:
862 spin_unlock_bh(&xprt->transport_lock); 854 spin_unlock_bh(&xprt->transport_lock);
863 return err; 855 return err;
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 879af6f27b4c..8e58b0b5460b 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1162,7 +1162,7 @@ static void xs_tcp_state_change(struct sock *sk)
1162 transport->tcp_flags = 1162 transport->tcp_flags =
1163 TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID; 1163 TCP_RCV_COPY_FRAGHDR | TCP_RCV_COPY_XID;
1164 1164
1165 xprt_wake_pending_tasks(xprt, 0); 1165 xprt_wake_pending_tasks(xprt, -EAGAIN);
1166 } 1166 }
1167 spin_unlock_bh(&xprt->transport_lock); 1167 spin_unlock_bh(&xprt->transport_lock);
1168 break; 1168 break;
@@ -1721,20 +1721,22 @@ static void xs_tcp_connect_worker4(struct work_struct *work)
1721 dprintk("RPC: %p connect status %d connected %d sock state %d\n", 1721 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
1722 xprt, -status, xprt_connected(xprt), 1722 xprt, -status, xprt_connected(xprt),
1723 sock->sk->sk_state); 1723 sock->sk->sk_state);
1724 if (status < 0) { 1724 switch (status) {
1725 switch (status) { 1725 case 0:
1726 case -EINPROGRESS: 1726 case -EINPROGRESS:
1727 case -EALREADY: 1727 case -EALREADY:
1728 goto out_clear; 1728 goto out_clear;
1729 case -ECONNREFUSED: 1729 case -ECONNREFUSED:
1730 case -ECONNRESET: 1730 case -ECONNRESET:
1731 /* retry with existing socket, after a delay */ 1731 /* retry with existing socket, after a delay */
1732 break; 1732 break;
1733 default: 1733 default:
1734 /* get rid of existing socket, and retry */ 1734 /* get rid of existing socket, and retry */
1735 xs_tcp_shutdown(xprt); 1735 xs_tcp_shutdown(xprt);
1736 } 1736 printk("%s: connect returned unhandled error %d\n",
1737 __func__, status);
1737 } 1738 }
1739 status = -EAGAIN;
1738out: 1740out:
1739 xprt_wake_pending_tasks(xprt, status); 1741 xprt_wake_pending_tasks(xprt, status);
1740out_clear: 1742out_clear:
@@ -1780,20 +1782,22 @@ static void xs_tcp_connect_worker6(struct work_struct *work)
1780 status = xs_tcp_finish_connecting(xprt, sock); 1782 status = xs_tcp_finish_connecting(xprt, sock);
1781 dprintk("RPC: %p connect status %d connected %d sock state %d\n", 1783 dprintk("RPC: %p connect status %d connected %d sock state %d\n",
1782 xprt, -status, xprt_connected(xprt), sock->sk->sk_state); 1784 xprt, -status, xprt_connected(xprt), sock->sk->sk_state);
1783 if (status < 0) { 1785 switch (status) {
1784 switch (status) { 1786 case 0:
1785 case -EINPROGRESS: 1787 case -EINPROGRESS:
1786 case -EALREADY: 1788 case -EALREADY:
1787 goto out_clear; 1789 goto out_clear;
1788 case -ECONNREFUSED: 1790 case -ECONNREFUSED:
1789 case -ECONNRESET: 1791 case -ECONNRESET:
1790 /* retry with existing socket, after a delay */ 1792 /* retry with existing socket, after a delay */
1791 break; 1793 break;
1792 default: 1794 default:
1793 /* get rid of existing socket, and retry */ 1795 /* get rid of existing socket, and retry */
1794 xs_tcp_shutdown(xprt); 1796 xs_tcp_shutdown(xprt);
1795 } 1797 printk("%s: connect returned unhandled error %d\n",
1798 __func__, status);
1796 } 1799 }
1800 status = -EAGAIN;
1797out: 1801out:
1798 xprt_wake_pending_tasks(xprt, status); 1802 xprt_wake_pending_tasks(xprt, status);
1799out_clear: 1803out_clear: