From eddcee3ad518dff9fbfda790640c5bfd2e97ef5a Mon Sep 17 00:00:00 2001 From: Andrew Deason Date: Mon, 7 Mar 2011 11:08:26 -0600 Subject: [PATCH] RX: Avoid timing out non-kernel busy channels 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 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- src/afs/afs_call.c | 2 ++ src/afs/afs_pag_call.c | 1 + src/libafsrpc/afsrpc.def | 1 + src/libafsrpc/afsrpc.exp | 1 + src/rx/rx.c | 33 +++++++++++++++++++++++++++++---- src/rx/rx_prototypes.h | 1 + src/shlibafsrpc/Makefile.in | 2 +- src/shlibafsrpc/libafsrpc.map | 1 + 8 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/afs/afs_call.c b/src/afs/afs_call.c index 2fd25b7..01704ad 100644 --- a/src/afs/afs_call.c +++ b/src/afs/afs_call.c @@ -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 */ diff --git a/src/afs/afs_pag_call.c b/src/afs/afs_pag_call.c index 5c61015..1a11ebf 100644 --- a/src/afs/afs_pag_call.c +++ b/src/afs/afs_pag_call.c @@ -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); diff --git a/src/libafsrpc/afsrpc.def b/src/libafsrpc/afsrpc.def index eddafe6..bc33abc 100755 --- a/src/libafsrpc/afsrpc.def +++ b/src/libafsrpc/afsrpc.def @@ -293,6 +293,7 @@ EXPORTS rx_identity_freeContents @302 rx_identity_free @303 + rx_SetBusyChannelError @304 ; for performance testing rx_TSFPQGlobSize @2001 DATA diff --git a/src/libafsrpc/afsrpc.exp b/src/libafsrpc/afsrpc.exp index 0355bc9..7dd2779 100755 --- a/src/libafsrpc/afsrpc.exp +++ b/src/libafsrpc/afsrpc.exp @@ -34,6 +34,7 @@ rx_ReleaseCachedConnection rx_ServerProc rx_StartServer rx_WriteProc +rx_SetBusyChannelError rxevent_Init rxevent_Post rxkad_GetServerInfo diff --git a/src/rx/rx.c b/src/rx/rx.c index 949e89d..9fc9718 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -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); } diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h index 21eada6..b4b3b8c 100644 --- a/src/rx/rx_prototypes.h +++ b/src/rx/rx_prototypes.h @@ -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); diff --git a/src/shlibafsrpc/Makefile.in b/src/shlibafsrpc/Makefile.in index 92fbd81..984ecdd 100644 --- a/src/shlibafsrpc/Makefile.in +++ b/src/shlibafsrpc/Makefile.in @@ -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. diff --git a/src/shlibafsrpc/libafsrpc.map b/src/shlibafsrpc/libafsrpc.map index 4619447..ce468e4 100755 --- a/src/shlibafsrpc/libafsrpc.map +++ b/src/shlibafsrpc/libafsrpc.map @@ -159,6 +159,7 @@ rx_identity_freeContents; rx_identity_free; rx_InterruptCall; + rx_SetBusyChannelError; local: *; }; -- 1.7.1