]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afs: discard cached state when we are unsure of validity
authorDerrick Brashear <shadow@dementix.org>
Wed, 4 Jan 2012 20:04:41 +0000 (15:04 -0500)
committerDerrick Brashear <shadow@dementix.org>
Mon, 9 Jan 2012 02:16:13 +0000 (18:16 -0800)
in the event we got a network error, we don't know if the server
completed (or will complete) our operation. we can assume nothing.
a more complicated version of this could attempt to verify that the
state is what we expect it to be, but in extended callbacks universe
this is potentially easier to solve anyway. for now, return the
error to the caller, and mark the vcache unstat'd.

(cherry picked from commit c2fc7e0f66621fc97f5b4dc389d379260638315c)

Change-Id: Ic38cf16e47664e6f36ad614735b42d3f4e5a6ce2
Reviewed-on: http://gerrit.openafs.org/6520
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
src/afs/afs_analyze.c
src/afs/afs_stats.h

index 33c962758f137a346a30c83875355a29c03aa5f0..1d1b7c40b3774265c2c3f61b5a21b71572400561 100644 (file)
@@ -273,6 +273,61 @@ afs_BlackListOnce(struct vrequest *areq, struct VenusFid *afid,
     return serversleft;
 }
 
+/*------------------------------------------------------------------------
+ * afs_ClearStatus
+ *
+ * Description:
+ *     Analyze the outcome of an RPC operation, taking whatever support
+ *     actions are necessary.
+ *
+ * Arguments:
+ *     afid  : The FID of the file involved in the action.  This argument
+ *             may be null if none was involved.
+ *      op    : which RPC we are analyzing.
+ *      avp   : A pointer to the struct volume, if we already have one.
+ *
+ * Returns:
+ *     Non-zero value if the related RPC operation can be retried,
+ *     zero otherwise.
+ *
+ * Environment:
+ *     This routine is called when we got a network error,
+ *      and discards state if the operation was a data-mutating
+ *      operation.
+ *------------------------------------------------------------------------*/
+static int
+afs_ClearStatus(struct VenusFid *afid, int op, struct volume *avp)
+{
+    struct volume *tvp = NULL;
+
+    /* if it's not a write op, we have nothing to veto and shouldn't clear. */
+    if (!AFS_STATS_FS_RPCIDXES_ISWRITE(op)) {
+       return 1;
+    }
+
+    if (avp)
+       tvp = avp;
+    else if (afid)
+       tvp = afs_FindVolume(afid, READ_LOCK);
+
+    /* don't assume just discarding will fix if no cached volume */
+    if (tvp) {
+       struct vcache *tvc;
+       ObtainReadLock(&afs_xvcache);
+       if ((tvc = afs_FindVCache(afid, 0, 0))) {
+           ReleaseReadLock(&afs_xvcache);
+           tvc->f.states &= ~(CStatd | CUnique);
+           afs_PutVCache(tvc);
+       } else {
+           ReleaseReadLock(&afs_xvcache);
+       }
+    }
+    if (!avp)
+       afs_PutVolume(tvp, READ_LOCK);
+
+    /* not retriable: we may have raced ourselves */
+    return 0;
+}
 
 /*------------------------------------------------------------------------
  * EXPORTED afs_Analyze
@@ -465,8 +520,12 @@ afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
            else {
                if (acode == RX_MSGSIZE)
                    shouldRetry = 1;
-               else
+               else {
                    areq->networkError = 1;
+                   /* do not promote to shouldRetry if not already */
+                   if (afs_ClearStatus(afid, op, NULL) == 0)
+                       shouldRetry = 0;
+               }
            }
        }
        return shouldRetry;
@@ -516,14 +575,17 @@ afs_Analyze(struct afs_conn *aconn, struct rx_connection *rxconn,
            serversleft = afs_BlackListOnce(areq, afid, tsp);
            if (afid)
                tvp = afs_FindVolume(afid, READ_LOCK);
-           if (!afid || !tvp || (tvp->states & VRO))
-               areq->idleError++;
            if ((serversleft == 0) && tvp &&
                ((tvp->states & VRO) || (tvp->states & VBackup))) {
                shouldRetry = 0;
            } else {
                shouldRetry = 1;
            }
+           if (!afid || !tvp || (tvp->states & VRO))
+               areq->idleError++;
+           else if (afs_ClearStatus(afid, op, tvp) == 0)
+               shouldRetry = 0;
+
            if (tvp)
                afs_PutVolume(tvp, READ_LOCK);
            /* By doing this, we avoid ever marking a server down
index 92a1ba8a47e039a9bc38beedbf912dd2f160aa99..e02be19520ad52941b744087c59db8ec452ee170 100644 (file)
@@ -867,6 +867,8 @@ struct afs_stats_CMPerf {
 
 #define AFS_STATS_NUM_FS_RPC_OPS               29
 
+#define AFS_STATS_FS_RPCIDXES_ISWRITE(X)        (((X > AFS_STATS_FS_RPCIDX_FETCHSTATUS) && (X < AFS_STATS_FS_RPCIDX_GETSTATISTICS)) || (X == AFS_STATS_FS_RPCIDX_SETVOLUMESTATUS))
+
 #define AFS_STATS_FS_XFERIDX_FETCHDATA          0
 #define AFS_STATS_FS_XFERIDX_STOREDATA          1