From 9b0d5f274fe79ccc5dd0e4bba86b3f52b27d3586 Mon Sep 17 00:00:00 2001 From: Michael Meffie Date: Fri, 18 Dec 2009 08:20:24 -0500 Subject: [PATCH] return an error from afs_readdir when out of buffers 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 Tested-by: BuildBot --- src/afs/LINUX/osi_vnodeops.c | 8 +++---- src/afs/VNOPS/afs_vnop_lookup.c | 8 +++---- src/afs/VNOPS/afs_vnop_readdir.c | 47 ++++++++++++++++++++++------------------ 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/afs/LINUX/osi_vnodeops.c b/src/afs/LINUX/osi_vnodeops.c index 36d00d4..e0dcca9 100644 --- a/src/afs/LINUX/osi_vnodeops.c +++ b/src/afs/LINUX/osi_vnodeops.c @@ -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); diff --git a/src/afs/VNOPS/afs_vnop_lookup.c b/src/afs/VNOPS/afs_vnop_lookup.c index d194025..ff641e0 100644 --- a/src/afs/VNOPS/afs_vnop_lookup.c +++ b/src/afs/VNOPS/afs_vnop_lookup.c @@ -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 */ diff --git a/src/afs/VNOPS/afs_vnop_readdir.c b/src/afs/VNOPS/afs_vnop_readdir.c index d5aa00d..83e76dd 100644 --- a/src/afs/VNOPS/afs_vnop_readdir.c +++ b/src/afs/VNOPS/afs_vnop_readdir.c @@ -42,21 +42,24 @@ * 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); -- 1.9.4