From f2c6ae300a211460c24c87752cf9400b9e61ee1f Mon Sep 17 00:00:00 2001 From: Marc Dionne Date: Thu, 4 Nov 2010 20:49:41 -0400 Subject: [PATCH] Cache bypass: Fix oops in bypass transition functions The FCSBypass flag might change between the time we check it before entering afs_TransitionToCaching or afs_TransitionToBypass and when we check it again within the functions. Instead of panicing, just exit if someone beat us to it. Also move the checks within the write lock region to make sure the code doesn't get run multiple times. Change-Id: I4319896e522d0681c548299d2bd547e71998cc88 Reviewed-on: http://gerrit.openafs.org/3266 Reviewed-by: Jeffrey Altman Tested-by: Marc Dionne Reviewed-by: Derrick Brashear --- src/afs/afs_bypasscache.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c index e23c5591db..2e92b413d1 100644 --- a/src/afs/afs_bypasscache.c +++ b/src/afs/afs_bypasscache.c @@ -143,9 +143,6 @@ afs_TransitionToBypass(struct vcache *avc, if (!avc) return; - if (avc->f.states & FCSBypass) - osi_Panic("afs_TransitionToBypass: illegal transition to bypass--already FCSBypass\n"); - if (aflags & TRANSChangeDesiredBit) setDesire = 1; if (aflags & TRANSSetManualBit) @@ -156,7 +153,14 @@ afs_TransitionToBypass(struct vcache *avc, #else AFS_GLOCK(); #endif + ObtainWriteLock(&avc->lock, 925); + /* + * Someone may have beat us to doing the transition - we had no lock + * when we checked the flag earlier. No cause to panic, just return. + */ + if (avc->f.states & FCSBypass) + goto done; /* If we never cached this, just change state */ if (setDesire && (!(avc->cachingStates & FCSBypass))) { @@ -220,9 +224,6 @@ afs_TransitionToCaching(struct vcache *avc, if (!avc) return; - if (!(avc->f.states & FCSBypass)) - osi_Panic("afs_TransitionToCaching: illegal transition to caching--already caching\n"); - if (aflags & TRANSChangeDesiredBit) resetDesire = 1; if (aflags & TRANSSetManualBit) @@ -234,6 +235,12 @@ afs_TransitionToCaching(struct vcache *avc, AFS_GLOCK(); #endif ObtainWriteLock(&avc->lock, 926); + /* + * Someone may have beat us to doing the transition - we had no lock + * when we checked the flag earlier. No cause to panic, just return. + */ + if (!(avc->f.states & FCSBypass)) + goto done; /* Ok, we actually do need to flush */ ObtainWriteLock(&afs_xcbhash, 957); @@ -255,6 +262,7 @@ afs_TransitionToCaching(struct vcache *avc, avc->cachingStates |= FCSManuallySet; avc->cachingTransitions++; +done: ReleaseWriteLock(&avc->lock); #ifdef AFS_BOZONLOCK_ENV afs_BozonUnlock(&avc->pvnLock, avc);