Windows: Fail RX_INVALID_OPERATION errors
authorJeffrey Altman <jaltman@your-file-system.com>
Sat, 24 Nov 2012 19:36:46 +0000 (14:36 -0500)
committerJeffrey Altman <jaltman@your-file-system.com>
Thu, 29 Nov 2012 23:48:42 +0000 (15:48 -0800)
RX_INVALID_OPERATION errors were not resulting in an eventual
failure and the RPC was being repeated indefinitely.  There were
three subtle problems:

 1. RX_INVALID_OPERATION was being processed by cm_Analyze()
    resulting in a retry in all cases.  Even those where no
    connp was passed in as NULL.  connp == NULL implies that
    no server could be obtained so the RPC was not issued on
    this pass.  As a result there should be no retry.

 2. RX_INVALID_OPERATION was mapped to CM_ERROR_UNKNOWN which
    is not an error that is reported to the AFS redirector.

 3. RDR_BkgFetch was setting CM_REQ_NORETRY and permitting
    the retries to be handled by the cm_daemon threads.  However,
    CM_ERROR_UNKNOWN was not treated as a fatal error by cm_Daemon.

Address the failures in the following ways:

 A. cm_Analyze no longer retries calls which did not take place.

 B. Create a new CM_ERROR_INVAL_NET_RESP error for RX_INVALID_OPERATION
    which is translated to the Win32 STATUS_INVALID_NETWORK_RESPONSE
    error.  This is now returned to the AFS redirector and treated
    as a fatal error.

 C. RDR_BkgFetch no longer queues tasks to cm_Daemon with the
    CM_REQ_NORETRY flag set.

Change-Id: I1eba0e83fbbe5726f43f667ddb67ced8c011853d
Reviewed-on: http://gerrit.openafs.org/8510
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Jeffrey Altman <jaltman@your-file-system.com>
Tested-by: Jeffrey Altman <jaltman@your-file-system.com>

src/WINNT/afsd/cm_buf.c
src/WINNT/afsd/cm_conn.c
src/WINNT/afsd/cm_dcache.c
src/WINNT/afsd/cm_error.h
src/WINNT/afsd/cm_utils.c
src/WINNT/afsd/smb.c
src/WINNT/afsrdr/user/RDRFunction.c

