LINUX: Don't panic on some file open errors 42/14242/9
authorCheyenne Wills <cwills@sinenomine.net>
Thu, 2 Jul 2020 19:39:27 +0000 (13:39 -0600)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 3 Jul 2020 22:16:36 +0000 (18:16 -0400)
Commit 'LINUX: Return NULL for afs_linux_raw_open error' (f6af4a155)
updated afs_linux_raw_open to return NULL on some errors, but still
panics if obtaining the dentry fails.

Commit 'afs: Verify osi_UFSOpen worked' (c6b61a451) updated callers of
osi_UFSOpen to verify whether or not the open was successful.  This
meant osi_UFSOpen (and routines it calls) could pass back an error
indication rather than panic when an error is encountered.

Update afs_linux_raw_open to return a failure instead of panic if unable
to obtain a dentry.

Update osi_UFSOpen to return a NULL instead of panic if unable to obtain
memory or fails to open the file. All callers of osi_UFSOpen handle a
fail return, though some will still issue a panic.

Update afs_linux_readpage_fastpath and afs_linux_readpages to not panic
if afs_linux_raw_open fails.  Instead of panic, return an error.

For testing, an error can be forced by removing a file from the
cache directory.

Note this work is based on a commit by pruiter@sinenomine.net

Change-Id: Ic47e4868b4f81d99fbe3b2e4958778508ae4851f
Reviewed-on: https://gerrit.openafs.org/14242
Reviewed-by: Andrew Deason <adeason@sinenomine.net>
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/LINUX/osi_file.c
src/afs/LINUX/osi_vnodeops.c

index e2218ad..42d49ef 100644 (file)
@@ -65,8 +65,12 @@ afs_linux_raw_open(afs_dcache_id_t *ainode)
 
     dp = afs_get_dentry_from_fh(afs_cacheSBp, ainode, cache_fh_len, cache_fh_type,
                afs_fh_acceptable);
-    if ((!dp) || IS_ERR(dp))
-           osi_Panic("Can't get dentry\n");
+    if ((!dp) || IS_ERR(dp)) {
+          afs_warn("afs: Cannot get dentry for cache file (code %d). Trying to continue, "
+                   "but AFS accesses may return errors or panic the system\n",
+                   (int) PTR_ERR(dp));
+          return NULL;
+    }
     tip = dp->d_inode;
     tip->i_flags |= S_NOATIME; /* Disable updating access times. */
 
@@ -114,8 +118,11 @@ osi_UFSOpen(afs_dcache_id_t *ainode)
     AFS_GUNLOCK();
     afile = kmalloc(sizeof(struct osi_file), GFP_NOFS);
     if (!afile) {
-       osi_Panic("osi_UFSOpen: Failed to allocate %d bytes for osi_file.\n",
-                 (int)sizeof(struct osi_file));
+       afs_warn("afs: Failed to allocate memory for opening a cache file. "
+                "Trying to continue, but AFS access may return errors or panic "
+                "the system\n");
+       AFS_GLOCK();
+       return NULL;
     }
     memset(afile, 0, sizeof(struct osi_file));
 
index c32b280..cab5fcc 100644 (file)
@@ -2333,7 +2333,11 @@ afs_linux_readpage_fastpath(struct file *fp, struct page *pp, int *codep)
     /* XXX - I suspect we should be locking the inodes before we use them! */
     AFS_GUNLOCK();
     cacheFp = afs_linux_raw_open(&tdc->f.inode);
-    osi_Assert(cacheFp);
+    if (cacheFp == NULL) {
+       /* Problem getting the inode */
+       AFS_GLOCK();
+       goto out;
+    }
     if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) {
        cachefs_noreadpage = 1;
        AFS_GLOCK();
@@ -2726,8 +2730,10 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
            afs_PutDCache(tdc);
            AFS_GUNLOCK();
            tdc = NULL;
-           if (cacheFp)
+           if (cacheFp) {
                filp_close(cacheFp, NULL);
+               cacheFp = NULL;
+           }
        }
 
        if (!tdc) {
@@ -2744,7 +2750,10 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
            AFS_GUNLOCK();
            if (tdc) {
                cacheFp = afs_linux_raw_open(&tdc->f.inode);
-                osi_Assert(cacheFp);
+               if (cacheFp == NULL) {
+                   /* Problem getting the inode */
+                   goto out;
+               }
                if (!cacheFp->f_dentry->d_inode->i_mapping->a_ops->readpage) {
                    cachefs_noreadpage = 1;
                    goto out;
@@ -2765,7 +2774,7 @@ afs_linux_readpages(struct file *fp, struct address_space *mapping,
     afs_lru_cache_finalize(&lrupages);
 
 out:
-    if (tdc)
+    if (cacheFp)
        filp_close(cacheFp, NULL);
 
     afs_pagecopy_put_task(task);