From ded88c8f8d1dc6758344b708d2aa55f3b29651c7 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Sat, 24 Nov 2012 14:36:46 -0500 Subject: [PATCH] Windows: Fail RX_INVALID_OPERATION errors 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 Reviewed-by: Jeffrey Altman Tested-by: Jeffrey Altman --- src/WINNT/afsd/cm_buf.c | 14 +++++++++++--- src/WINNT/afsd/cm_conn.c | 19 +++++++++---------- src/WINNT/afsd/cm_dcache.c | 2 ++ src/WINNT/afsd/cm_error.h | 1 + src/WINNT/afsd/cm_utils.c | 6 ++++++ src/WINNT/afsd/smb.c | 3 +++ src/WINNT/afsrdr/user/RDRFunction.c | 5 +++++ 7 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/WINNT/afsd/cm_buf.c b/src/WINNT/afsd/cm_buf.c index 04573d055..beeb30359 100644 --- a/src/WINNT/afsd/cm_buf.c +++ b/src/WINNT/afsd/cm_buf.c @@ -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 diff --git a/src/WINNT/afsd/cm_conn.c b/src/WINNT/afsd/cm_conn.c index 0df8b372c..2ccbe4280 100644 --- a/src/WINNT/afsd/cm_conn.c +++ b/src/WINNT/afsd/cm_conn.c @@ -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 */ diff --git a/src/WINNT/afsd/cm_dcache.c b/src/WINNT/afsd/cm_dcache.c index cbeb035f9..97f5cd75f 100644 --- a/src/WINNT/afsd/cm_dcache.c +++ b/src/WINNT/afsd/cm_dcache.c @@ -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. */ diff --git a/src/WINNT/afsd/cm_error.h b/src/WINNT/afsd/cm_error.h index 6715552ef..e13a2d2d4 100644 --- a/src/WINNT/afsd/cm_error.h +++ b/src/WINNT/afsd/cm_error.h @@ -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 */ diff --git a/src/WINNT/afsd/cm_utils.c b/src/WINNT/afsd/cm_utils.c index de8f52b1a..109c25da5 100644 --- a/src/WINNT/afsd/cm_utils.c +++ b/src/WINNT/afsd/cm_utils.c @@ -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) diff --git a/src/WINNT/afsd/smb.c b/src/WINNT/afsd/smb.c index a2171214c..3b3ad0cb0 100644 --- a/src/WINNT/afsd/smb.c +++ b/src/WINNT/afsd/smb.c @@ -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 */ } diff --git a/src/WINNT/afsrdr/user/RDRFunction.c b/src/WINNT/afsrdr/user/RDRFunction.c index 82d8da2ac..1b56c5963 100644 --- a/src/WINNT/afsrdr/user/RDRFunction.c +++ b/src/WINNT/afsrdr/user/RDRFunction.c @@ -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", -- 2.39.5