return an error from afs_readdir when out of buffers
authorMichael Meffie <mmeffie@sinenomine.net>
Fri, 18 Dec 2009 13:20:24 +0000 (08:20 -0500)
committerBenjamin Kaduk <kaduk@mit.edu>
Mon, 31 Aug 2015 21:25:18 +0000 (17:25 -0400)
Instead of silently failing, return EIO from readdir when the
cache manager is unable to allocate a buffer in afs_newslot,
(afs: all buffers locked).

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

src/afs/LINUX/osi_vnodeops.c
src/afs/VNOPS/afs_vnop_lookup.c
src/afs/VNOPS/afs_vnop_readdir.c

index 36d00d4..e0dcca9 100644 (file)
@@ -289,7 +289,7 @@ afs_linux_write(struct file *fp, const char *buf, size_t count, loff_t * offp)
 }
 #endif
 
-extern int BlobScan(struct dcache * afile, afs_int32 ablob);
+extern int BlobScan(struct dcache * afile, afs_int32 ablob, afs_int32 *ablobOut);
 
 /* This is a complete rewrite of afs_readdir, since we can make use of
  * filldir instead of afs_readdir_move. Note that changes to vcache/dcache
@@ -307,7 +307,7 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
     struct dcache *tdc;
     int code;
     int offset;
-    int dirpos;
+    afs_int32 dirpos;
     struct DirEntry *de;
     struct DirBuffer entry;
     ino_t ino;
@@ -385,8 +385,8 @@ afs_linux_readdir(struct file *fp, void *dirbuf, filldir_t filldir)
     offset = (int) fp->f_pos;
 #endif
     while (1) {
-       dirpos = BlobScan(tdc, offset);
-       if (!dirpos)
+       code = BlobScan(tdc, offset, &dirpos);
+       if (code || !dirpos)
            break;
 
        code = afs_dir_GetVerifiedBlob(tdc, dirpos, &entry);
index d194025..ff641e0 100644 (file)
@@ -648,7 +648,7 @@ afs_CheckBulkStatus(struct afs_conn *tc, int nFids, AFSBulkStats *statParm,
     return 0;
 }
 
-extern int BlobScan(struct dcache * afile, afs_int32 ablob);
+extern int BlobScan(struct dcache * afile, afs_int32 ablob, afs_int32 *ablobOut);
 
 /* called with an unlocked directory and directory cookie.  Areqp
  * describes who is making the call.
@@ -699,7 +699,7 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
     int ftype[4] = {VNON, VREG, VDIR, VLNK}; /* verify type is as expected */
     afs_size_t statSeqNo = 0;  /* Valued of file size to detect races */
     int code;                  /* error code */
-    long newIndex;             /* new index in the dir */
+    afs_int32 newIndex;                /* new index in the dir */
     struct DirBuffer entry;    /* Buffer for dir manipulation */
     struct DirEntry *dirEntryp;        /* dir entry we are examining */
     int i;
@@ -808,8 +808,8 @@ afs_DoBulkStat(struct vcache *adp, long dirCookie, struct vrequest *areqp)
        /* look for first safe entry to examine in the directory.  BlobScan
         * looks for a the 1st allocated dir after the dirCookie slot.
         */
-       newIndex = BlobScan(dcp, (dirCookie >> 5));
-       if (newIndex == 0)
+       code = BlobScan(dcp, (dirCookie >> 5), &newIndex);
+       if (code || newIndex == 0)
            break;
 
        /* remember the updated directory cookie */
index d5aa00d..83e76dd 100644 (file)
  * AFS readdir vnodeop and bulk stat support.
  */
 
-/* BlobScan is supposed to ensure that the blob reference refers to a valid
-    directory entry.  It consults the allocation map in the page header
-    to determine whether a blob is actually in use or not.
-
-    More formally, BlobScan is supposed to return a new blob number which is just like
-    the input parameter, only it is advanced over header or free blobs.
-    
-    Note that BlobScan switches pages if necessary.  BlobScan may return
-    either 0 or an out-of-range blob number for end of file.
-
-    BlobScan is used by the Linux port in a separate file, so it should not
-    become static.
-*/
+/**
+ * Ensure that the blob reference refers to a valid directory entry.
+ * It consults the allocation map in the page header to determine
+ * whether a blob is actually in use or not.
+ *
+ * More formally, BlobScan is supposed to return a new blob number
+ * which is just like the input parameter, only it is advanced over
+ * header or free blobs.
+ *
+ * Note that BlobScan switches pages if necessary.  BlobScan may
+ * return either 0 for success or an error code.  Upon successful
+ * return, the new blob value is assigned to *ablobOut.
+ *
+ * BlobScan is used by the Linux port in a separate file, so it should not
+ * become static.
+ */
 int
-BlobScan(struct dcache * afile, afs_int32 ablob)
+BlobScan(struct dcache * afile, afs_int32 ablob, int *ablobOut)
 {
     afs_int32 relativeBlob;
     afs_int32 pageBlob;
@@ -71,7 +74,7 @@ BlobScan(struct dcache * afile, afs_int32 ablob)
        pageBlob = ablob & ~(EPP - 1);  /* base blob in same page */
        code = afs_dir_GetBlob(afile, pageBlob, &headerbuf);
        if (code)
-           return 0;
+           return code;
        tpe = (struct PageHeader *)headerbuf.data;
 
        relativeBlob = ablob - pageBlob;        /* relative to page's first blob */
@@ -92,8 +95,10 @@ BlobScan(struct dcache * afile, afs_int32 ablob)
        /* now relativeBlob is the page-relative first allocated blob,
         * or EPP (if there are none in this page). */
        DRelease(&headerbuf, 0);
-       if (i != EPP)
-           return i + pageBlob;
+       if (i != EPP) {
+           *ablobOut = i + pageBlob;
+           return 0;
+       }
        ablob = pageBlob + EPP; /* go around again */
     }
     /* never get here */
@@ -588,7 +593,7 @@ afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
     struct DirBuffer oldEntry, nextEntry;
     struct DirEntry *ode = 0, *nde = 0;
     int o_slen = 0, n_slen = 0;
-    afs_uint32 us;
+    afs_int32 us;
     struct afs_fakestat_state fakestate;
 #if defined(AFS_SGI53_ENV)
     afs_int32 use64BitDirent, dirsiz;
@@ -732,9 +737,9 @@ afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
        origOffset = AFS_UIO_OFFSET(auio);
        /* scan for the next interesting entry scan for in-use blob otherwise up point at
         * this blob note that ode, if non-zero, also represents a held dir page */
-       us = BlobScan(tdc, (origOffset >> 5));
+       code = BlobScan(tdc, (origOffset >> 5), &us);
 
-       if (us)
+       if (code == 0 && us)
           code = afs_dir_GetVerifiedBlob(tdc, us, &nextEntry);
 
        if (us == 0 || code != 0) {
@@ -910,7 +915,7 @@ afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
        DRelease(&oldEntry, 0);
        oldEntry = nextEntry;
        ode = nde;
-       AFS_UIO_SETOFFSET(auio, (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5));
+       AFS_UIO_SETOFFSET(auio, (us + afs_dir_NameBlobs(nde->name)) << 5);
     }
     
     DRelease(&oldEntry, 0);