Cache bypass: Fix oops in bypass transition functions
authorMarc Dionne <marc.c.dionne@gmail.com>
Fri, 5 Nov 2010 00:49:41 +0000 (20:49 -0400)
committerDerrick Brashear <shadow@dementia.org>
Fri, 5 Nov 2010 02:53:53 +0000 (19:53 -0700)
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>

src/afs/afs_bypasscache.c

index e23c559..2e92b41 100644 (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);