From: Derrick Brashear Date: Wed, 4 Jan 2012 20:04:41 +0000 (-0500) Subject: afs: discard cached state when we are unsure of validity X-Git-Tag: openafs-stable-1_8_0pre1~2853 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=9620b67c138797e815621f0254cf15d0de504121 afs: discard cached state when we are unsure of validity 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. Change-Id: Iafb67f24b89d78b8236660d047da12fce1dd6061 Reviewed-on: http://gerrit.openafs.org/6510 Reviewed-by: Derrick Brashear Tested-by: Derrick Brashear --- diff --git a/src/afs/afs_analyze.c b/src/afs/afs_analyze.c index 47fdff3..0023d5b 100644 --- a/src/afs/afs_analyze.c +++ b/src/afs/afs_analyze.c @@ -271,6 +271,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 @@ -463,8 +518,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; @@ -514,14 +573,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 diff --git a/src/afs/afs_stats.h b/src/afs/afs_stats.h index 60f2e93..37b9aad 100644 --- a/src/afs/afs_stats.h +++ b/src/afs/afs_stats.h @@ -869,6 +869,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