windows-rx-idle-timeout-20080428
authorJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 28 Apr 2008 16:04:38 +0000 (16:04 +0000)
committerJeffrey Altman <jaltman@secure-endpoints.com>
Mon, 28 Apr 2008 16:04:38 +0000 (16:04 +0000)
LICENSE MIT

Add "IdleDeadTimeout" registry value and call rx_SetConnIdleDeadTime()
with it when creating new rx connections.   This forces the Rx stack
to return RX_CALL_TIMEOUT if the file server has returned VBUSY for
longer than the IdleDeadTimeout.

When RX_CALL_TIMEOUT is received, the cache manager will now attempt to
find another server for the object that might be less busy.

src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_conn.h

index 130deda..e81739d 100644 (file)
@@ -26,6 +26,7 @@ osi_rwlock_t cm_connLock;
 DWORD RDRtimeout = CM_CONN_DEFAULTRDRTIMEOUT;
 unsigned short ConnDeadtimeout = CM_CONN_CONNDEADTIME;
 unsigned short HardDeadtimeout = CM_CONN_HARDDEADTIME;
+unsigned short IdleDeadtimeout = CM_CONN_IDLEDEADTIME;
 
 #define LANMAN_WKS_PARAM_KEY "SYSTEM\\CurrentControlSet\\Services\\lanmanworkstation\\parameters"
 #define LANMAN_WKS_SESSION_TIMEOUT "SessTimeout"
@@ -84,7 +85,15 @@ void cm_InitConn(void)
            if (code == ERROR_SUCCESS)
                 HardDeadtimeout = (unsigned short)dwValue;
            afsi_log("HardDeadTimeout is %d", HardDeadtimeout);
-           RegCloseKey(parmKey);
+
+           dummyLen = sizeof(DWORD);
+           code = RegQueryValueEx(parmKey, "IdleDeadTimeout", NULL, NULL,
+                                   (BYTE *) &dwValue, &dummyLen);
+           if (code == ERROR_SUCCESS)
+                IdleDeadtimeout = (unsigned short)dwValue;
+           afsi_log("IdleDeadTimeout is %d", IdleDeadtimeout);
+
+            RegCloseKey(parmKey);
        }
 
        afsi_log("lanmanworkstation : SessTimeout %u", RDRtimeout);
@@ -549,9 +558,11 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
 
        LogEvent(EVENTLOG_WARNING_TYPE, MSG_RX_HARD_DEAD_TIME_EXCEEDED, addr);
          
-        retry = 0;
         osi_Log1(afsd_logp, "cm_Analyze: hardDeadTime exceeded addr[%s]",
                 osi_LogSaveString(afsd_logp,addr));
+        reqp->tokenIdleErrorServp = serverp;
+        reqp->idleError++;
+        retry = 1;
     }
     else if (errorCode >= -64 && errorCode < 0) {
         /* mark server as down */
@@ -585,7 +596,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                 retry = 1;
         }
     } else if (errorCode >= ERROR_TABLE_BASE_RXK && errorCode < ERROR_TABLE_BASE_RXK + 256) {
-        reqp->tokenErrorServp = serverp;
+        reqp->tokenIdleErrorServp = serverp;
         reqp->tokenError = errorCode;
         retry = 1;
     } else if (errorCode == VICECONNBAD || errorCode == VICETOKENDEAD) {
@@ -767,15 +778,15 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
     lock_ObtainRead(&cm_serverLock);
     for (tsrp = serversp; tsrp; tsrp=tsrp->next) {
         tsp = tsrp->server;
-        if (reqp->tokenErrorServp) {
+        if (reqp->tokenIdleErrorServp) {
             /* 
              * search the list until we find the server
              * that failed last time.  When we find it
              * clear the error, skip it and try the one
              * in the list.
              */
-            if (tsp == reqp->tokenErrorServp)
-                reqp->tokenErrorServp = NULL;
+            if (tsp == reqp->tokenIdleErrorServp)
+                reqp->tokenIdleErrorServp = NULL;
             continue;
         }
         cm_GetServerNoLock(tsp);
@@ -822,7 +833,8 @@ long cm_ConnByMServers(cm_serverRef_t *serversp, cm_user_t *usersp,
 
     if (firstError == 0) {
         if (allDown) 
-            firstError = (reqp->tokenError ? reqp->tokenError : CM_ERROR_ALLDOWN);
+            firstError = (reqp->tokenError ? reqp->tokenError : 
+                          (reqp->idleError ? RX_CALL_TIMEOUT : CM_ERROR_ALLDOWN));
         else if (allBusy) 
             firstError = CM_ERROR_ALLBUSY;
        else if (allOffline || (someBusy && someOffline))
@@ -906,6 +918,7 @@ static void cm_NewRXConnection(cm_conn_t *tcp, cm_ucell_t *ucellp,
                                   secIndex);
     rx_SetConnDeadTime(tcp->callp, ConnDeadtimeout);
     rx_SetConnHardDeadTime(tcp->callp, HardDeadtimeout);
+    rx_SetConnIdleDeadTime(tcp->callp, IdleDeadtimeout);
     tcp->ucgen = ucellp->gen;
     if (secObjp)
         rxs_Release(secObjp);   /* Decrement the initial refCount */
index ea85580..6220592 100644 (file)
@@ -13,6 +13,7 @@
 #define        CM_CONN_DEFAULTRDRTIMEOUT       45
 #define CM_CONN_CONNDEADTIME            0
 #define CM_CONN_HARDDEADTIME             0
+#define CM_CONN_IDLEDEADTIME            30
 
 extern unsigned short ConnDeadtimeout;
 extern unsigned short HardDeadtimeout;
@@ -42,8 +43,9 @@ typedef struct cm_req {
        int rpcError;                   /* RPC error code */
        int volumeError;                /* volume error code */
        int accessError;                /* access error code */
-        struct cm_server * tokenErrorServp;  /* server that reported a token error other than expired */
+        struct cm_server * tokenIdleErrorServp;  /* server that reported a token/idle error other than expired */
         int tokenError;
+        int idleError;
        afs_uint32 flags;
         char * tidPathp;
         char * relPathp;