]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
rx: RX_CALL_IDLE and RX_CALL_BUSY
authorJeffrey Altman <jaltman@your-file-system.com>
Mon, 28 Nov 2011 17:58:02 +0000 (12:58 -0500)
committerDerrick Brashear <shadow@dementix.org>
Tue, 24 Jan 2012 02:49:44 +0000 (18:49 -0800)
Allocate new Rx error codes for Idle and Busy calls but do not
send these errors on the wire.  They are only intended for local
use.

RX_CALL_IDLE is an indication to an application that requests it
that the rx peer is maintaining an open call channel but has not
sent any actual data for the length of the registered idle dead
timeout.

RX_CALL_BUSY is an indication to an application that requests it
that the rx peer believes the selected call channel is in use by
a pre-existing call.

When either RX_CALL_IDLE or RX_CALL_BUSY are assigned as the call
error and an abort must be sent to the rx peer, the errors are
translated to RX_CALL_TIMEOUT.  This is necessary because it is
not possible to add new Rx error values in a method that is safe
for peers that are not expecting them.

This patchset also documents which Rx errors defined in rx.h are
used on the wire and which are not.

The Unix and Windows cache managers are updated to build with
these new error codes.

eviewed-on: http://gerrit.openafs.org/6128
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@secure-endpoints.com>
Tested-by: Jeffrey Altman <jaltman@secure-endpoints.com>
(cherry picked from commit c7673f4fad8e8b9390564e3cbfa11d5f1b52ba2f)
Change-Id: I4c7d6733ddae03bda5a31fe4486ada090dcfd0b3
Reviewed-on: http://gerrit.openafs.org/6612
Reviewed-by: Derrick Brashear <shadow@dementix.org>
12 files changed:
src/WINNT/afsd/afsd_init.c
src/WINNT/afsd/cm.h
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_server.c
src/WINNT/afsd/cm_utils.c
src/afs/afs_analyze.c
src/afs/afs_call.c
src/afs/afs_conn.c
src/afs/afs_pag_call.c
src/rx/rx.c
src/rx/rx.h
src/rx/rx_prototypes.h

index d9761f5193329396311eae546330ae2805302fef..f3d8a315f71a225eee23ecb1e91d311c92b4d67d 100644 (file)
@@ -1343,7 +1343,7 @@ afsd_InitCM(char **reasonP)
         afsi_log("rx_SetUdpBufSize %d", rx_udpbufsize);
     }
 
-    rx_SetBusyChannelError(CM_RX_RETRY_BUSY_CALL);
+    rx_SetBusyChannelError(1);  /* Activate busy call channel reporting */
 
     /* initialize RX, and tell it to listen to the callbackport,
      * which is used for callback RPC messages.
index e80848c925399f8fff8663775d9045a41ce36f78..8ef4c9a5e457d086811d486f341da5e9fb80901d 100644 (file)
@@ -34,9 +34,6 @@
 #define CM_FLAG_NOPROBE         0x100           /* For use with cm_GetCellxxx - do not probe server status */
 #define CM_FLAG_DFS_REFERRAL    0x200           /* The request is a DFS Referral - the last char of the lookup name may be missing */
 
-/* Private RX Errors */
-#define CM_RX_RETRY_BUSY_CALL           (-13)
-
 /* Used by cm_FollowMountPoint and cm_FindVolumeByName */
 /* And as an index in cm_volume_t */
 #define RWVOL  0
index 6a5f17e643365b4afa614b2a51b29eb967da00eb..e786fe2dc40d3f711b07f92c7043f8a0434116a6 100644 (file)
@@ -747,7 +747,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
 
         retry = 1;
     }
