Windows: handle rx busy call channel
[openafs.git] / src / WINNT / afsd / cm_conn.c
index c88ab95..2134a96 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>
@@ -35,6 +38,7 @@ unsigned short NatPingInterval = CM_CONN_NATPINGINTERVAL;
 
 afs_uint32 cryptall = 0;
 afs_uint32 cm_anonvldb = 0;
+afs_uint32 rx_pmtu_discovery = 0;
 
 void cm_PutConn(cm_conn_t *connp)
 {
@@ -458,11 +462,11 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
         switch ( errorCode ) {
         case VBUSY:
            msgID = MSG_SERVER_REPORTS_VBUSY;
-            format = "Server %s reported busy when accessing volume %d.";
+            format = "Server %s reported busy when accessing volume %d in cell %s.";
             break;
         case VRESTARTING:
            msgID = MSG_SERVER_REPORTS_VRESTARTING;
-            format = "Server %s reported restarting when accessing volume %d.";
+            format = "Server %s reported restarting when accessing volume %d in cell %s.";
             break;
         }
 
@@ -474,8 +478,8 @@ cm_Analyze(cm_conn_t *connp, cm_user_t *userp, cm_req_t *reqp,
                    ((serverp->addr.sin_addr.s_addr & 0xff0000)>> 16),
                    ((serverp->addr.sin_addr.s_addr & 0xff000000)>> 24));
 
-           osi_Log2(afsd_logp, format, osi_LogSaveString(afsd_logp,addr), fidp->volume);
-           LogEvent(EVENTLOG_WARNING_TYPE, msgID, addr, fidp->volume);
+           osi_Log3(afsd_logp, format, osi_LogSaveString(afsd_logp,addr), fidp->volume, cellp->name);
+           LogEvent(EVENTLOG_WARNING_TYPE, msgID, addr, fidp->volume, cellp->name);
         }
 
         lock_ObtainWrite(&cm_serverLock);
@@ -524,43 +528,43 @@ 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 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;
-            format = "Server %s reported volume %d as moved.";
+            format = "Server %s reported volume %d in cell %s as moved.";
             break;
         case VOFFLINE:
            msgID = MSG_SERVER_REPORTS_VOFFLINE;
-            format = "Server %s reported volume %d as offline.";
+            format = "Server %s reported volume %d in cell %s as offline.";
             break;
         case VSALVAGE:
            msgID = MSG_SERVER_REPORTS_VSALVAGE;
-            format = "Server %s reported volume %d as needs salvage.";
+            format = "Server %s reported volume %d in cell %s as needs salvage.";
             break;
         case VNOSERVICE:
            msgID = MSG_SERVER_REPORTS_VNOSERVICE;
-            format = "Server %s reported volume %d as not in service.";
+            format = "Server %s reported volume %d in cell %s as not in service.";
             break;
         case VIO:
            msgID = MSG_SERVER_REPORTS_VIO;
-            format = "Server %s reported volume %d as temporarily unaccessible.";
+            format = "Server %s reported volume %d in cell %s as temporarily unaccessible.";
             break;
         }
 
-        if (serverp && fidp) {
-            /* Log server being offline for this volume */
-            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)); 
-
-           osi_Log2(afsd_logp, format, osi_LogSaveString(afsd_logp,addr), fidp->volume);
-           LogEvent(EVENTLOG_WARNING_TYPE, msgID, addr, fidp->volume);
-        }
-
         if (fidp) { /* File Server query */
+            if (serverp) {
+                /* 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),
+                         ((serverp->addr.sin_addr.s_addr & 0xff0000)>> 16),
+                         ((serverp->addr.sin_addr.s_addr & 0xff000000)>> 24));
+
+                osi_Log3(afsd_logp, format, osi_LogSaveString(afsd_logp,addr), fidp->volume, cellp->name);
+                LogEvent(EVENTLOG_WARNING_TYPE, msgID, addr, fidp->volume, cellp->name);
+            }
+
             code = cm_FindVolumeByID(cellp, fidp->volume, userp, reqp,
                                       CM_GETVOL_FLAG_NO_LRU_UPDATE,
                                       &volp);
@@ -618,7 +622,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",
@@ -728,20 +732,36 @@ 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));
 
-        if (timeLeft > 2)
-            retry = 1;
+        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 */
@@ -967,12 +987,12 @@ 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))
+    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;
 
-  out:
     /* drop this on the way out */
     if (connp)
         cm_PutConn(connp);
@@ -1188,10 +1208,17 @@ 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.
      */
-    rx_SetMsgsizeRetryErr(tcp->rxconnp, RX_MSGSIZE);
+    if (rx_pmtu_discovery)
+        rx_SetMsgsizeRetryErr(tcp->rxconnp, RX_MSGSIZE);
+
     /*
      * Attempt to limit NAT pings to the anonymous file server connections.
      * Only file servers implement client callbacks and we only need one ping