From: Andrew Deason Date: Thu, 1 Nov 2012 18:41:06 +0000 (-0500) Subject: afs: Traverse discard/free dslot list if errors X-Git-Tag: upstream/1.6.6_pre2^2~37 X-Git-Url: https://git.michaelhowe.org/gitweb/?a=commitdiff_plain;h=2679af76;p=packages%2Fo%2Fopenafs.git afs: Traverse discard/free dslot list if errors Currently, when we pull a dslot off of the discard or free list, we just try to get the first entry from the list, and panic if we cannot get it. Instead, traverse through the whole list, trying to find an entry we can successfully get. This introduces the helper function afs_GetDSlotFromList to do this traversal. This does not yet address the case where we cannot get any entry on the relevant list. Reviewed-on: http://gerrit.openafs.org/8376 Tested-by: BuildBot Reviewed-by: Derrick Brashear (cherry picked from commit 336939179721d79a6798614ff747dd06701e3edc) Change-Id: I12d8cfbe7d1fe7bbe50b49bcee34a8a5dced1569 Reviewed-on: http://gerrit.openafs.org/10354 Tested-by: BuildBot Reviewed-by: Andrew Deason Reviewed-by: Marc Dionne Reviewed-by: Mark Vitale Reviewed-by: Stephan Wiesand --- diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c index 8f3d5d627..593473c7d 100644 --- a/src/afs/afs_dcache.c +++ b/src/afs/afs_dcache.c @@ -1066,6 +1066,34 @@ afs_DiscardDCache(struct dcache *adc) } /*afs_DiscardDCache */ +/** + * Get a dcache entry from the discard or free list + * + * @param[in] indexp A pointer to the head of the dcache free list or discard + * list (afs_freeDCList, or afs_discardDCList) + * + * @return A dcache from that list, or NULL if none could be retrieved. + * + * @pre afs_xdcache is write-locked + */ +static struct dcache * +afs_GetDSlotFromList(afs_int32 *indexp) +{ + struct dcache *tdc; + + for ( ; *indexp != NULLIDX; indexp = &afs_dvnextTbl[*indexp]) { + tdc = afs_GetUnusedDSlot(*indexp); + if (tdc) { + osi_Assert(tdc->refCount == 1); + ReleaseReadLock(&tdc->tlock); + *indexp = afs_dvnextTbl[tdc->index]; + afs_dvnextTbl[tdc->index] = NULLIDX; + return tdc; + } + } + return NULL; +} + /*! * Free the next element on the list of discarded cache elements. */ @@ -1087,13 +1115,9 @@ afs_FreeDiscardedDCache(void) /* * Get an entry from the list of discarded cache elements */ - tdc = afs_GetUnusedDSlot(afs_discardDCList); + tdc = afs_GetDSlotFromList(&afs_discardDCList); osi_Assert(tdc); - osi_Assert(tdc->refCount == 1); - ReleaseReadLock(&tdc->tlock); - afs_discardDCList = afs_dvnextTbl[tdc->index]; - afs_dvnextTbl[tdc->index] = NULLIDX; afs_discardDCCount--; size = ((tdc->f.chunkBytes + afs_fsfragsize) ^ afs_fsfragsize) >> 10; /* round up */ afs_blocksDiscarded -= size; @@ -1516,22 +1540,16 @@ afs_AllocDCache(struct vcache *avc, afs_int32 chunk, afs_int32 lock, if (afs_discardDCList == NULLIDX || ((lock & 2) && afs_freeDCList != NULLIDX)) { - afs_indexFlags[afs_freeDCList] &= ~IFFree; - tdc = afs_GetUnusedDSlot(afs_freeDCList); + tdc = afs_GetDSlotFromList(&afs_freeDCList); osi_Assert(tdc); - osi_Assert(tdc->refCount == 1); - ReleaseReadLock(&tdc->tlock); + afs_indexFlags[tdc->index] &= ~IFFree; ObtainWriteLock(&tdc->lock, 604); - afs_freeDCList = afs_dvnextTbl[tdc->index]; afs_freeDCCount--; } else { - afs_indexFlags[afs_discardDCList] &= ~IFDiscarded; - tdc = afs_GetUnusedDSlot(afs_discardDCList); + tdc = afs_GetDSlotFromList(&afs_discardDCList); osi_Assert(tdc); - osi_Assert(tdc->refCount == 1); - ReleaseReadLock(&tdc->tlock); + afs_indexFlags[tdc->index] &= ~IFDiscarded; ObtainWriteLock(&tdc->lock, 605); - afs_discardDCList = afs_dvnextTbl[tdc->index]; afs_discardDCCount--; size = ((tdc->f.chunkBytes +