afs: Avoid GetDCache panic on AllocDCache failure 32/13032/3
authorAndrew Deason <adeason@sinenomine.net>
Thu, 26 Apr 2018 17:02:18 +0000 (12:02 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Sun, 10 Jun 2018 20:44:32 +0000 (16:44 -0400)
Currently, in afs_GetDCache, if afs_AllocDCache fails, we retry for 5
minutes and then panic. Panicing in this situation is completely
unnecessary; afs_GetDCache can fail for a variety of other mundane
reasons (such as, if we can't fetch the requested data from the
relevant fileserver).

It may seem unusual for afs_AllocDCache to fail for over 5 minutes
(this is supposed to mean that we're out of dslots, and our attempts
to free up dslots have failed). However, afs_AllocDCache can also fail
if we are having issues in accessing the disk cache, and so we may not
be out of cache space or dslots at all; we just can't access the
cache. In this case, afs_AllocDCache can easily fail forever; waiting
longer or trying to free up cache space isn't going to help.

So, to avoid panicing in such situations, just make afs_GetDCache
return an error. We just need to make sure afs_xdcache is unlocked,
and then we can just jump to 'done', like plenty of other codepaths
do; no extra cleanup is required.

Also since we are removing a panic, add a log message when this
situation happens, so EIO errors don't suddenly pop up silently.

Change-Id: I9b8dd6c861b8066822c44758566c05abd7dc1660
Reviewed-on: https://gerrit.openafs.org/13032
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Reviewed-by: Michael Meffie <mmeffie@sinenomine.net>
Reviewed-by: Marcio Brito Barbosa <mbarbosa@sinenomine.net>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/afs_dcache.c

index f71f459..659e5ef 100644 (file)
@@ -1971,10 +1971,19 @@ afs_GetDCache(struct vcache *avc, afs_size_t abyte,
            }
            tdc = afs_AllocDCache(avc, chunk, aflags, NULL);
            if (!tdc) {
-               /* If we can't get space for 5 mins we give up and panic */
-               if (++downDCount > 300)
-                   osi_Panic("getdcache");
                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;
+                }
+
                /*
                 * Locks held:
                 * avc->lock(R) if setLocks