From: Jeffrey Altman Date: Fri, 18 Oct 2013 23:14:00 +0000 (-0400) Subject: Windows: cm_RemoveSCacheFromHashTable scp not found X-Git-Tag: upstream/1.8.0_pre1^2~955 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=05ecdb353a7c960a34133002a388889e9882d946;p=packages%2Fo%2Fopenafs.git Windows: cm_RemoveSCacheFromHashTable scp not found If the cm_scache_t has CM_SCACHEFLAG_INHASH flag set but cannot be found in the CH_SCACHE_HASH(&scp->fid) hash chain then search the entire hash table for the object. At the end of the function we will know that the CM_SCACHEFLAG_INHASH flag is safe to clear. Change-Id: I92bfad98b7d3cdc42b5aa6b8fae24d47557465e7 Reviewed-on: http://gerrit.openafs.org/10352 Tested-by: BuildBot Reviewed-by: Jeffrey Altman --- diff --git a/src/WINNT/afsd/cm_scache.c b/src/WINNT/afsd/cm_scache.c index d93955432..a2432b5fd 100644 --- a/src/WINNT/afsd/cm_scache.c +++ b/src/WINNT/afsd/cm_scache.c @@ -72,28 +72,61 @@ void cm_AdjustScacheLRU(cm_scache_t *scp) } } -/* call with cm_scacheLock write-locked and scp rw held */ -void cm_RemoveSCacheFromHashTable(cm_scache_t *scp) +static int +cm_RemoveSCacheFromHashChain(cm_scache_t *scp, int index) { cm_scache_t **lscpp; cm_scache_t *tscp; - int i; + int found = 0; + + for (lscpp = &cm_data.scacheHashTablep[index], tscp = cm_data.scacheHashTablep[index]; + tscp; + lscpp = &tscp->nextp, tscp = tscp->nextp) { + if (tscp == scp) { + *lscpp = scp->nextp; + scp->nextp = NULL; + found = 1; + break; + } + } + + return found; +} +/* call with cm_scacheLock write-locked and scp rw held */ +void cm_RemoveSCacheFromHashTable(cm_scache_t *scp) +{ lock_AssertWrite(&cm_scacheLock); lock_AssertWrite(&scp->rw); if (scp->flags & CM_SCACHEFLAG_INHASH) { + int h,i; + int found = 0; + /* hash it out first */ - i = CM_SCACHE_HASH(&scp->fid); - for (lscpp = &cm_data.scacheHashTablep[i], tscp = cm_data.scacheHashTablep[i]; - tscp; - lscpp = &tscp->nextp, tscp = tscp->nextp) { - if (tscp == scp) { - *lscpp = scp->nextp; - scp->nextp = NULL; - _InterlockedAnd(&scp->flags, ~CM_SCACHEFLAG_INHASH); - break; + h = CM_SCACHE_HASH(&scp->fid); + found = cm_RemoveSCacheFromHashChain(scp, h); + + if (!found) { + /* + * The CM_SCACHEFLAG_INHASH is set on the cm_scache_t but + * we didn't find the entry in the expected hash chain. + * Did the fid change? + * In any case, we will search the entire hashtable for + * the object. If we don't find it, then we know it is + * safe to remove the flag. + */ + for (i=0; !found && iflags, ~CM_SCACHEFLAG_INHASH); } }