Remove spurious NULL checks
[openafs.git] / src / afs / afs_dcache.c
index 8833c39..27b0733 100644 (file)
@@ -396,6 +396,27 @@ static struct CTD_stats {
 u_int afs_min_cache = 0;
 
 /*!
+ * If there are waiters for the cache to drain, wake them if
+ * the number of free or discarded cache blocks reaches the
+ * CM_CACHESIZEDDRAINEDPCT limit.
+ *
+ * \note Environment:
+ *     This routine must be called with the afs_xdcache lock held
+ *     (in write mode).
+ */
+static void
+afs_WakeCacheWaitersIfDrained(void)
+{
+    if (afs_WaitForCacheDrain) {
+       if ((afs_blocksUsed - afs_blocksDiscarded) <=
+           PERCENT(CM_CACHESIZEDRAINEDPCT, afs_cacheBlocks)) {
+           afs_WaitForCacheDrain = 0;
+           afs_osi_Wakeup(&afs_WaitForCacheDrain);
+       }
+    }
+}
+
+/*!
  * Keeps the cache clean and free by truncating uneeded files, when used.
  * \param
  * \return
@@ -416,7 +437,7 @@ afs_CacheTruncateDaemon(void)
     while (1) {
        cb_lowat = PERCENT((CM_DCACHESPACEFREEPCT - CM_DCACHEEXTRAPCT), afs_cacheBlocks);
        ObtainWriteLock(&afs_xdcache, 266);
-       if (afs_CacheTooFull) {
+       if (afs_CacheTooFull || afs_WaitForCacheDrain) {
            int space_needed, slots_needed;
            /* if we get woken up, we should try to clean something out */
            for (counter = 0; counter < 10; counter++) {
@@ -431,14 +452,15 @@ afs_CacheTruncateDaemon(void)
                if (slots_needed || space_needed)
                    afs_GetDownD(slots_needed, &space_needed, 0);
                if ((space_needed <= 0) && (slots_needed <= 0)) {
-                   afs_CacheTooFull = 0;
                    break;
                }
                if (afs_termState == AFSOP_STOP_TRUNCDAEMON)
                    break;
            }
-           if (!afs_CacheIsTooFull())
+           if (!afs_CacheIsTooFull()) {
                afs_CacheTooFull = 0;
+               afs_WakeCacheWaitersIfDrained();
+           }
        }       /* end of cache cleanup */
        ReleaseWriteLock(&afs_xdcache);
 
@@ -987,14 +1009,6 @@ afs_FlushDCache(struct dcache *adc)
     } else {
        afs_FreeDCache(adc);
     }
-
-    if (afs_WaitForCacheDrain) {
-       if (afs_blocksUsed <=
-           PERCENT(CM_CACHESIZEDRAINEDPCT, afs_cacheBlocks)) {
-           afs_WaitForCacheDrain = 0;
-           afs_osi_Wakeup(&afs_WaitForCacheDrain);
-       }
-    }
 }                              /*afs_FlushDCache */
 
 
@@ -1019,13 +1033,7 @@ afs_FreeDCache(struct dcache *adc)
     afs_indexFlags[adc->index] |= IFFree;
     adc->dflags |= DFEntryMod;
 
