]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
afs_AllocDCache: return NULL instead of panic
authorAndrew Deason <adeason@sinenomine.net>
Thu, 1 Nov 2012 20:32:31 +0000 (15:32 -0500)
committerStephan Wiesand <stephan.wiesand@desy.de>
Wed, 30 Oct 2013 18:34:58 +0000 (11:34 -0700)
Currently afs_AllocDCache will panic if we cannot get a valid dcache
from the free/discard lists. Instead, return NULL, so the caller can
decide how to handle the error.

Currently the caller will just panic anyway, but that will be
addressed in a future commit.

Reviewed-on: http://gerrit.openafs.org/8377
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@your-file-system.com>
(cherry picked from commit 64ee7b32f134e6431eb2894ed4397f8b1fea25ad)

Change-Id: Ica8f1539279c30f4914ab84161c6bc2f0468d565
Reviewed-on: http://gerrit.openafs.org/10355
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Marc Dionne <marc.c.dionne@gmail.com>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Stephan Wiesand <stephan.wiesand@desy.de>
src/afs/afs_dcache.c

index 593473c7da2101efa9a7b077332210c712a41cd5..48aa01aa93d59781df5c279293dd2b6d72f767e4 100644 (file)
@@ -1512,6 +1512,53 @@ afs_FindDCache(struct vcache *avc, afs_size_t abyte)
     return NULL;
 }                              /*afs_FindDCache */
 
+/* only call these from afs_AllocDCache() */
+static struct dcache *
+afs_AllocFreeDSlot(void)
+{
+    struct dcache *tdc;
+
+    tdc = afs_GetDSlotFromList(&afs_freeDCList);
+    if (!tdc) {
+       return NULL;
+    }
+    afs_indexFlags[tdc->index] &= ~IFFree;
+    ObtainWriteLock(&tdc->lock, 604);
+    afs_freeDCCount--;
+
+    return tdc;
+}
+static struct dcache *
+afs_AllocDiscardDSlot(afs_int32 lock)
+{
+    struct dcache *tdc;
+    afs_uint32 size = 0;
+    struct osi_file *file;
+
+    tdc = afs_GetDSlotFromList(&afs_discardDCList);
+    if (!tdc) {
+       return NULL;
+    }
+    afs_indexFlags[tdc->index] &= ~IFDiscarded;
+    ObtainWriteLock(&tdc->lock, 605);
+    afs_discardDCCount--;
+    size =
+       ((tdc->f.chunkBytes +
+         afs_fsfragsize) ^ afs_fsfragsize) >> 10;
+    tdc->f.states &= ~(DRO|DBackup|DRW);
+    afs_DCMoveBucket(tdc, size, 0);
+    afs_blocksDiscarded -= size;
+    afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
+    if ((lock & 2)) {
+       /* Truncate the chunk so zeroes get filled properly */
+       file = afs_CFileOpen(&tdc->f.inode);
+       afs_CFileTruncate(file, 0);
+       afs_CFileClose(file);
+       afs_AdjustSize(tdc, 0);
+    }
+
+    return tdc;
+}
 
 /*!
  * Get a fresh dcache from the free or discarded list.
@@ -1534,38 +1581,23 @@ afs_AllocDCache(struct vcache *avc, afs_int32 chunk, afs_int32 lock,
                struct VenusFid *ashFid)
 {
     struct dcache *tdc = NULL;
-    afs_uint32 size = 0;
-    struct osi_file *file;
-
-    if (afs_discardDCList == NULLIDX
-       || ((lock & 2) && afs_freeDCList != NULLIDX)) {
 
-       tdc = afs_GetDSlotFromList(&afs_freeDCList);
-       osi_Assert(tdc);
-       afs_indexFlags[tdc->index] &= ~IFFree;
-       ObtainWriteLock(&tdc->lock, 604);
-       afs_freeDCCount--;
+    /* if (lock & 2), prefer 'free' dcaches; otherwise, prefer 'discard'
+     * dcaches. In either case, try both if our first choice doesn't work. */
+    if ((lock & 2)) {
+       tdc = afs_AllocFreeDSlot();
+       if (!tdc) {
+           tdc = afs_AllocDiscardDSlot(lock);
+       }
     } else {
-       tdc = afs_GetDSlotFromList(&afs_discardDCList);
-       osi_Assert(tdc);
-       afs_indexFlags[tdc->index] &= ~IFDiscarded;
-       ObtainWriteLock(&tdc->lock, 605);
-       afs_discardDCCount--;
-       size =
-           ((tdc->f.chunkBytes +
-             afs_fsfragsize) ^ afs_fsfragsize) >> 10;
-       tdc->f.states &= ~(DRO|DBackup|DRW);
-       afs_DCMoveBucket(tdc, size, 0);
-       afs_blocksDiscarded -= size;
-       afs_stats_cmperf.cacheBlocksDiscarded = afs_blocksDiscarded;
-       if (lock & 2) {
-           /* Truncate the chunk so zeroes get filled properly */
-           file = afs_CFileOpen(&tdc->f.inode);
-           afs_CFileTruncate(file, 0);
-           afs_CFileClose(file);
-           afs_AdjustSize(tdc, 0);
+       tdc = afs_AllocDiscardDSlot(lock);
+       if (!tdc) {
+           tdc = afs_AllocFreeDSlot();
        }
     }
+    if (!tdc) {
+       return NULL;
+    }
 
     /*
      * Locks held:
@@ -1888,6 +1920,7 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
            }
 
            tdc = afs_AllocDCache(avc, chunk, aflags, NULL);
+           osi_Assert(tdc);
 
            /*
             * Now add to the two hash chains - note that i is still set
@@ -3468,6 +3501,7 @@ afs_MakeShadowDir(struct vcache *avc, struct dcache *adc)
 
     /* Get a fresh dcache. */
     new_dc = afs_AllocDCache(avc, 0, 0, &shadow_fid);
+    osi_Assert(new_dc);
 
     ObtainReadLock(&adc->mflock);