From a4b3a659095cf50a4c5bb6cea69c71680817830a Mon Sep 17 00:00:00 2001 From: Mark Vitale Date: Mon, 29 Oct 2018 16:48:14 -0400 Subject: [PATCH] afs: avoid afs_GetDownDSlot panic on afs_WriteDCache failure If afs_GetDownDSlot() finds insuffcient free slots in the afs_freeDSList, it will walk the afs_DLRU attempting to flush and free eligible dcaches. However, if an error occurs during the flush to CacheItems (afs_WriteDCache()), e.g., -EINTR, afs_GetDownDSlot() will assert. However, a panic in this case is overkill, since afs_GetDownDSlot() is a best-effort attempt to free dslots. The caller (afs_UFSGetDSlot()) will allocate more dcaches if needed. Instead: - Refactor afs_GetDownDSlot() by moving the QRemove() call to after the afs_WriteDCache logic, so it accompanies the logic that puts the dcache back on the freelist. This is safe because we hold the afs_xdcache W lock for the duration of the routine. - If afs_WriteDCache() returns an error, return early and let the caller handle any recovery. Reviewed-on: https://gerrit.openafs.org/13364 Reviewed-by: Andrew Deason Tested-by: Andrew Deason Reviewed-by: Cheyenne Wills Reviewed-by: Benjamin Kaduk (cherry picked from commit d6f52d11c358f71b2c4357cb135e898de7c6277b) Change-Id: I2630bf04b3e3a88a1fa00f693adf2a77290d47ef Reviewed-on: https://gerrit.openafs.org/13503 Tested-by: BuildBot Reviewed-by: Cheyenne Wills Reviewed-by: Andrew Deason Reviewed-by: Benjamin Kaduk Reviewed-by: Stephan Wiesand --- src/afs/afs_dcache.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/afs/afs_dcache.c b/src/afs/afs_dcache.c index eb07a4aa6..dc0f928ac 100644 --- a/src/afs/afs_dcache.c +++ b/src/afs/afs_dcache.c @@ -1272,8 +1272,6 @@ afs_GetDownDSlot(int anumber) if (tdc->refCount == 0) { if ((ix = tdc->index) == NULLIDX) osi_Panic("getdowndslot"); - /* pull the entry out of the lruq and put it on the free list */ - QRemove(&tdc->lruq); /* write-through if modified */ if (tdc->dflags & DFEntryMod) { @@ -1295,12 +1293,23 @@ afs_GetDownDSlot(int anumber) AFS_GLOCK(); } #else + int code; + + code = afs_WriteDCache(tdc, 1); + if (code) { + /* + * We couldn't flush it at this time; return early because + * if afs_WriteDCache() failed once it is likely to + * continue failing for subsequent dcaches. + */ + return; + } tdc->dflags &= ~DFEntryMod; - osi_Assert(afs_WriteDCache(tdc, 1) == 0); #endif } - /* finally put the entry in the free list */ + /* pull the entry out of the lruq and put it on the free list */ + QRemove(&tdc->lruq); afs_indexTable[ix] = NULL; afs_indexFlags[ix] &= ~IFEverUsed; tdc->index = NULLIDX; -- 2.39.5