Windows: avoid recursive cm_CheckOfflineVolume
[openafs.git] / src / WINNT / afsd / cm_conn.c
index 0f644fc..5baba3f 100644 (file)
@@ -7,7 +7,10 @@
  * directory or online at http://www.openafs.org/dl/license10.html
  */
 
+#include <afsconfig.h>
 #include <afs/param.h>
+#include <roken.h>
+
 #include <afs/stds.h>
 
 #include <windows.h>
@@ -348,7 +351,11 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                                       CM_GETVOL_FLAG_NO_LRU_UPDATE, 
                                       &volp);
             if (code == 0) {
-                if (timeLeft > 7) {
+                /*
+                 * Do not perform a cm_CheckOfflineVolume() if cm_Analyze()
+                 * was called by cm_CheckOfflineVolumeState().
+                 */
+                if (!(reqp->flags & CM_REQ_OFFLINE_VOL_CHK) && timeLeft > 7) {
                     thrd_Sleep(5000);
 
                     /* cm_CheckOfflineVolume() resets the serverRef state */
@@ -525,7 +532,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
         switch ( errorCode ) {
         case VNOVOL:
            msgID = MSG_SERVER_REPORTS_VNOVOL;
-            format = "Server %s reported volume %d in cell %s as not attached (does not exist).";
+            format = "Server %s reported volume %d in cell %s as not attached (may have been moved or deleted).";
             break;
         case VMOVED:
            msgID = MSG_SERVER_REPORTS_VMOVED;
@@ -551,7 +558,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
 
         if (fidp) { /* File Server query */
             if (serverp) {
-                /* Log server being offline for this volume */
+                /* Log server being unavailable for this volume */
                 sprintf(addr, "%d.%d.%d.%d",
                          ((serverp->addr.sin_addr.s_addr & 0xff)),
                          ((serverp->addr.sin_addr.s_addr & 0xff00)>> 8),
@@ -619,7 +626,7 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                      ((tsrp->server->addr.sin_addr.s_addr & 0xff0000)>> 16),
                      ((tsrp->server->addr.sin_addr.s_addr & 0xff000000)>> 24));
 
-            if (tsrp->server == serverp) {
+            if (cm_ServerEqual(tsrp->server, serverp)) {
                 /* REDIRECT */
                 if (errorCode == VMOVED || errorCode == VNOVOL) {
                     osi_Log2(afsd_logp, "volume %d not present on server %s",
@@ -729,20 +736,37 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
          * with a smaller mtu size.
          */
 
-        if (serverp) {
+        if (serverp)
             sprintf(addr, "%d.%d.%d.%d",
                     ((serverp->addr.sin_addr.s_addr & 0xff)),
                     ((serverp->addr.sin_addr.s_addr & 0xff00)>> 8),
                     ((serverp->addr.sin_addr.s_addr & 0xff0000)>> 16),
                     ((serverp->addr.sin_addr.s_addr & 0xff000000)>> 24));
 
-            LogEvent(EVENTLOG_WARNING_TYPE, MSG_RX_MSGSIZE_EXCEEDED, addr);
-            osi_Log1(afsd_logp, "cm_Analyze: Path MTU may have been exceeded addr[%s]",
-                     osi_LogSaveString(afsd_logp,addr));
-        }
+        LogEvent(EVENTLOG_WARNING_TYPE, MSG_RX_MSGSIZE_EXCEEDED, addr);
+        osi_Log1(afsd_logp, "cm_Analyze: Path MTU may have been exceeded addr[%s]",
+                 osi_LogSaveString(afsd_logp,addr));
 
         retry = 1;
     }
+    else if (errorCode == CM_RX_RETRY_BUSY_CALL) {
+        /*
+         * RPC failed because the selected call channel
+         * is currently busy on the server.  Unconditionally
+         * retry the request so an alternate call channel can be used.
+         */
+        if (serverp)
+            sprintf(addr, "%d.%d.%d.%d",
+                    ((serverp->addr.sin_addr.s_addr & 0xff)),
+                    ((serverp->addr.sin_addr.s_addr & 0xff00)>> 8),
+                    ((serverp->addr.sin_addr.s_addr & 0xff0000)>> 16),
+                    ((serverp->addr.sin_addr.s_addr & 0xff000000)>> 24));
+
+        LogEvent(EVENTLOG_WARNING_TYPE, MSG_RX_BUSY_CALL_CHANNEL, addr);
+        osi_Log1(afsd_logp, "cm_Analyze: Retry RPC due to busy call channel addr[%s]",
+                 osi_LogSaveString(afsd_logp,addr));
+        retry = 1;
+    }
     else if (errorCode >= -64 && errorCode < 0) {
         /* mark server as down */
         if (serverp)
@@ -967,7 +991,8 @@ 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))
+    if (!forcing_new && (reqp->flags & CM_REQ_NORETRY) &&
+        (errorCode != RX_MSGSIZE && errorCode != CM_RX_RETRY_BUSY_CALL))
        retry = 0;
     else if (retry && dead_session)
         retry = 0;
@@ -1187,6 +1212,11 @@ static void cm_NewRXConnection(cm_conn_t *tcp, cm_ucell_t *ucellp,
     rx_SetConnIdleDeadTime(tcp->rxconnp, IdleDeadtimeout);
 
     /*
+     * Register the error to be returned on an idle dead timeout
+     */
+    rx_SetServerConnIdleDeadErr(tcp->rxconnp, RX_CALL_DEAD);
+
+    /*
      * Let the Rx library know that we can auto-retry if an
      * RX_MSGSIZE error is returned.
      */