{
struct dcache *tdc;
- for ( ; *indexp != NULLIDX; indexp = &afs_dvnextTbl[*indexp]) {
+ if (*indexp != NULLIDX) {
tdc = afs_GetUnusedDSlot(*indexp);
if (tdc) {
osi_Assert(tdc->refCount == 1);
tdc = afs_GetValidDSlot(index);
if (!tdc) {
/* afs_TryToSmush is best-effort; we may not actually discard
- * everything, so failure to discard a dcache due to an i/o
+ * everything, so failure to discard dcaches due to an i/o
* error is okay. */
- continue;
+ break;
}
if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
if (sync) {
i = afs_dvnextTbl[index];
if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
tdc = afs_GetValidDSlot(index);
- if (tdc) {
- if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
- totalChunks--;
- }
- ReleaseReadLock(&tdc->tlock);
- afs_PutDCache(tdc);
- }
+ if (!tdc) {
+ break;
+ }
+ if (!FidCmp(&tdc->f.fid, &avc->f.fid)) {
+ totalChunks--;
+ }
+ ReleaseReadLock(&tdc->tlock);
+ afs_PutDCache(tdc);
}
}
ReleaseWriteLock(&afs_xdcache);
/* afs_FindDCache is best-effort; we may not find the given
* file/offset, so if we cannot find the given dcache due to
* i/o errors, that is okay. */
- continue;
+ index = NULLIDX;
+ break;
}
ReleaseReadLock(&tdc->tlock);
if (!FidCmp(&tdc->f.fid, &avc->f.fid) && chunk == tdc->f.chunk) {
*
* \return The new dcache.
*/
-struct dcache *
+static struct dcache *
afs_AllocDCache(struct vcache *avc, afs_int32 chunk, afs_int32 lock,
struct VenusFid *ashFid)
{
if (afs_indexUnique[index] == avc->f.fid.Fid.Unique) {
tdc = afs_GetValidDSlot(index);
if (!tdc) {
- /* we got an i/o error when trying to get the given dslot,
- * but do not bail out just yet; it is possible the dcache
- * we're looking for is elsewhere, so it doesn't matter if
- * we can't load this one. */
+ /* we got an i/o error when trying to get the given dslot.
+ * it's possible the dslot we're looking for is elsewhere,
+ * but most likely the disk cache is currently unusable, so
+ * all afs_GetValidDSlot calls will fail, so just bail out. */
dslot_error = 1;
- continue;
+ index = NULLIDX;
+ break;
}
ReleaseReadLock(&tdc->tlock);
/*
tdc = afs_AllocDCache(avc, chunk, aflags, NULL);
if (!tdc) {
ReleaseWriteLock(&afs_xdcache);
-
- /* If we can't get space for 5 mins we give up and bail out */
- if (++downDCount > 300) {
- afs_warn("afs: Unable to get free cache space for file "
- "%u:%u.%u.%u for 5 minutes; failing with an i/o error\n",
- avc->f.fid.Cell,
- avc->f.fid.Fid.Volume,
- avc->f.fid.Fid.Vnode,
- avc->f.fid.Fid.Unique);
- goto done;
+ if (afs_discardDCList == NULLIDX && afs_freeDCList == NULLIDX) {
+ /* It looks like afs_AllocDCache failed because we don't
+ * have any free dslots to use. Maybe if we wait a little
+ * while, we'll be able to free up some slots, so try for 5
+ * minutes, then bail out. */
+ if (++downDCount > 300) {
+ afs_warn("afs: Unable to get free cache space for file "
+ "%u:%u.%u.%u for 5 minutes; failing with an i/o error\n",
+ avc->f.fid.Cell,
+ avc->f.fid.Fid.Volume,
+ avc->f.fid.Fid.Vnode,
+ avc->f.fid.Fid.Unique);
+ goto done;
+ }
+ afs_osi_Wait(1000, 0, 0);
+ goto RetryLookup;
}
- /*
- * Locks held:
- * avc->lock(R) if setLocks
- * avc->lock(W) if !setLocks
- */
- afs_osi_Wait(1000, 0, 0);
- goto RetryLookup;
+ /* afs_AllocDCache failed, but not because we're out of free
+ * dslots. Something must be screwy with the cache, so bail out
+ * immediately without waiting. */
+ afs_warn("afs: Error while alloc'ing cache slot for file "
+ "%u:%u.%u.%u; failing with an i/o error\n",
+ avc->f.fid.Cell,
+ avc->f.fid.Fid.Volume,
+ avc->f.fid.Fid.Vnode,
+ avc->f.fid.Fid.Unique);
+ goto done;
}
/*