rx: Don't build a call to immediately abort it
authorSimon Wilkinson <sxw@your-file-system.com>
Fri, 26 Oct 2012 11:21:41 +0000 (12:21 +0100)
committerDerrick Brashear <shadow@your-file-system.com>
Mon, 29 Oct 2012 20:33:49 +0000 (13:33 -0700)
If the server is over the busy threshold, then don't create a new
call structure just to be able to send an abort on that call. Instead,
use rx_SendRawAbort to send an abort packet on the appropriate channel.

Change-Id: I02782fc25fe8ed7608b39e3f8355e2793f7526e3
Reviewed-on: http://gerrit.openafs.org/8296
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>

src/rx/rx.c

index 631cd97..7a255be 100644 (file)
@@ -3208,6 +3208,26 @@ rxi_CheckBusy(struct rx_call *call)
     MUTEX_EXIT(&conn->conn_call_lock);
 }
 
+/*!
+ * Abort the call if the server is over the busy threshold. This
+ * can be used without requiring a call structure be initialised,
+ * or connected to a particular channel
+ */
+static_inline int
+rxi_AbortIfServerBusy(osi_socket socket, afs_uint32 host,
+                     u_short port, struct rx_packet *np)
+{
+    if ((rx_BusyThreshold > 0) &&
+       (rx_atomic_read(&rx_nWaiting) > rx_BusyThreshold)) {
+       rxi_SendRawAbort(socket, host, port, rx_BusyError, np, 0);
+       if (rx_stats_active)
+           rx_atomic_inc(&rx_stats.nBusies);
+       return 1;
+    }
+
+    return 0;
+}
+
 /* There are two packet tracing routines available for testing and monitoring
  * Rx.  One is called just after every packet is received and the other is
  * called just before every packet is sent.  Received packets, have had their
@@ -3398,6 +3418,12 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
         currentCallNumber = conn->callNumber[channel];
         MUTEX_EXIT(&conn->conn_call_lock);
     } else if (type == RX_SERVER_CONNECTION) {  /* No call allocated */
+
+       if (rxi_AbortIfServerBusy(socket, host, port, np)) {
+           putConnection(conn);
+           return np;
+       }
+
        call = rxi_NewCall(conn, channel);  /* returns locked call */
        *call->callNumber = currentCallNumber = np->header.callNumber;
        MUTEX_EXIT(&conn->conn_call_lock);
@@ -3405,23 +3431,8 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
        clock_GetTime(&call->queueTime);
        call->app.bytesSent = 0;
        call->app.bytesRcvd = 0;
-       /*
-        * If the number of queued calls exceeds the overload
-        * threshold then abort this call.
-        */
-       if ((rx_BusyThreshold > 0) &&
-           (rx_atomic_read(&rx_nWaiting) > rx_BusyThreshold)) {
-           struct rx_packet *tp;
-
-           rxi_CallError(call, rx_BusyError);
-           tp = rxi_SendCallAbort(call, np, 1, 0);
-           MUTEX_EXIT(&call->lock);
-           putConnection(conn);
-           if (rx_stats_active)
-               rx_atomic_inc(&rx_stats.nBusies);
-           return tp;
-        }
        rxi_KeepAliveOn(call);
+
     } else {    /* RX_CLIENT_CONNECTION and No call allocated */
         /* This packet can't be for this call. If the new call address is
          * 0 then no call is running on this channel. If there is a call
@@ -3478,6 +3489,13 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
                putConnection(conn);
                return tp;
            }
+
+           if (rxi_AbortIfServerBusy(socket, host, port, np)) {
+               MUTEX_EXIT(&call->lock);
+               putConnection(conn);
+               return np;
+           }
+
            rxi_ResetCall(call, 0);
             /*
              * The conn_call_lock is not held but no one else should be
@@ -3489,22 +3507,6 @@ rxi_ReceivePacket(struct rx_packet *np, osi_socket socket,
            clock_GetTime(&call->queueTime);
            call->app.bytesSent = 0;
            call->app.bytesRcvd = 0;
-           /*
-            * If the number of queued calls exceeds the overload
-            * threshold then abort this call.
-            */
-           if ((rx_BusyThreshold > 0) &&
-               (rx_atomic_read(&rx_nWaiting) > rx_BusyThreshold)) {
-               struct rx_packet *tp;
-
-               rxi_CallError(call, rx_BusyError);
-               tp = rxi_SendCallAbort(call, np, 1, 0);
-               MUTEX_EXIT(&call->lock);
-               putConnection(conn);
-                if (rx_stats_active)
-                    rx_atomic_inc(&rx_stats.nBusies);
-               return tp;
-           }
            rxi_KeepAliveOn(call);
        } else {
            /* Continuing call; do nothing here. */