RX: Avoid timing out non-kernel busy channels
authorAndrew Deason <adeason@sinenomine.net>
Mon, 7 Mar 2011 17:08:26 +0000 (11:08 -0600)
committerDerrick Brashear <shadow@dementia.org>
Tue, 8 Mar 2011 19:55:33 +0000 (11:55 -0800)
When we encounter a "busy" call channel (indicated by receiving
RX_PACKET_TYPE_BUSY packets), we can error out a call with
RX_CALL_TIMEOUT to try and get the application code to retry the call.
However, many RX applications are not aware of this, and will just
fail with an error upon receiving a single busy packet.

So instead, make this behavior optional, and only do it if the
application tells us what specific error it expects to receive when a
busy call channel is detected. Enable this behavior for the Unix cache
manager, as it can cope with receiving an RX_CALL_TIMEOUT error in
this scenario.

Change-Id: I2fe03c0ff81576da3b2ce2b4d27a16d5631c073e
Reviewed-on: http://gerrit.openafs.org/4159
Reviewed-by: Jeffrey Altman <jaltman@openafs.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>

src/afs/afs_call.c
src/afs/afs_pag_call.c
src/libafsrpc/afsrpc.def
src/libafsrpc/afsrpc.exp
src/rx/rx.c
src/rx/rx_prototypes.h
src/shlibafsrpc/Makefile.in
src/shlibafsrpc/libafsrpc.map

index 2fd25b7..01704ad 100644 (file)
@@ -110,6 +110,8 @@ afs_InitSetup(int preallocs)
 
     memset(afs_zeros, 0, AFS_ZEROS);
 
+    rx_SetBusyChannelError(RX_CALL_TIMEOUT);
+
     /* start RX */
     if(!afscall_set_rxpck_received)
     rx_extraPackets = AFS_NRXPACKETS;  /* smaller # of packets */
index 5c61015..1a11ebf 100644 (file)
@@ -101,6 +101,7 @@ afspag_Init(afs_int32 nfs_server_addr)
     AFS_GLOCK();
 
     afs_InitStats();
+    rx_SetBusyChannelError(RX_CALL_TIMEOUT);
     rx_Init(htons(7001));
 
     AFS_STATCNT(afs_ResourceInit);
index eddafe6..bc33abc 100755 (executable)
@@ -293,6 +293,7 @@ EXPORTS
        rx_identity_freeContents                @302
        rx_identity_free                        @303
 
+       rx_SetBusyChannelError                  @304
 
 ; for performance testing
         rx_TSFPQGlobSize                        @2001 DATA
index 0355bc9..7dd2779 100755 (executable)
@@ -34,6 +34,7 @@ rx_ReleaseCachedConnection
 rx_ServerProc
 rx_StartServer
 rx_WriteProc
+rx_SetBusyChannelError
 rxevent_Init
 rxevent_Post
 rxkad_GetServerInfo
index 949e89d..9fc9718 100644 (file)
@@ -143,6 +143,16 @@ static unsigned int rxi_rpc_peer_stat_cnt;
 
 static unsigned int rxi_rpc_process_stat_cnt;
 
+/*
+ * rxi_busyChannelError is the error to return to the application when a call
+ * channel appears busy (inferred from the receipt of RX_PACKET_TYPE_BUSY
+ * packets on the channel), and there are other call channels in the
+ * connection that are not busy. If 0, we do not return errors upon receiving
+ * busy packets; we just keep trying on the same call channel until we hit a
+ * timeout.
+ */
+static afs_int32 rxi_busyChannelError = 0;
+
 rx_atomic_t rx_nWaiting = RX_ATOMIC_INIT(0);
 rx_atomic_t rx_nWaited = RX_ATOMIC_INIT(0);
 
@@ -600,6 +610,20 @@ rx_Init(u_int port)
     return rx_InitHost(htonl(INADDR_ANY), port);
 }
 
+/**
+ * Sets the error generated when a busy call channel is detected.
+ *
+ * @param[in] error The error to return for a call on a busy channel.
+ *
+ * @pre Neither rx_Init nor rx_InitHost have been called yet
+ */
+void
+rx_SetBusyChannelError(afs_int32 error)
+{
+    osi_Assert(rxinit_status != 0);
+    rxi_busyChannelError = error;
+}
+
 /* called with unincremented nRequestsRunning to see if it is OK to start
  * a new thread in this service.  Could be "no" for two reasons: over the
  * max quota, or would prevent others from reaching their min quota.
@@ -2818,6 +2842,7 @@ rxi_FindConnection(osi_socket socket, afs_uint32 host,
  *      call->conn->lastBusy[call->channel] != 0)
  *
  * @pre call->lock is held
+ * @pre rxi_busyChannelError is nonzero
  *
  * @note call->lock is dropped and reacquired
  */
@@ -2882,10 +2907,10 @@ rxi_CheckBusy(struct rx_call *call)
         * rx_conn that the application thread might be able to use. We know
         * that we have the correct call since callNumber is unchanged, and we
         * know that the call is still busy. So, set the call error state to
-        * RX_CALL_TIMEOUT so the application can retry the request, presumably
-        * on a less-busy call channel. */
+        * rxi_busyChannelError so the application can retry the request,
+        * presumably on a less-busy call channel. */
 
-       rxi_CallError(call, RX_CALL_TIMEOUT);
+       rxi_CallError(call, rxi_busyChannelError);
     }
 }
 
@@ -5789,7 +5814,7 @@ rxi_Start(struct rxevent *event,
         MUTEX_EXIT(&rx_refcnt_mutex);
        call->resendEvent = NULL;
 
-       if ((call->flags & RX_CALL_PEER_BUSY)) {
+       if (rxi_busyChannelError && (call->flags & RX_CALL_PEER_BUSY)) {
            rxi_CheckBusy(call);
        }
 
index 21eada6..b4b3b8c 100644 (file)
@@ -24,6 +24,7 @@ extern int (*rx_almostSent) (struct rx_packet *, struct sockaddr_in *);
 extern void rx_SetEpoch(afs_uint32 epoch);
 extern int rx_Init(u_int port);
 extern int rx_InitHost(u_int host, u_int port);
+extern void rx_SetBusyChannelError(afs_int32 error);
 #ifdef AFS_NT40_ENV
 extern void rx_DebugOnOff(int on);
 extern void rx_StatsOnOff(int on);
index 92fbd81..984ecdd 100644 (file)
@@ -1,7 +1,7 @@
 # API version. When something changes, increment as appropriate. 
 # Ignore at your own risk.
 LIBAFSRPCMAJOR=1
-LIBAFSRPCMINOR=3
+LIBAFSRPCMINOR=4
 
 # Copyright 2000, International Business Machines Corporation and others.
 # All Rights Reserved.
index 4619447..ce468e4 100755 (executable)
        rx_identity_freeContents;
        rx_identity_free;
        rx_InterruptCall;
+       rx_SetBusyChannelError;
     local:
        *;
 };