-    if (afs_WaitForCacheDrain) {
-       if ((afs_blocksUsed - afs_blocksDiscarded) <=
-           PERCENT(CM_CACHESIZEDRAINEDPCT, afs_cacheBlocks)) {
-           afs_WaitForCacheDrain = 0;
-           afs_osi_Wakeup(&afs_WaitForCacheDrain);
-       }
-    }
+    afs_WakeCacheWaitersIfDrained();
 }                              /* afs_FreeDCache */
 
 /*!
@@ -1065,14 +1073,7 @@ afs_DiscardDCache(struct dcache *adc)
     adc->dflags |= DFEntryMod;
     afs_indexFlags[adc->index] |= IFDiscarded;
 
-    if (afs_WaitForCacheDrain) {
-       if ((afs_blocksUsed - afs_blocksDiscarded) <=
-           PERCENT(CM_CACHESIZEDRAINEDPCT, afs_cacheBlocks)) {
-           afs_WaitForCacheDrain = 0;
-           afs_osi_Wakeup(&afs_WaitForCacheDrain);
-       }
-    }
-
+    afs_WakeCacheWaitersIfDrained();
 }                              /*afs_DiscardDCache */
 
 /**
@@ -2397,6 +2398,13 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
                        afs_PutDCache(tdc);
                        tdc = 0;
                        ReleaseReadLock(&avc->lock);
+
+                       if (tc) {
+                           /* If we have a connection, we must put it back,
+                            * since afs_Analyze will not be called here. */
+                           afs_PutConn(tc, rxconn, SHARED_LOCK);
+                       }
+
                        slowPass = 1;
                        goto RetryGetDCache;
                    }
@@ -2680,11 +2688,7 @@ afs_WriteThroughDSlots(void)
         */
        struct afs_fheader theader;
 
-       theader.magic = AFS_FHMAGIC;
-       theader.firstCSize = AFS_FIRSTCSIZE;
-       theader.otherCSize = AFS_OTHERCSIZE;
-       theader.version = AFS_CI_VERSION;
-       theader.dataSize = sizeof(struct fcache);
+       afs_InitFHeader(&theader);
        afs_osi_Write(afs_cacheInodep, 0, &theader, sizeof(theader));
     }
     ReleaseWriteLock(&afs_xdcache);
@@ -2699,14 +2703,14 @@ afs_WriteThroughDSlots(void)
  *
  * Parameters:
  *     aslot : Dcache slot to look at.
- *      needvalid : Whether the specified slot should already exist
+ *      type : What 'type' of dslot to get; see the dslot_state enum
  *
  * Environment:
  *     Must be called with afs_xdcache write-locked.
  */
 
 struct dcache *
-afs_MemGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
+afs_MemGetDSlot(afs_int32 aslot, dslot_state type)
 {
     struct dcache *tdc;
     int existing = 0;
@@ -2727,10 +2731,14 @@ afs_MemGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
        return tdc;
     }
 
-    /* if 'indexvalid' is true, the slot must already exist and be populated
-     * somewhere. for memcache, the only place that dcache entries exist is
-     * in memory, so if we did not find it above, something is very wrong. */
-    osi_Assert(!indexvalid);
+    /* if we got here, the given slot is not in memory in our list of known
+     * slots. for memcache, the only place a dslot can exist is in memory, so
+     * if the caller is expecting to get back a known dslot, and we've reached
+     * here, something is very wrong. DSLOT_NEW is the only type of dslot that
+     * may not exist; for all others, the caller assumes the given dslot
+     * already exists. so, 'type' had better be DSLOT_NEW here, or something is
+     * very wrong. */
+    osi_Assert(type == DSLOT_NEW);
 
     if (!afs_freeDSList)
        afs_GetDownDSlot(4);
@@ -2791,20 +2799,13 @@ unsigned int last_error = 0, lasterrtime = 0;
  *
  * Parameters:
  *     aslot : Dcache slot to look at.
- *      indexvalid : 1 if we know the slot we're giving is valid, and thus
- *                   reading the dcache from the disk index should succeed. 0
- *                   if we are initializing a new dcache, and so reading from
- *                   the disk index may fail.
- *      datavalid : 0 if we are loading a dcache entry from the free or
- *                  discard list, so we know the data in the given dcache is
- *                  not valid. 1 if we are loading a known used dcache, so the
- *                  data in the dcache must be valid.
+ *      type : What 'type' of dslot to get; see the dslot_state enum
  *
  * Environment:
  *     afs_xdcache lock write-locked.
  */
 struct dcache *
