afs: free the Buffers array correctly during shutdown
[openafs.git] / src / afs / afs_buffer.c
index 99af18e..c7a394d 100644 (file)
@@ -153,12 +153,16 @@ DInit(int abuffers)
  * \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
+ * \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;
@@ -167,6 +171,9 @@ 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) {
@@ -260,6 +267,8 @@ DRead(struct dcache *adc, int page, struct DirBuffer *entry)
                      AFS_BUFFER_PAGESIZE);
     afs_CFileClose(tfile);
     if (code < AFS_BUFFER_PAGESIZE) {
+       if (code < 0 && physerr != NULL)
+          *physerr = -code;
        code = EIO;
        goto error;
     }
@@ -278,6 +287,22 @@ DRead(struct dcache *adc, int page, struct DirBuffer *entry)
     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
 FixupBucket(struct buffer *ap)
 {
@@ -425,7 +450,6 @@ DRelease(struct DirBuffer *entry, int flag)
     if (tp == NULL)
        return;
 
-    tp = entry->buffer;
     ObtainWriteLock(&tp->lock, 261);
     tp->lockers--;
     if (flag)
@@ -555,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);
@@ -575,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++;
@@ -602,7 +642,7 @@ shutdown_bufferpackage(void)
     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));
+    afs_osi_Free(Buffers, afs_max_buffers * sizeof(struct buffer));
     Buffers = NULL;
     nbuffers = 0;
     timecounter = 1;