diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-11 14:37:59 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2009-03-11 14:37:59 -0400 |
commit | c8485e4d634f6df155040293928707f127f0d06d (patch) | |
tree | 72ec8a7ea829e4f7df4648e646353c55a037e50e /net/sunrpc/xprt.c | |
parent | 40d2549db5f515e415894def98b49db7d4c56714 (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>
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 38 |
1 files changed, 16 insertions, 22 deletions
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 | ||
932 | static inline void do_xprt_reserve(struct rpc_task *task) | 926 | static inline void do_xprt_reserve(struct rpc_task *task) |