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 <jaltman@openafs.org>
Tested-by: Marc Dionne <marc.c.dionne@gmail.com>
Reviewed-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Marc Dionne 2010-11-04 20:49:41 -04:00 committed by Derrick Brashear
parent 732a4c52d5
commit f2c6ae300a

View File

@ -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);