afs: avoid panic in DNew when afs_WriteDCache fails 04/13804/13
authorMark Vitale <mvitale@sinenomine.net>
Fri, 19 Jul 2019 18:41:55 +0000 (14:41 -0400)
committerBenjamin Kaduk <kaduk@mit.edu>
Fri, 6 Nov 2020 20:51:35 +0000 (15:51 -0500)
afs_WriteDCache may fail for an IO error, or if interrupted (EINTR).
Unfortunately, DNew will panic in this case, crashing the entire
machine.

In order to avoid an outage in this case, don't panic.  Instead, reflect
the error back to the caller of DNew.

While here, add Doxygen comments to DNew.

Change-Id: I27a8f89bab979c5691dded70e8b9eacbe8aff4fd
Reviewed-on: https://gerrit.openafs.org/13804
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>

src/afs/afs_buffer.c

index 76c2b7c..ef0ee18 100644 (file)
@@ -579,12 +579,24 @@ DFlush(void)
     return 0;
 }
 
+/*!
+ * Prepare a new directory page buffer
+ *
+ * \param adc      pointer to the directory object dcache
+ * \param nblobs    page we want
+ * \param entry            buffer to return requested page
+ *
+ * \retval 0       success; entry is updated
+ * \retval non-zero internal error or IO error writing to disk
+ */
 int
 DNew(struct dcache *adc, int page, struct DirBuffer *entry)
 {
     /* Same as read, only do *not* even try to read the page, since it
      * probably doesn't exist. */
     struct buffer *tb;
+    int code;
+
     AFS_STATCNT(DNew);
 
     ObtainWriteLock(&afs_bufferLock, 264);
@@ -599,7 +611,11 @@ DNew(struct dcache *adc, int page, struct DirBuffer *entry)
      * DFlush due to lock hierarchy issues */
     if ((page + 1) * AFS_BUFFER_PAGESIZE > adc->f.chunkBytes) {
        afs_AdjustSize(adc, (page + 1) * AFS_BUFFER_PAGESIZE);
-       osi_Assert(afs_WriteDCache(adc, 1) == 0);
+       code = afs_WriteDCache(adc, 1);
+       if (code) {
+           ReleaseWriteLock(&afs_bufferLock);
+           return code;
+       }
     }
     ObtainWriteLock(&tb->lock, 265);
     tb->lockers++;