afs: Cope with afs_GetValidDSlot errors
authorAndrew Deason <adeason@sinenomine.net>
Wed, 21 Dec 2011 21:05:40 +0000 (16:05 -0500)
committerDerrick Brashear <shadow@dementix.org>
Tue, 27 Dec 2011 04:33:29 +0000 (20:33 -0800)
Make callers of afs_GetValidDSlot deal with getting a NULL dcache,
which can occur if an error is encountered. Some of these just panic
at least for now, since a code path for recovery is complex, but this
is at least better than dereferencing a NULL pointer.

Change-Id: I4022a914bbaa0e1f3f4daadfdc32d165a6e2febd
Reviewed-on: http://gerrit.openafs.org/6418
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>

src/afs/afs_buffer.c
src/afs/afs_daemons.c
src/afs/afs_dcache.c
src/afs/afs_disconnected.c
src/afs/afs_pioctl.c
src/afs/afs_segments.c

index 52243d6..6eb7730 100644 (file)
@@ -547,7 +547,7 @@ DNew(struct dcache *adc, int page, struct DirBuffer *entry)
      * DFlush due to lock hierarchy issues */
     if ((page + 1) * AFS_BUFFER_PAGESIZE > adc->f.chunkBytes) {
        afs_AdjustSize(adc, (page + 1) * AFS_BUFFER_PAGESIZE);
-       afs_WriteDCache(adc, 1);
+       osi_Assert(afs_WriteDCache(adc, 1) == 0);
     }
     ObtainWriteLock(&tb->lock, 265);
     tb->lockers++;
index 595d76f..a1bd5f0 100644 (file)
@@ -1177,7 +1177,7 @@ afs_sgidaemon(void)
            SPUNLOCK(afs_sgibklock, s);
            AFS_GLOCK();
            tdc->dflags &= ~DFEntryMod;
-           afs_WriteDCache(tdc, 1);
+           osi_Assert(afs_WriteDCache(tdc, 1) == 0);
            AFS_GUNLOCK();
            s = SPLOCK(afs_sgibklock);
        }
index 420b92e..9d4a7e1 100644 (file)
@@ -674,13 +674,15 @@ afs_GetDownD(int anumber, int *aneedSpace, afs_int32 buckethint)
        for (i = 0; i < victimPtr; i++) {
            tdc = afs_GetValidDSlot(victims[i]);
            /* We got tdc->tlock(R) here */
-           if (tdc->refCount == 1)
+           if (tdc && tdc->refCount == 1)
                victimDCs[i] = tdc;
            else
                victimDCs[i] = 0;
-           ReleaseReadLock(&tdc->tlock);
-           if (!victimDCs[i])
-               afs_PutDCache(tdc);
+           if (tdc) {
+               ReleaseReadLock(&tdc->tlock);
+               if (!victimDCs[i])
+                   afs_PutDCache(tdc);
+           }
        }
        for (i = 0; i < victimPtr; i++) {
            /* q is first elt in dcache entry */
@@ -1201,7 +1203,7 @@ afs_GetDownDSlot(int anumber)
                }
 #else
                tdc->dflags &= ~DFEntryMod;
-               afs_WriteDCache(tdc, 1);
+               osi_Assert(afs_WriteDCache(tdc, 1) == 0);
 #endif
            }
 
@@ -1312,6 +1314,7 @@ afs_TryToSmush(struct vcache *avc, afs_ucred_t *acred, int sync)
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            int releaseTlock = 1;
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_TryToSmush tdc");
            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
                if (sync) {
                    if ((afs_indexFlags[index] & IFDataMod) == 0
@@ -1401,11 +1404,13 @@ afs_DCacheMissingChunks(struct vcache *avc)
         i = afs_dvnextTbl[index];
         if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
             tdc = afs_GetValidDSlot(index);
-            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
-               totalChunks--;
-            }
-            ReleaseReadLock(&tdc->tlock);
-            afs_PutDCache(tdc);
+           if (tdc) {
+               if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
+                   totalChunks--;
+               }
+               ReleaseReadLock(&tdc->tlock);
+               afs_PutDCache(tdc);
+           }
         }
     }
     ReleaseWriteLock(&afs_xdcache);
