afs: Add afs_WriteDCache sanity checks

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.

Reviewed-on: http://gerrit.openafs.org/6419
Tested-by: BuildBot <buildbot@rampaginggeek.com>
Reviewed-by: Derrick Brashear <shadow@dementix.org>
(cherry picked from commit 79f69f2eb130c1c5cb6cdfa4e7a129f450a58339)

Change-Id: I482ad6a1fef3896144855b58c70e73bdf896027f
Reviewed-on: http://gerrit.openafs.org/7942
Reviewed-by: Derrick Brashear <shadow@dementix.org>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
This commit is contained in:
Andrew Deason 2011-12-21 17:01:16 -05:00 committed by Derrick Brashear
parent 9a55866037
commit 4b68723f2e

View 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;
}