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)
committerGreg Kroah-Hartman <gregkh@suse.de>
Thu, 30 Jul 2009 23:06:08 +0000 (16:06 -0700)
commit 15f081ca8ddfe150fb639c591b18944a539da0fc upstream.

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>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
net/sunrpc/clnt.c

index 76739e9..66cfe88 100644 (file)
@@ -1089,14 +1089,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);
+       }
 }
 
 /*