@@ -1454,6 +1459,7 @@ afs_FindDCache(struct vcache *avc, afs_size_t abyte)
     for (index = afs_dchashTbl[i]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_FindDCache tdc");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid) && chunk == tdc->f.chunk) {
                break;          /* leaving refCount high for caller */
@@ -1770,6 +1776,10 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
        for (index = afs_dchashTbl[i]; index != NULLIDX;) {
            if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
                tdc = afs_GetValidDSlot(index);
+               if (!tdc) {
+                   ReleaseWriteLock(&afs_xdcache);
+                   goto done;
+               }
                ReleaseReadLock(&tdc->tlock);
                /*
                 * Locks held:
@@ -2523,7 +2533,7 @@ afs_WriteThroughDSlots(void)
            if (wrLock && (tdc->dflags & DFEntryMod)) {
                tdc->dflags &= ~DFEntryMod;
                ObtainWriteLock(&afs_xdcache, 620);
-               afs_WriteDCache(tdc, 1);
+               osi_Assert(afs_WriteDCache(tdc, 1) == 0);
                ReleaseWriteLock(&afs_xdcache);
                touchedit = 1;
            }
@@ -3002,7 +3012,7 @@ afs_InitCacheFile(char *afile, ino_t ainode)
     tdc->f.states &= ~DWriting;
     tdc->dflags &= ~DFEntryMod;
     /* don't set f.modTime; we're just cleaning up */
-    afs_WriteDCache(tdc, 0);
+    osi_Assert(afs_WriteDCache(tdc, 0) == 0);
     ReleaseWriteLock(&afs_xdcache);
     ReleaseWriteLock(&tdc->lock);
     afs_PutDCache(tdc);
index 272bc4f..c1499b1 100644 (file)
@@ -72,11 +72,13 @@ afs_FindDCacheByFid(struct VenusFid *afid)
     for (index = afs_dvhashTbl[i]; index != NULLIDX;) {
        if (afs_indexUnique[index] == afid->Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
-           ReleaseReadLock(&tdc->tlock);
-           if (!FidCmp(&tdc->f.fid, afid)) {
-               break;          /* leaving refCount high for caller */
+           if (tdc) {
+               ReleaseReadLock(&tdc->tlock);
+               if (!FidCmp(&tdc->f.fid, afid)) {
+                   break;              /* leaving refCount high for caller */
+               }
+               afs_PutDCache(tdc);
            }
-           afs_PutDCache(tdc);
        }
        index = afs_dvnextTbl[index];
     }
index 83f159c..d1af181 100644 (file)
@@ -3547,6 +3547,9 @@ DECL_PIOCTL(PFlushVolumeData)
        if (!(afs_indexFlags[i] & IFEverUsed))
            continue;           /* never had any data */
        tdc = afs_GetValidDSlot(i);
+       if (!tdc) {
+           continue;
+       }
        if (tdc->refCount <= 1) {    /* too high, in use by running sys call */
            ReleaseReadLock(&tdc->tlock);
            if (tdc->f.fid.Fid.Volume == volume && tdc->f.fid.Cell == cell) {
index 8ae6680..47058f9 100644 (file)
@@ -253,6 +253,11 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
            if ((afs_indexFlags[index] & IFDataMod)
                && (afs_indexUnique[index] == avc->f.fid.Fid.Unique)) {
                tdc = afs_GetValidDSlot(index); /* refcount+1. */
+               if (!tdc) {
+                   ReleaseWriteLock(&afs_xdcache);
+                   code = EIO;
+                   goto done;
+               }
                ReleaseReadLock(&tdc->tlock);
                if (!FidCmp(&tdc->f.fid, &avc->f.fid) && tdc->f.chunk >= minj) {
                    off = tdc->f.chunk - minj;
@@ -315,6 +320,7 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
        minj += NCHUNKSATONCE;
     } while (!code && moredata);
 
+ done:
     UpgradeSToWLock(&avc->lock, 29);
 
     /* send a trivial truncation store if did nothing else */
@@ -357,6 +363,7 @@ afs_StoreAllSegments(struct vcache *avc, struct vrequest *areq,
 
                if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
                    tdc = afs_GetValidDSlot(index);
+                   if (!tdc) osi_Panic("afs_StoreAllSegments tdc dv");
                    ReleaseReadLock(&tdc->tlock);
 
                    if (!FidCmp(&tdc->f.fid, &avc->f.fid)
@@ -521,6 +528,7 @@ afs_InvalidateAllSegments(struct vcache *avc)
     for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_InvalidateAllSegments tdc count");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid))
                dcListMax++;
@@ -535,6 +543,7 @@ afs_InvalidateAllSegments(struct vcache *avc)
     for (index = afs_dvhashTbl[hash]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_InvalidateAllSegments tdc store");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
                /* same file? we'll zap it */
@@ -713,6 +722,11 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) {
+               ReleaseWriteLock(&afs_xdcache);
+               code = EIO;
+               goto done;
+           }
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid))
                dcCount++;
@@ -731,6 +745,7 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     for (index = afs_dvhashTbl[code]; index != NULLIDX;) {
        if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
            tdc = afs_GetValidDSlot(index);
+           if (!tdc) osi_Panic("afs_TruncateAllSegments tdc");
            ReleaseReadLock(&tdc->tlock);
            if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
                /* same file, and modified, we'll store it back */
@@ -778,6 +793,9 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
 
     osi_Free(tdcArray, dcCount * sizeof(struct dcache *));
 
+    code = 0;
+
+ done:
 #if    (defined(AFS_SUN5_ENV))
     ObtainWriteLock(&avc->vlock, 547);
     if (--avc->activeV == 0 && (avc->vstates & VRevokeWait)) {
@@ -787,5 +805,5 @@ afs_TruncateAllSegments(struct vcache *avc, afs_size_t alen,
     ReleaseWriteLock(&avc->vlock);
 #endif
 
-    return 0;
+    return code;
 }