From 05ecdb353a7c960a34133002a388889e9882d946 Mon Sep 17 00:00:00 2001 From: Jeffrey Altman Date: Fri, 18 Oct 2013 19:14:00 -0400 Subject: [PATCH] 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 --- src/WINNT/afsd/cm_scache.c | 57 ++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 12 deletions(-) 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); } } -- 2.39.5