SUNRPC: Avoid an unnecessary task reschedule on ENOTCONN
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 11 Mar 2009 18:37:57 +0000 (14:37 -0400)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 11 Mar 2009 18:37:57 +0000 (14:37 -0400)
If the socket is unconnected, and xprt_transmit() returns ENOTCONN, we
currently give up the lock on the transport channel. Doing so means that
the lock automatically gets assigned to the next task in the xprt->sending
queue, and so that task needs to be woken up to do the actual connect.

The following patch aims to avoid that unnecessary task switch.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
net/sunrpc/clnt.c

index 836f15c0c4a3489b6e9d5ba5a7bfc59514a0db3d..07e9b05321e6876014b1a188e5a630a08da1101e 100644 (file)
@@ -1105,14 +1105,24 @@ static void
 call_transmit_status(struct rpc_task *task)
 {
        task->tk_action = call_status;
-       /*
-        * Special case: if we've been waiting on the socket's write_space()
-        * callback, then don't call xprt_end_transmit().
-        */
-       if (task->tk_status == -EAGAIN)
-               return;
-       xprt_end_transmit(task);
-       rpc_task_force_reencode(task);
+       switch (task->tk_status) {
+       case -EAGAIN:
+               break;
+       default:
+               xprt_end_transmit(task);
+               /*
+                * Special cases: if we've been waiting on the
+                * socket's write_space() callback, or if the
+                * socket just returned a connection error,
+                * then hold onto the transport lock.
+                */
+       case -ECONNREFUSED:
+       case -ENOTCONN:
+       case -EHOSTDOWN:
+       case -EHOSTUNREACH:
+       case -ENETUNREACH:
+               rpc_task_force_reencode(task);
+       }
 }
 
 /*