From: Andrew Deason Date: Thu, 1 Nov 2012 20:32:31 +0000 (-0500) Subject: afs_AllocDCache: return NULL instead of panic X-Git-Tag: upstream/1.8.0_pre1^2~1813 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=64ee7b32f134e6431eb2894ed4397f8b1fea25ad;p=packages%2Fo%2Fopenafs.git afs_AllocDCache: return NULL instead of panic 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. Change-Id: Iafb539bbda9ef20907ef575699185f111ca39c2b Reviewed-on: http://gerrit.openafs.org/8377 Tested-by: BuildBot Reviewed-by: Derrick Brashear --- diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c index a93255369..b48c05ff5 100644 --- a/src/afs/afs_dcache.c +++ b/src/afs/afs_dcache.c @@ -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 @@ -3459,6 +3492,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);