From: Marc Dionne Date: Fri, 5 Nov 2010 00:49:41 +0000 (-0400) Subject: Cache bypass: Fix oops in bypass transition functions X-Git-Tag: upstream/1.6.0.pre2^2~154 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=5de4614c14f73b3d6d4b0da3ed87b6264b42332a;p=packages%2Fo%2Fopenafs.git 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. Reviewed-on: http://gerrit.openafs.org/3266 Reviewed-by: Jeffrey Altman Tested-by: Marc Dionne Reviewed-by: Derrick Brashear (cherry picked from commit f2c6ae300a211460c24c87752cf9400b9e61ee1f) Change-Id: I3b7ad3f9672975a87dbe337256d42166fc638b34 Reviewed-on: http://gerrit.openafs.org/3639 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/afs/afs_bypasscache.c b/src/afs/afs_bypasscache.c index e23c5591d..2e92b413d 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);