index 04573d0..beeb303 100644 (file)
@@ -871,7 +871,8 @@ afs_uint32 buf_CleanLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
         */
        if (code == CM_ERROR_NOSUCHFILE || code == CM_ERROR_BADFD || code == CM_ERROR_NOACCESS ||
             code == CM_ERROR_QUOTA || code == CM_ERROR_SPACE || code == CM_ERROR_TOOBIG ||
-            code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH || code == EIO){
+            code == CM_ERROR_READONLY || code == CM_ERROR_NOSUCHPATH || code == EIO ||
+            code == CM_ERROR_INVAL || code == CM_ERROR_INVAL_NET_RESP || code == CM_ERROR_UNKNOWN){
            _InterlockedAnd(&bp->flags, ~CM_BUF_DIRTY);
            _InterlockedOr(&bp->flags, CM_BUF_ERROR);
             bp->dirty_length = 0;
@@ -894,10 +895,14 @@ afs_uint32 buf_CleanLocked(cm_scache_t *scp, cm_buf_t *bp, cm_req_t *reqp,
        if (reqp->flags & CM_REQ_NORETRY)
            break;
 
-        /* Ditto if the hardDeadTimeout or idleTimeout was reached */
+        /*
+         * Ditto if the hardDeadTimeout or idleTimeout was reached
+         * Or a fatal error is received.
+         */
         if (code == CM_ERROR_TIMEDOUT || code == CM_ERROR_ALLDOWN ||
             code == CM_ERROR_ALLBUSY || code == CM_ERROR_ALLOFFLINE ||
-            code == CM_ERROR_CLOCKSKEW) {
+            code == CM_ERROR_CLOCKSKEW || code == CM_ERROR_INVAL_NET_RESP ||
+            code == CM_ERROR_INVAL || code == CM_ERROR_UNKNOWN || code == EIO) {
             break;
         }
     }
@@ -2244,6 +2249,7 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
 
                 switch (code) {
                 case CM_ERROR_NOSUCHFILE:
+                case CM_ERROR_INVAL:
                 case CM_ERROR_BADFD:
                 case CM_ERROR_NOACCESS:
                 case CM_ERROR_QUOTA:
@@ -2252,6 +2258,8 @@ long buf_CleanVnode(struct cm_scache *scp, cm_user_t *userp, cm_req_t *reqp)
                 case CM_ERROR_READONLY:
                 case CM_ERROR_NOSUCHPATH:
                 case EIO:
+                case CM_ERROR_INVAL_NET_RESP:
+                case CM_ERROR_UNKNOWN:
                     /*
                      * Apply the previous fatal error to this buffer.
                      * Do not waste the time attempting to store to
index 0df8b37..2ccbe42 100644 (file)
@@ -314,12 +314,12 @@ cm_Analyze(cm_conn_t *connp,
     cm_volume_t * volp = NULL;
     cm_vol_state_t *statep = NULL;
     cm_scache_t * scp = NULL;
-    afs_uint32 replicated;
+    afs_uint32 replicated = 0;
     int retry = 0;
     int free_svr_list = 0;
-    int dead_session;
+    int dead_session = (userp->cellInfop == NULL);
     long timeUsed, timeLeft;
-    long code;
+    long code = 0;
     char addr[16]="unknown";
     int forcing_new = 0;
     int location_updated = 0;
@@ -332,7 +332,6 @@ cm_Analyze(cm_conn_t *connp,
 
     /* no locking required, since connp->serverp never changes after
      * creation */
-    dead_session = (userp->cellInfop == NULL);
     if (connp)
         serverp = connp->serverp;
 
@@ -1132,9 +1131,10 @@ cm_Analyze(cm_conn_t *connp,
                 forcing_new = 1;
                 cm_ForceNewConnections(serverp);
             }
+
+            if ( timeLeft > 2 )
+                retry = 1;
         }
-        if ( timeLeft > 2 )
-            retry = 1;
     }
     else if (errorCode == RXKADEXPIRED) {
         osi_Log1(afsd_logp, "cm_Analyze: rxkad error code 0x%x (RXKADEXPIRED)",
@@ -1320,10 +1320,9 @@ cm_Analyze(cm_conn_t *connp,
     }
 
     /* If not allowed to retry, don't */
-    if (!forcing_new && (reqp->flags & CM_REQ_NORETRY) &&
-        (errorCode != RX_MSGSIZE && errorCode != RX_CALL_BUSY))
-       retry = 0;
-    else if (retry && dead_session)
+    if (dead_session ||
+        !forcing_new && (reqp->flags & CM_REQ_NORETRY) &&
+        !(errorCode > -64 && errorCode <= RX_INVALID_OPERATION))
         retry = 0;
 
     /* drop this on the way out */
index cbeb035..97f5cd7 100644 (file)
@@ -1535,6 +1535,8 @@ void cm_ReleaseBIOD(cm_bulkIO_t *biop, int isStore, long code, int scp_locked)
                     case CM_ERROR_READONLY:
                     case CM_ERROR_NOSUCHPATH:
                     case EIO:
+                    case CM_ERROR_INVAL_NET_RESP:
+                    case CM_ERROR_UNKNOWN:
                         /*
                          * Apply the fatal error to this buffer.
                          */
index 6715552..e13a2d2 100644 (file)
@@ -77,6 +77,7 @@
 #define CM_ERROR_RPC_MOREDATA          (CM_ERROR_BASE+63)
 #define CM_ERROR_BUFFER_OVERFLOW        (CM_ERROR_BASE+64)
 #define CM_ERROR_EMPTY                  (CM_ERROR_BASE+65)
+#define CM_ERROR_INVAL_NET_RESP         (CM_ERROR_BASE+66)
 
 #endif /* OPENAFS_WINNT_AFSD_CM_ERROR_H */
 
index de8f52b..109c25d 100644 (file)
@@ -219,6 +219,8 @@ long cm_MapRPCError(long error, cm_req_t *reqp)
         error = CM_ERROR_RETRY;
     else if (error == RX_CALL_IDLE)
         error = EIO;
+    else if (error == RX_INVALID_OPERATION)
+        error = CM_ERROR_INVAL_NET_RESP;
     else if (error < 0)
         error = CM_ERROR_UNKNOWN;
     else if (error == EINVAL)
@@ -292,6 +294,8 @@ long cm_MapRPCErrorRmdir(long error, cm_req_t *reqp)
         error = CM_ERROR_ALLOFFLINE;
     else if (error == VBUSY || error == VRESTARTING)
         error = CM_ERROR_ALLBUSY;
+    else if (error == RX_INVALID_OPERATION)
+        error = CM_ERROR_INVAL_NET_RESP;
     else if (error < 0)
         error = CM_ERROR_UNKNOWN;
     else if (error == EROFS)
@@ -337,6 +341,8 @@ long cm_MapVLRPCError(long error, cm_req_t *reqp)
         error == RX_MSGSIZE ||
         error == VNOSERVICE)
         error = CM_ERROR_RETRY;
+    else if (error == RX_INVALID_OPERATION)
+        error = CM_ERROR_INVAL_NET_RESP;
     else if (error == RX_RESTARTING)
         error = CM_ERROR_ALLBUSY;
     else if (error < 0)
index a217121..3b3ad0c 100644 (file)
@@ -3142,6 +3142,9 @@ void smb_MapNTError(long code, unsigned long *NTStatusp, afs_uint32 redir)
     else if (code == CM_ERROR_INVAL) {
         NTStatus = 0xC000000DL;        /* Invalid parameter */
     }
+    else if (code == CM_ERROR_INVAL_NET_RESP) {
+        NTStatus = 0xC00000C3L; /* Invalid network response */
+    }
     else if (code == CM_ERROR_BADFD) {
         NTStatus = 0xC0000008L;        /* Invalid handle */
     }
index 82d8da2..1b56c59 100644 (file)
@@ -3442,6 +3442,8 @@ RDR_BkgFetch(cm_scache_t *scp, afs_uint32 p1, afs_uint32 p2, afs_uint32 p3, afs_
             case CM_ERROR_QUOTA:
             case CM_ERROR_LOCK_CONFLICT:
             case EIO:
+            case CM_ERROR_INVAL_NET_RESP:
+            case CM_ERROR_UNKNOWN:
                 /*
                  * these are fatal errors.  deliver what we can
                  * and halt.
@@ -3715,10 +3717,12 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
                 buf_Release(bufp);
 
             if (QueueLength) {
+                req.flags &= ~CM_REQ_NORETRY;
                 cm_QueueBKGRequest(scp, RDR_BkgFetch, QueueOffset.LowPart, QueueOffset.HighPart,
                                    QueueLength, 0, userp, &req);
                 osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",
                          QueueOffset.HighPart, QueueOffset.LowPart, QueueLength);
+                req.flags |= CM_REQ_NORETRY;
             }
         } else {
             /* No error from buf_Get() can be fatal */
@@ -3730,6 +3734,7 @@ RDR_RequestFileExtentsAsync( IN cm_user_t *userp,
     if (BeginOffset.QuadPart != EndOffset.QuadPart) {
         afs_uint32 length = (afs_uint32)(EndOffset.QuadPart - BeginOffset.QuadPart);
 
+        req.flags &= ~CM_REQ_NORETRY;
         cm_QueueBKGRequest(scp, RDR_BkgFetch, BeginOffset.LowPart, BeginOffset.HighPart,
                            length, 0, userp, &req);
         osi_Log3(afsd_logp, "RDR_RequestFileExtentsAsync Queued a Background Fetch offset 0x%x:%x length 0x%x",