-afs_UFSGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
+afs_UFSGetDSlot(afs_int32 aslot, dslot_state type)
 {
     afs_int32 code;
     struct dcache *tdc;
@@ -2867,7 +2868,10 @@ afs_UFSGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
        last_error = code;
 #endif
        lasterrtime = osi_Time();
-       if (indexvalid) {
+       if (type != DSLOT_NEW) {
+           /* If we are requesting a non-DSLOT_NEW slot, this is an error.
+            * non-DSLOT_NEW slots are supposed to already exist, so if we
+            * failed to read in the slot, something is wrong. */
            struct osi_stat tstat;
            if (afs_osi_Stat(afs_cacheInodep, &tstat)) {
                tstat.size = -1;
@@ -2887,19 +2891,27 @@ afs_UFSGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
     }
     if (!afs_CellNumValid(tdc->f.fid.Cell)) {
        entryok = 0;
-       if (datavalid) {
+       if (type == DSLOT_VALID) {
            osi_Panic("afs: needed valid dcache but index %d off %d has "
                      "invalid cell num %d\n",
                      (int)aslot, off, (int)tdc->f.fid.Cell);
        }
     }
 
-    if (datavalid && tdc->f.fid.Fid.Volume == 0) {
+    if (type == DSLOT_VALID && tdc->f.fid.Fid.Volume == 0) {
        osi_Panic("afs: invalid zero-volume dcache entry at slot %d off %d",
                  (int)aslot, off);
     }
 
-    if (!entryok || !datavalid) {
+    if (type == DSLOT_UNUSED) {
+       /* the requested dslot is known to exist, but contain invalid data
+        * (this happens when we're using a dslot from the free or discard
+        * list). be sure not to re-use the data in it, so force invalidation.
+        */
+       entryok = 0;
+    }
+
+    if (!entryok) {
        tdc->f.fid.Cell = 0;
        tdc->f.fid.Fid.Volume = 0;
        tdc->f.chunk = -1;
@@ -2909,14 +2921,12 @@ afs_UFSGetDSlot(afs_int32 aslot, int indexvalid, int datavalid)
        tdc->f.states &= ~(DRO|DBackup|DRW);
        afs_DCMoveBucket(tdc, 0, 0);
     } else {
-       if (&tdc->f != 0) {
-           if (tdc->f.states & DRO) {
-               afs_DCMoveBucket(tdc, 0, 2);
-           } else if (tdc->f.states & DBackup) {
-               afs_DCMoveBucket(tdc, 0, 1);
-           } else {
-               afs_DCMoveBucket(tdc, 0, 1);
-           }
+       if (tdc->f.states & DRO) {
+           afs_DCMoveBucket(tdc, 0, 2);
+       } else if (tdc->f.states & DBackup) {
+           afs_DCMoveBucket(tdc, 0, 1);
+       } else {
+           afs_DCMoveBucket(tdc, 0, 1);
        }
     }
     tdc->refCount = 1;
@@ -3035,7 +3045,7 @@ afs_wakeup(struct vcache *avc)
             * is already being handled by the higher-level code.
             */
            if ((avc->f.states & CSafeStore) == 0) {
-               tb->code = 0;
+               tb->code_raw = tb->code_checkcode = 0;
                tb->flags |= BUVALID;
                if (tb->flags & BUWAIT) {
                    tb->flags &= ~BUWAIT;
@@ -3106,6 +3116,13 @@ afs_InitCacheFile(char *afile, ino_t ainode)
        if ((tdc->f.states & DWriting) || tdc->f.fid.Fid.Volume == 0)
            fileIsBad = 1;
        tfile = osi_UFSOpen(&tdc->f.inode);
+       if (!tfile) {
+           ReleaseWriteLock(&afs_xdcache);
+           ReleaseWriteLock(&tdc->lock);
+           afs_PutDCache(tdc);
+           return ENOENT;
+       }
+
        code = afs_osi_Stat(tfile, &tstat);
        if (code)
            osi_Panic("initcachefile stat");