afs: remove redundant assignment
[openafs.git] / src / afs / afs_buffer.c
index 2810d9d..76c2b7c 100644 (file)
@@ -147,8 +147,22 @@ DInit(int abuffers)
     return;
 }
 
+/*!
+ * Read and return the requested directory page.
+ *
+ * \param[in]   adc    pointer to directory dcache
+ * \param[in]  page    number of the desired directory page
+ * \param[out] entry   buffer to return requested page
+ * \param[out] physerr (optional) pointer to return errno, if any
+ *
+ * \retval 0       success
+ * \retval non-zero invalid directory or internal IO error;
+ *                 if physerr is supplied by caller, it will be set:
+ *                     0       logical error
+ *                     errno   physical error
+ */
 int
-DRead(struct dcache *adc, int page, struct DirBuffer *entry)
+DReadWithErrno(struct dcache *adc, int page, struct DirBuffer *entry, int *physerr)
 {
     /* Read a page from the disk. */
     struct buffer *tb, *tb2;
@@ -157,8 +171,20 @@ DRead(struct dcache *adc, int page, struct DirBuffer *entry)
 
     AFS_STATCNT(DRead);
 
+    if (physerr != NULL)
+       *physerr = 0;
+
     memset(entry, 0, sizeof(struct DirBuffer));
 
+    if (adc->f.chunk == 0 && adc->f.chunkBytes == 0) {
+        /* The directory blob is empty, apparently. This is not a valid dir
+         * blob, so throw an error. */
+        return EIO;
+    }
+    if (page * AFS_BUFFER_PAGESIZE >= adc->f.chunkBytes) {
+        return ENOENT; /* past the end */
+    }
+
     ObtainWriteLock(&afs_bufferLock, 256);
 
 #define bufmatch(tb) (tb->page == page && tb->fid == adc->index)
@@ -231,24 +257,20 @@ DRead(struct dcache *adc, int page, struct DirBuffer *entry)
     ObtainWriteLock(&tb->lock, 260);
     tb->lockers++;
     ReleaseWriteLock(&afs_bufferLock);
-    if (page * AFS_BUFFER_PAGESIZE >= adc->f.chunkBytes) {
-       tb->fid = NULLIDX;
-       afs_reset_inode(&tb->inode);
-       tb->lockers--;
-       ReleaseWriteLock(&tb->lock);
-       return EIO;
-    }
     tfile = afs_CFileOpen(&adc->f.inode);
+    if (!tfile) {
+       code = EIO;
+       goto error;
+    }
     code =
        afs_CFileRead(tfile, tb->page * AFS_BUFFER_PAGESIZE, tb->data,
                      AFS_BUFFER_PAGESIZE);
     afs_CFileClose(tfile);
     if (code < AFS_BUFFER_PAGESIZE) {
-       tb->fid = NULLIDX;
-       afs_reset_inode(&tb->inode);
-       tb->lockers--;
-       ReleaseWriteLock(&tb->lock);
-       return EIO;
+       if (code < 0 && physerr != NULL)
+          *physerr = -code;
+       code = EIO;
+       goto error;
     }
     /* Note that findslot sets the page field in the buffer equal to
      * what it is searching for. */
@@ -256,6 +278,29 @@ DRead(struct dcache *adc, int page, struct DirBuffer *entry)
     entry->buffer = tb;
     entry->data = tb->data;
     return 0;
+
+ error:
+    tb->fid = NULLIDX;
+    afs_reset_inode(&tb->inode);
+    tb->lockers--;
+    ReleaseWriteLock(&tb->lock);
+    return code;
+}
+
+/*!
+ * Read and return the requested directory page.
+ *
+ * \param[in]   adc    pointer to directory dcache
+ * \param[in]  page    number of the desired directory page
+ * \param[out] entry   buffer to return requested page
+ *
+ * \retval 0       success
+ * \retval non-zero invalid directory or internal IO error;
+ */
+int
+DRead(struct dcache *adc, int page, struct DirBuffer *entry)
+{
+    return DReadWithErrno(adc, page, entry, NULL);
 }
 
 static void
@@ -372,6 +417,9 @@ afs_newslot(struct dcache *adc, afs_int32 apage, struct buffer *lp)
     if (lp->dirty) {
        /* see DFlush for rationale for not getting and locking the dcache */
         tfile = afs_CFileOpen(&lp->inode);
+       if (!tfile)
+           return NULL;    /* Callers will flag as EIO */
+
        afs_CFileWrite(tfile, lp->page * AFS_BUFFER_PAGESIZE, lp->data,
                       AFS_BUFFER_PAGESIZE);
        lp->dirty = 0;
@@ -379,6 +427,8 @@ afs_newslot(struct dcache *adc, afs_int32 apage, struct buffer *lp)
        AFS_STATS(afs_stats_cmperf.bufFlushDirty++);
     }
 
+    /* Zero out the data so we don't leak something we shouldn't. */
+    memset(lp->data, 0, AFS_BUFFER_PAGESIZE);
     /* Now fill in the header. */
     lp->fid = adc->index;
     afs_copy_inode(&lp->inode, &adc->f.inode);
@@ -400,7 +450,6 @@ DRelease(struct DirBuffer *entry, int flag)
     if (tp == NULL)
        return;
 
-    tp = entry->buffer;
     ObtainWriteLock(&tp->lock, 261);
     tp->lockers--;
     if (flag)
@@ -459,6 +508,7 @@ DFlushBuffer(struct buffer *ab)
     struct osi_file *tfile;
 
     tfile = afs_CFileOpen(&ab->inode);
+    osi_Assert(tfile);
     afs_CFileWrite(tfile, ab->page * AFS_BUFFER_PAGESIZE,
                   ab->data, AFS_BUFFER_PAGESIZE);
     ab->dirty = 0;     /* Clear the dirty flag */
@@ -570,17 +620,20 @@ shutdown_bufferpackage(void)
     AFS_STATCNT(shutdown_bufferpackage);
     /* Free all allocated Buffers and associated buffer pages */
     DFlush();
+
+    dinit_flag = 0;
+    tp = Buffers;
+    for (i = 0; i < nbuffers; i += NPB, tp += NPB) {
+       afs_osi_Free(tp->data, NPB * AFS_BUFFER_PAGESIZE);
+    }
+    afs_osi_Free(Buffers, nbuffers * sizeof(struct buffer));
+    Buffers = NULL;
+    nbuffers = 0;
+    timecounter = 1;
+    for (i = 0; i < PHSIZE; i++)
+       phTable[i] = NULL;
+
     if (afs_cold_shutdown) {
-       dinit_flag = 0;
-       tp = Buffers;
-       for (i = 0; i < nbuffers; i += NPB, tp += NPB) {
-           afs_osi_Free(tp->data, NPB * AFS_BUFFER_PAGESIZE);
-       }
-       afs_osi_Free(Buffers, nbuffers * sizeof(struct buffer));
-       nbuffers = 0;
-       timecounter = 1;
-       for (i = 0; i < PHSIZE; i++)
-           phTable[i] = 0;
        memset(&afs_bufferLock, 0, sizeof(afs_lock_t));
     }
 }