afs: Add afs_WriteDCache sanity checks
authorAndrew Deason <adeason@sinenomine.net>
Wed, 21 Dec 2011 22:01:16 +0000 (17:01 -0500)
committerDerrick Brashear <shadow@dementix.org>
Tue, 27 Dec 2011 04:34:06 +0000 (20:34 -0800)
Writing a non-free non-discarded dcache entry with a zero volume id
can easily cause hash table corruption later on, so make sure we don't
do that. Also log something if the write itself fails, as this usually
indicates an unusual situation involving I/O errors or something.

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

src/afs/afs_dcache.c

index 9d4a7e1..3fc0bb5 100644 (file)
@@ -2829,6 +2829,19 @@ afs_WriteDCache(struct dcache *adc, int atime)
     osi_Assert(WriteLocked(&afs_xdcache));
     if (atime)
        adc->f.modTime = osi_Time();
+
+    if ((afs_indexFlags[adc->index] & (IFFree | IFDiscarded)) == 0 &&
+        adc->f.fid.Fid.Volume == 0) {
+       /* If a dcache slot is not on the free or discard list, it must be
+        * in the hash table. Thus, the volume must be non-zero, since that
+        * is how we determine whether or not to unhash the entry when kicking
+        * it out of the cache. Do this check now, since otherwise this can
+        * cause hash table corruption and a panic later on after we read the
+        * entry back in. */
+       osi_Panic("afs_WriteDCache zero volume index %d flags 0x%x\n",
+                 adc->index, (unsigned)afs_indexFlags[adc->index]);
+    }
+
     /*
      * Seek to the right dcache slot and write the in-memory image out to disk.
      */
@@ -2838,8 +2851,12 @@ afs_WriteDCache(struct dcache *adc, int atime)
                      sizeof(struct fcache) * adc->index +
                      sizeof(struct afs_fheader), (char *)(&adc->f),
                      sizeof(struct fcache));
-    if (code != sizeof(struct fcache))
+    if (code != sizeof(struct fcache)) {
+       afs_warn("afs: failed to write to CacheItems off %ld code %d/%d\n",
+                (long)(sizeof(struct fcache) * adc->index + sizeof(struct afs_fheader)),
+                (int)code, (int)sizeof(struct fcache));
        return EIO;
+    }
     return 0;
 }