-    else if (errorCode == CM_RX_RETRY_BUSY_CALL) {
+    else if (errorCode == RX_CALL_BUSY) {
         /*
          * RPC failed because the selected call channel
          * is currently busy on the server.  Unconditionally
@@ -990,7 +990,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
 
     /* If not allowed to retry, don't */
     if (!forcing_new && (reqp->flags & CM_REQ_NORETRY) &&
-        (errorCode != RX_MSGSIZE && errorCode != CM_RX_RETRY_BUSY_CALL))
+        (errorCode != RX_MSGSIZE && errorCode != RX_CALL_BUSY))
        retry = 0;
     else if (retry && dead_session)
         retry = 0;
@@ -1207,12 +1207,11 @@ static void cm_NewRXConnection(cm_conn_t *tcp, cm_ucell_t *ucellp,
                                     secIndex);
     rx_SetConnDeadTime(tcp->rxconnp, ConnDeadtimeout);
     rx_SetConnHardDeadTime(tcp->rxconnp, HardDeadtimeout);
-    rx_SetConnIdleDeadTime(tcp->rxconnp, IdleDeadtimeout);
 
     /*
-     * Register the error to be returned on an idle dead timeout
+     * Setting idle dead timeout to a non-zero value activates RX_CALL_IDLE errors
      */
-    rx_SetServerConnIdleDeadErr(tcp->rxconnp, RX_CALL_DEAD);
+    rx_SetConnIdleDeadTime(tcp->rxconnp, IdleDeadtimeout);
 
     /*
      * Let the Rx library know that we can auto-retry if an
index bfee6275c18cd9269880eeacdc15eec0d7e9a6e9..45925c7c2c42700821d1f7e5e7c7540d8abc4f61 100644 (file)
@@ -169,13 +169,14 @@ cm_PingServer(cm_server_t *tsp)
     }  /* got an unauthenticated connection to this server */
 
     lock_ObtainMutex(&tsp->mx);
-    if (code >= 0 || code == RXGEN_OPCODE) {
+    if (code >= 0 || code == RXGEN_OPCODE || code == RX_CALL_BUSY) {
        /* mark server as up */
        _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
         tsp->downTime = 0;
 
        /* we currently handle 32-bits of capabilities */
-       if (code != RXGEN_OPCODE && caps.Capabilities_len > 0) {
+       if (code != RXGEN_OPCODE && code != RX_CALL_BUSY &&
+            caps.Capabilities_len > 0) {
            tsp->capabilities = caps.Capabilities_val[0];
            xdr_free((xdrproc_t) xdr_Capabilities, &caps);
            caps.Capabilities_len = 0;
@@ -452,13 +453,15 @@ static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
             lock_ObtainMutex(&tsp->mx);
             wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
 
-            if (results[i] >= 0 || results[i] == RXGEN_OPCODE)  {
+            if (results[i] >= 0 || results[i] == RXGEN_OPCODE ||
+                results[i] == RX_CALL_BUSY)  {
                 /* mark server as up */
                 _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
                 tsp->downTime = 0;
 
                 /* we currently handle 32-bits of capabilities */
-                if (results[i] != RXGEN_OPCODE && caps[i].Capabilities_len > 0) {
+                if (results[i] != RXGEN_OPCODE && results[i] != RX_CALL_BUSY &&
+                    caps[i].Capabilities_len > 0) {
                     tsp->capabilities = caps[i].Capabilities_val[0];
                     xdr_free((xdrproc_t) xdr_Capabilities, &caps[i]);
                     caps[i].Capabilities_len = 0;
@@ -617,7 +620,7 @@ static void cm_CheckServersMulti(afs_uint32 flags, cm_cell_t *cellp)
             lock_ObtainMutex(&tsp->mx);
             wasDown = tsp->flags & CM_SERVERFLAG_DOWN;
 
-            if (results[i] >= 0)  {
+            if (results[i] >= 0 || results[i] == RX_CALL_BUSY)  {
                 /* mark server as up */
                 _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN);
                 tsp->downTime = 0;
index c352627ce08a62a2da3a5741c4c07eac13e4d2bd..a13fc692c5385bdd1f516fa722d4bf6f13afdcff 100644 (file)
@@ -210,6 +210,8 @@ long cm_MapRPCError(long error, cm_req_t *reqp)
 
     if (error == RX_CALL_DEAD ||
         error == RX_CALL_TIMEOUT ||
+        error == RX_CALL_BUSY ||
+        error == RX_CALL_IDLE ||
         error == RX_MSGSIZE)
         error = CM_ERROR_RETRY;
     else if (error < 0)
@@ -274,6 +276,8 @@ long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
 
     if (error == RX_CALL_DEAD ||
         error == RX_CALL_TIMEOUT ||
+        error == RX_CALL_BUSY ||
+        error == RX_CALL_IDLE ||
         error == RX_MSGSIZE)
         error = CM_ERROR_RETRY;
     else if (error == VNOVNODE)
@@ -322,6 +326,8 @@ long cm_MapVLRPCError(long error, cm_req_t *reqp)
 
     if (error == RX_CALL_DEAD ||
         error == RX_CALL_TIMEOUT ||
+        error == RX_CALL_BUSY ||
+        error == RX_CALL_IDLE ||
         error == RX_MSGSIZE)
         error = CM_ERROR_RETRY;
     else if (error == RX_RESTARTING)
index 6dba5c0de989c20c2fceb8c58d32e2f1ccc4d700..379d4258b7deb80320eb739f3c0260bf223e1ba7 100644 (file)
@@ -571,7 +571,7 @@ afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
            shouldRetry = 1;
            goto out;
        }
-       if (acode == RX_CALL_TIMEOUT) {
+       if (acode == RX_CALL_TIMEOUT || acode == RX_CALL_IDLE || acode == RX_CALL_BUSY) {
            serversleft = afs_BlackListOnce(areq, afid, tsp);
            if (afid)
                tvp = afs_FindVolume(afid, READ_LOCK);
index 561ad6f7aad77fa5086ccb92d1f40871ee199855..735ffad75a16ec9fd0af0b8c23c79683cda07d80 100644 (file)
@@ -115,7 +115,7 @@ afs_InitSetup(int preallocs)
 
     memset(afs_zeros, 0, AFS_ZEROS);
 
-    rx_SetBusyChannelError(RX_CALL_TIMEOUT);
+    rx_SetBusyChannelError(1);  /* turn on busy call error reporting */
 
     /* start RX */
     if(!afscall_set_rxpck_received)
index 434c7617d9b1967d56014b5b5491d5712c3c1b74..cbe1fcbaf3937fdfa192644c30320a0b825be2e2 100644 (file)
@@ -329,8 +329,6 @@ afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
        if (service == 52) {
            rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
        }
-       /* set to a RX_CALL_TIMEOUT error to allow MTU retry to trigger */
-       rx_SetServerConnIdleDeadErr(tc->id, RX_CALL_DEAD);
         /* Setting idle dead time to non-zero activates RX_CALL_IDLE errors. */
        if (isrep)        
            rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead_rep);
index d61a91c7ef93116421caa7c23da60f6168cffaab..9d23e90821196c38d7e0fe5d1003744f523bef02 100644 (file)
@@ -98,7 +98,7 @@ afspag_Init(afs_int32 nfs_server_addr)
     AFS_GLOCK();
 
     afs_InitStats();
-    rx_SetBusyChannelError(RX_CALL_TIMEOUT);
+    rx_SetBusyChannelError(1);  /* turn on busy call error reporting */
     rx_Init(htons(7001));
 
     AFS_STATCNT(afs_ResourceInit);
index 918be8c1ab70e6e126c8fb43d31d6a3c93afc40b..28e0d76e07d40de6320f8b399d30774f15b603f1 100644 (file)
@@ -181,12 +181,12 @@ 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.
+ * rxi_busyChannelError is a boolean.  It indicates whether or not RX_CALL_BUSY
+ * errors should be reported 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;
 
@@ -775,17 +775,17 @@ rx_rto_setPeerTimeoutSecs(struct rx_peer *peer, int secs) {
 }
 
 /**
- * Sets the error generated when a busy call channel is detected.
+ * Enables or disables the busy call channel error (RX_CALL_BUSY).
  *
- * @param[in] error The error to return for a call on a busy channel.
+ * @param[in] onoff Non-zero to enable busy call channel errors.
  *
  * @pre Neither rx_Init nor rx_InitHost have been called yet
  */
 void
-rx_SetBusyChannelError(afs_int32 error)
+rx_SetBusyChannelError(afs_int32 onoff)
 {
     osi_Assert(rxinit_status != 0);
-    rxi_busyChannelError = error;
+    rxi_busyChannelError = onoff ? 1 : 0;
 }
 
 /* called with unincremented nRequestsRunning to see if it is OK to start
@@ -1102,6 +1102,7 @@ void
 rx_SetConnIdleDeadTime(struct rx_connection *conn, int seconds)
 {
     conn->idleDeadTime = seconds;
+    conn->idleDeadDetection = (seconds ? 1 : 0);
     rxi_CheckConnTimeouts(conn);
 }
 
@@ -2979,8 +2980,8 @@ rxi_FindConnection(osi_socket socket, afs_uint32 host,
        conn->nSpecific = 0;
        conn->specific = NULL;
        rx_SetConnDeadTime(conn, service->connDeadTime);
-       rx_SetConnIdleDeadTime(conn, service->idleDeadTime);
-       rx_SetServerConnIdleDeadErr(conn, service->idleDeadErr);
+       conn->idleDeadTime = service->idleDeadTime;
+       conn->idleDeadDetection = service->idleDeadErr ? 1 : 0;
        for (i = 0; i < RX_MAXCALLS; i++) {
            conn->twind[i] = rx_initSendWindow;
            conn->rwind[i] = rx_initReceiveWindow;
@@ -3080,7 +3081,7 @@ rxi_CheckBusy(struct rx_call *call)
         * rxi_busyChannelError so the application can retry the request,
         * presumably on a less-busy call channel. */
 
-       rxi_CallError(call, rxi_busyChannelError);
+       rxi_CallError(call, RX_CALL_BUSY);
     }
 }
 
@@ -5118,18 +5119,27 @@ struct rx_packet *
 rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
                  int istack, int force)
 {
-    afs_int32 error;
+    afs_int32 error, cerror;
     struct clock when, now;
 
     if (!call->error)
        return packet;
 
+    switch (call->error) {
+    case RX_CALL_IDLE:
+    case RX_CALL_BUSY:
+        cerror = RX_CALL_TIMEOUT;
+        break;
+    default:
+        cerror = call->error;
+    }
+
     /* Clients should never delay abort messages */
     if (rx_IsClientConn(call->conn))
        force = 1;
 
-    if (call->abortCode != call->error) {
-       call->abortCode = call->error;
+    if (call->abortCode != cerror) {
+       call->abortCode = cerror;
        call->abortCount = 0;
     }
 
@@ -5139,7 +5149,7 @@ rxi_SendCallAbort(struct rx_call *call, struct rx_packet *packet,
            rxevent_Cancel(call->delayedAbortEvent, call,
                           RX_CALL_REFCOUNT_ABORT);
        }
-       error = htonl(call->error);
+       error = htonl(cerror);
        call->abortCount++;
        packet =
            rxi_SendSpecial(call, call->conn, packet, RX_PACKET_TYPE_ABORT,
@@ -6268,6 +6278,7 @@ rxi_CheckCall(struct rx_call *call)
     afs_uint32 fudgeFactor;
     int cerror = 0;
     int newmtu = 0;
+    int idle_timeout = 0;
 
 #ifdef AFS_GLOBAL_RXLOCK_KERNEL
     if (call->flags & RX_CALL_TQ_BUSY) {
@@ -6346,7 +6357,7 @@ rxi_CheckCall(struct rx_call *call)
         * attached process can die reasonably gracefully. */
     }
 
-    if (conn->idleDeadTime) {
+    if (conn->idleDeadDetection && conn->idleDeadTime) {
        idleDeadTime = conn->idleDeadTime + fudgeFactor;
     }
 
@@ -6359,10 +6370,11 @@ rxi_CheckCall(struct rx_call *call)
            goto mtuout;
        }
     }
-    if (call->lastSendData && idleDeadTime && (conn->idleDeadErr != 0)
+    if (call->lastSendData && idleDeadTime
         && ((call->lastSendData + idleDeadTime) < now)) {
        if (call->state == RX_STATE_ACTIVE) {
-           cerror = conn->idleDeadErr;
+           cerror = conn->service ? conn->service->idleDeadErr : RX_CALL_IDLE;
+            idle_timeout = 1;
            goto mtuout;
        }
     }
@@ -6380,8 +6392,8 @@ rxi_CheckCall(struct rx_call *call)
     }
     return 0;
 mtuout:
-    if (conn->msgsizeRetryErr && cerror != RX_CALL_TIMEOUT
-       && call->lastReceiveTime) {
+    if (conn->msgsizeRetryErr && cerror != RX_CALL_TIMEOUT && !idle_timeout &&
+        call->lastReceiveTime) {
        int oldMTU = conn->peer->ifMTU;
 
        /* if we thought we could send more, perhaps things got worse */
@@ -6595,7 +6607,7 @@ rxi_GrowMTUEvent(struct rxevent *event, void *arg1, void *dummy)
      */
     if ((conn->peer->maxPacketSize != 0) &&
        (conn->peer->natMTU < RX_MAX_PACKET_SIZE) &&
-       (conn->idleDeadErr))
+       conn->idleDeadDetection)
        (void)rxi_SendAck(call, NULL, 0, RX_ACK_MTU, 0);
     rxi_ScheduleGrowMTUEvent(call, 0);
     MUTEX_EXIT(&call->lock);
index ba692a7bccb0f1ca021cc7703d30da19e519ba34..dbee52ff54fdc9afb08ba6de34b074020355a2c8 100644 (file)
@@ -150,7 +150,10 @@ rx_IsLoopbackAddr(afs_uint32 addr)
 /* Define procedure to set service dead time */
 #define rx_SetIdleDeadTime(service,time) ((service)->idleDeadTime = (time))
 
-/* Define error to return in server connections when failing to answer */
+/*
+ * Define error to return in server connections when failing to answer.
+ * (server only) For example, AFS viced sends VNOSERVICE.
+ */
 #define rx_SetServerIdleDeadErr(service,err) ((service)->idleDeadErr = (err))
 
 /* Define procedures for getting and setting before and after execute-request procs */
@@ -172,8 +175,6 @@ rx_IsLoopbackAddr(afs_uint32 addr)
 /* Enable or disable asymmetric client checking for a service */
 #define rx_SetCheckReach(service, x) ((service)->checkReach = (x))
 
-#define rx_SetServerConnIdleDeadErr(conn,err) ((conn)->idleDeadErr = (err))
-
 /* Set the overload threshold and the overload error */
 #define rx_SetBusyThreshold(threshold, code) (rx_BusyThreshold=(threshold),rx_BusyError=(code))
 
@@ -280,7 +281,7 @@ struct rx_connection {
     u_short idleDeadTime;      /* max time a call can be idle (no data) */
     u_char ackRate;            /* how many packets between ack requests */
     u_char makeCallWaiters;    /* how many rx_NewCalls are waiting */
-    afs_int32 idleDeadErr;
+    u_char idleDeadDetection;   /* detect idle dead timeouts? */
     afs_int32 secondsUntilNatPing;     /* how often to ping conn */
     struct rxevent *natKeepAliveEvent; /* Scheduled to keep connection open */
     afs_int32 msgsizeRetryErr;
@@ -718,34 +719,57 @@ struct rx_ackPacket {
 #define        RX_CHECKREACH_TIMEOUT   2       /* Number of seconds before another ping is generated */
 #define        RX_CHECKREACH_TTL       60      /* Re-check reachability this often */
 
-/* RX error codes.  RX uses error codes from -1 to -64.  Rxgen may use other error codes < -64; user programs are expected to return positive error codes */
+/*
+ * RX error codes.  RX uses error codes from -1 to -64 and -100.
+ * Rxgen uses other error codes < -64 (see src/rxgen/rpc_errors.h);
+ * user programs are expected to return positive error codes
+ */
 
 /* Something bad happened to the connection; temporary loss of communication */
 #define        RX_CALL_DEAD                (-1)
 
-/* An invalid operation, such as a client attempting to send data after having received the beginning of a reply from the server */
+/*
+ * An invalid operation, such as a client attempting to send data
+ * after having received the beginning of a reply from the server.
+ */
 #define        RX_INVALID_OPERATION        (-2)
 
 /* An optional timeout per call may be specified */
 #define        RX_CALL_TIMEOUT             (-3)
 
-/* End of data on a read */
+/* End of data on a read.  Not currently in use. */
 #define        RX_EOF                      (-4)
 
-/* Some sort of low-level protocol error */
+/* Some sort of low-level protocol error. */
 #define        RX_PROTOCOL_ERROR           (-5)
 
-/* Generic user abort code; used when no more specific error code needs to be communicated.  For example, multi rx clients use this code to abort a multi rx call */
+/*
+ * Generic user abort code; used when no more specific error code needs to be
+ * communicated.  For example, multi rx clients use this code to abort a multi-
+ * rx call.
+ */
 #define        RX_USER_ABORT               (-6)
 
-/* Port already in use (from rx_Init) */
+/* Port already in use (from rx_Init).  This error is never sent on the wire. */
 #define RX_ADDRINUSE               (-7)
 
 /* EMSGSIZE returned from network.  Packet too big, must fragment */
 #define RX_MSGSIZE                 (-8)
 
+/*
+ * Idle dead timeout error.  This error is never sent on the wire.
+ * rxi_SendCallAbort() translates RX_CALL_IDLE to RX_CALL_TIMEOUT.
+ */
+#define RX_CALL_IDLE                (-9)
+
+/*
+ * Busy call channel error.  This error is never sent on the wire.
+ * rxi_SendCallAbort() translates RX_CALL_BUSY to RX_CALL_TIMEOUT.
+ */
+#define RX_CALL_BUSY                (-10)
+
 /* transient failure detected ( possibly the server is restarting ) */
-/* this shud be equal to VRESTARTING ( util/errors.h ) for old clients to work */
+/* this should be equal to VRESTARTING ( util/errors.h ) for old clients to work */
 #define RX_RESTARTING              (-100)
 
 typedef enum {
index 647e626f6d0fb5e097f97a61d70cdafa83657e4a..331511605067301bc1fc98d8c644ef713bea54c9 100644 (file)
@@ -25,7 +25,7 @@ extern void rx_rto_setPeerTimeoutSecs(struct rx_peer *, int secs);
 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);
+extern void rx_SetBusyChannelError(afs_int32 onoff);
 #ifdef AFS_NT40_ENV
 extern void rx_DebugOnOff(int on);
 extern void rx_StatsOnOff(int on);