* afs_readdir_move
* afs_bulkstat_send
* afs_readdir/afs_readdir2(HP)
- * afs_readdir1 - HP and DUX NFS versions
+ * afs_readdir1 - HP NFS version
*
*/
#include <afsconfig.h>
#include "afs/param.h"
-RCSID
- ("$Header$");
#include "afs/sysincludes.h" /* Standard vendor system headers */
#include "afsincludes.h" /* Afs-based standard headers */
#include "afs/nfsclient.h"
#include "afs/afs_osidnlc.h"
-
-#if defined(AFS_HPUX1122_ENV)
+#if defined(AFS_HPUX1122_ENV)
+#define DIRPAD 7
+#elif defined(AFS_NBSD40_ENV)
#define DIRPAD 7
#else
#define DIRPAD 3
#endif
-/**
- * A few definitions. This is until we have a proper header file
- * which ahs prototypes for all functions
- */
-extern struct DirEntry *afs_dir_GetBlob();
/*
* AFS readdir vnodeop and bulk stat support.
*/
-/* Saber C hates negative inode #s. We're not going to talk about software
- * that could fail if it sees a negative inode #.
- */
-#define FIXUPSTUPIDINODE(a) ((a) &= 0x7fffffff)
-
/* 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.
become static.
*/
int
-BlobScan(struct fcache * afile, afs_int32 ablob)
+BlobScan(struct dcache * afile, afs_int32 ablob)
{
- register afs_int32 relativeBlob;
+ afs_int32 relativeBlob;
afs_int32 pageBlob;
- register struct PageHeader *tpe;
- register afs_int32 i;
+ struct PageHeader *tpe;
+ struct DirBuffer headerbuf;
+ afs_int32 i;
+ int code;
AFS_STATCNT(BlobScan);
/* advance ablob over free and header blobs */
while (1) {
pageBlob = ablob & ~(EPP - 1); /* base blob in same page */
- tpe = (struct PageHeader *)afs_dir_GetBlob(afile, pageBlob);
- if (!tpe)
- return 0; /* we've past the end */
+ code = afs_dir_GetBlob(afile, pageBlob, &headerbuf);
+ if (code)
+ return 0;
+ tpe = (struct PageHeader *)headerbuf.data;
+
relativeBlob = ablob - pageBlob; /* relative to page's first blob */
/* first watch for headers */
if (pageBlob == 0) { /* first dir page has extra-big header */
}
/* now relativeBlob is the page-relative first allocated blob,
* or EPP (if there are none in this page). */
- DRelease((struct buffer *)tpe, 0);
+ DRelease(&headerbuf, 0);
if (i != EPP)
return i + pageBlob;
ablob = pageBlob + EPP; /* go around again */
/* never get here */
}
+
#if !defined(AFS_LINUX20_ENV)
/* Changes to afs_readdir which affect dcache or vcache handling or use of
* bulk stat data should also be reflected in the Linux specific verison of
#else
struct min_direct { /* miniature direct structure */
/* If struct direct changes, this must too */
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_DARWIN80_ENV)
+ ino_t d_fileno;
+ u_short d_reclen;
+ u_char d_type;
+ u_char d_namlen;
+#elif defined(AFS_NBSD40_ENV)
+ ino_t d_fileno; /* file number of entry */
+ uint16_t d_reclen; /* length of this record */
+ uint16_t d_namlen; /* length of string in d_name */
+ uint8_t d_type; /* file type, see below */
+#elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
afs_uint32 d_fileno;
u_short d_reclen;
u_char d_type;
u_char d_namlen;
-#else
-#ifdef AFS_SUN5_ENV
+#elif defined(AFS_SUN5_ENV)
afs_uint32 d_fileno;
afs_int32 d_off;
u_short d_reclen;
#else
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
+#if defined(AFS_AIX32_ENV)
afs_int32 d_off;
-#endif
-#if defined(AFS_HPUX100_ENV)
+#elif defined(AFS_HPUX100_ENV)
unsigned long long d_off;
#endif
afs_uint32 d_fileno;
u_short d_reclen;
u_short d_namlen;
#endif
-#endif
};
#endif /* AFS_SGI_ENV */
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
+#if defined(AFS_HPUX_ENV)
struct minnfs_direct {
afs_int32 d_off; /* XXX */
afs_uint32 d_fileno;
#define DIRSIZ_LEN(len) \
((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + DIRPAD) &~ DIRPAD))
#else
-#if defined(AFS_SUN56_ENV)
+#if defined(AFS_SUN5_ENV)
#define DIRSIZ_LEN(len) ((18 + (len) + 1 + 7) & ~7 )
#else
-#ifdef AFS_SUN5_ENV
-#define DIRSIZ_LEN(len) ((10 + (len) + 1 + (NBPW-1)) & ~(NBPW-1))
+#ifdef AFS_NBSD40_ENV
+#define DIRSIZ_LEN(len) \
+ ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((len)+1 + 7) & ~7))
#else
#ifdef AFS_DIRENT
#define DIRSIZ_LEN(len) \
((sizeof (struct direct) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
#endif /* AFS_SGI_ENV */
#endif /* AFS_DIRENT */
+#endif /* AFS_NBSD40_ENV */
#endif /* AFS_SUN5_ENV */
-#endif /* AFS_SUN56_ENV */
#endif /* AFS_HPUX100_ENV */
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
int
-afs_readdir_type(avc, ade)
- struct DirEntry *ade;
- struct vcache *avc;
+afs_readdir_type(struct vcache *avc, struct DirEntry *ade)
{
struct VenusFid tfid;
struct vcache *tvc;
int vtype;
- tfid.Cell = avc->fid.Cell;
- tfid.Fid.Volume = avc->fid.Fid.Volume;
+ tfid.Cell = avc->f.fid.Cell;
+ tfid.Fid.Volume = avc->f.fid.Fid.Volume;
tfid.Fid.Vnode = ntohl(ade->fid.vnode);
tfid.Fid.Unique = ntohl(ade->fid.vunique);
- if ((avc->states & CForeign) == 0 && (ntohl(ade->fid.vnode) & 1)) {
+ if ((avc->f.states & CForeign) == 0 && (ntohl(ade->fid.vnode) & 1)) {
return DT_DIR;
- } else if ((tvc = afs_FindVCache(&tfid, 0, 0))) {
- if (tvc->mvstat) {
+ }
+ ObtainReadLock(&afs_xvcache);
+ if ((tvc = afs_FindVCache(&tfid, 0, 0))) {
+ ReleaseReadLock(&afs_xvcache);
+ if (tvc->mvstat != AFS_MVSTAT_FILE) {
afs_PutVCache(tvc);
return DT_DIR;
- } else if (((tvc->states) & (CStatd | CTruth))) {
+ } else if (((tvc->f.states) & (CStatd | CTruth))) {
/* CTruth will be set if the object has
*ever* been statd */
vtype = vType(tvc);
else if (vtype == VREG)
return DT_REG;
/* Don't do this until we're sure it can't be a mtpt */
- /* else if (vtype == VLNK)
- * type=DT_LNK; */
+ /* if we're CStatd and CTruth and mvstat==AFS_MVSTAT_FILE, it's a link */
+ else if (vtype == VLNK)
+ return DT_LNK;
/* what other types does AFS support? */
} else
afs_PutVCache(tvc);
- }
+ } else
+ ReleaseReadLock(&afs_xvcache);
return DT_UNKNOWN;
}
#endif
#endif
char bufofzeros[64]; /* gotta fill with something */
-int
-afs_readdir_move(de, vc, auio, slen, rlen, off)
- struct DirEntry *de;
- struct vcache *vc;
- struct uio *auio;
- int slen;
#ifdef AFS_SGI65_ENV
- ssize_t rlen;
+int
+afs_readdir_move(struct DirEntry *de, struct vcache *vc, struct uio *auio,
+ int slen, ssize_t rlen, afs_size_t off)
#else
- int rlen;
+int
+afs_readdir_move(struct DirEntry *de, struct vcache *vc, struct uio *auio,
+ int slen, int rlen, afs_size_t off)
#endif
- afs_size_t off;
{
int code = 0;
-#if defined(AFS_SUN56_ENV)
+ struct volume *tvp;
+ afs_uint32 Volume = vc->f.fid.Fid.Volume;
+ afs_uint32 Vnode = de->fid.vnode;
+#if defined(AFS_SUN5_ENV)
struct dirent64 *direntp;
#else
-#if defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
+#if (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
struct dirent *direntp;
#endif
-#endif /* AFS_SUN56_ENV */
+#endif /* AFS_SUN5_ENV */
#ifndef AFS_SGI53_ENV
struct min_direct sdirEntry;
#endif /* AFS_SGI53_ENV */
AFS_STATCNT(afs_readdir_move);
+
+#define READDIR_CORRECT_INUMS
+#ifdef READDIR_CORRECT_INUMS
+ if (de->name[0] == '.' && !de->name[1]) {
+ /* This is the '.' entry; if we are a volume root, we need to
+ * ignore the directory and use the inum for the mount point.
+ */
+ if (!FidCmp(&afs_rootFid, &vc->f.fid)) {
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvstat == AFS_MVSTAT_ROOT) {
+ tvp = afs_GetVolume(&vc->f.fid, 0, READ_LOCK);
+ if (tvp) {
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ }
+ }
+ else if (de->name[0] == '.' && de->name[1] == '.' && !de->name[2]) {
+ /* This is the '..' entry. Getting this right is very tricky,
+ * because we might be a volume root (so our parent is in a
+ * different volume), or our parent might be a volume root
+ * (so we actually want the mount point) or BOTH! */
+ if (!FidCmp(&afs_rootFid, &vc->f.fid)) {
+ /* We are the root of the AFS root, and thus our own parent */
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvstat == AFS_MVSTAT_ROOT) {
+ /* We are a volume root, which means our parent is in another
+ * volume. Luckily, we should have his fid cached... */
+ if (vc->mvid.parent) {
+ if (!FidCmp(&afs_rootFid, vc->mvid.parent)) {
+ /* Parent directory is the root of the AFS root */
+ Volume = 0;
+ Vnode = 2;
+ } else if (vc->mvid.parent->Fid.Vnode == 1
+ && vc->mvid.parent->Fid.Unique == 1) {
+ /* XXX The above test is evil and probably breaks DFS */
+ /* Parent directory is the target of a mount point */
+ tvp = afs_GetVolume(vc->mvid.parent, 0, READ_LOCK);
+ if (tvp) {
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ } else {
+ /* Parent directory is not a volume root */
+ Volume = vc->mvid.parent->Fid.Volume;
+ Vnode = vc->mvid.parent->Fid.Vnode;
+ }
+ }
+ } else if (de->fid.vnode == 1 && de->fid.vunique == 1) {
+ /* XXX The above test is evil and probably breaks DFS */
+ /* Parent directory is a volume root; use the right inum */
+ tvp = afs_GetVolume(&vc->f.fid, 0, READ_LOCK);
+ if (tvp) {
+ if (tvp->cell == afs_rootFid.Cell
+ && tvp->volume == afs_rootFid.Fid.Volume) {
+ /* Parent directory is the root of the AFS root */
+ Volume = 0;
+ Vnode = 2;
+ } else {
+ /* Parent directory is the target of a mount point */
+ Volume = tvp->mtpoint.Fid.Volume;
+ Vnode = tvp->mtpoint.Fid.Vnode;
+ }
+ afs_PutVolume(tvp, READ_LOCK);
+ }
+ }
+ }
+#endif
+
#ifdef AFS_SGI53_ENV
{
afs_int32 use64BitDirent;
if (use64BitDirent) {
struct min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
+ sdirEntry.d_fileno = afs_calc_inum(vc->f.fid.Cell,
+ Volume, ntohl(Vnode));
sdirEntry.d_reclen = rlen;
sdirEntry.d_off = (off_t) off;
AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio,
}
} else {
struct irix5_min_dirent sdirEntry;
- sdirEntry.d_fileno =
- (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
+ sdirEntry.d_fileno = afs_calc_inum(vc->f.fid.Cell,
+ Volume, ntohl(Vnode));
sdirEntry.d_reclen = rlen;
sdirEntry.d_off = (afs_int32) off;
AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio,
}
#else /* AFS_SGI53_ENV */
#if defined(AFS_SUN5_ENV) || (defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL))
-#if defined(AFS_SUN56_ENV)
- direntp = (struct dirent64 *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-#else
- direntp = (struct dirent *)osi_AllocLargeSpace(AFS_LRALLOCSIZ);
-#endif
- direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(direntp->d_ino);
+ direntp = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ direntp->d_ino = afs_calc_inum(vc->f.fid.Cell, Volume, ntohl(Vnode));
#if defined(AFS_AIX51_ENV) && defined(AFS_64BIT_KERNEL)
direntp->d_offset = off;
direntp->d_namlen = slen;
osi_FreeLargeSpace((char *)direntp);
#else /* AFS_SUN5_ENV */
/* Note the odd mechanism for building the inode number */
- sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry.d_fileno);
+ sdirEntry.d_fileno = afs_calc_inum(vc->f.fid.Cell, Volume, ntohl(Vnode));
sdirEntry.d_reclen = rlen;
#if !defined(AFS_SGI_ENV)
sdirEntry.d_namlen = slen;
#endif
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
+#if defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
sdirEntry.d_off = off;
#endif
#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
auio, code);
#else /* AFS_SGI_ENV */
AFS_MOVE_UNLOCK();
- AFS_UIOMOVE((char *)&sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
-
+#if defined(AFS_NBSD40_ENV)
+ {
+ struct dirent *dp;
+ dp = osi_AllocLargeSpace(sizeof(struct dirent));
+ memset(dp, 0, sizeof(struct dirent));
+ dp->d_ino = afs_calc_inum(vc->f.fid.Cell, Volume, ntohl(Vnode));
+ dp->d_namlen = slen;
+ dp->d_type = afs_readdir_type(vc, de);
+ strcpy(dp->d_name, de->name);
+ dp->d_reclen = _DIRENT_SIZE(dp) /* rlen */;
+ if ((afs_debug & AFSDEB_VNLAYER) != 0) {
+ afs_warn("%s: %s type %d slen %d rlen %d act. rlen %zu\n", __func__,
+ dp->d_name, dp->d_type, slen, rlen, _DIRENT_SIZE(dp));
+ }
+ AFS_UIOMOVE(dp, dp->d_reclen, UIO_READ, auio, code);
+ osi_FreeLargeSpace((char *)dp);
+ }
+#else
+ AFS_UIOMOVE((char *) &sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
if (code == 0) {
AFS_UIOMOVE(de->name, slen, UIO_READ, auio, code);
}
-
/* pad out the remaining characters with zeros */
if (code == 0) {
AFS_UIOMOVE(bufofzeros, ((slen + 1 + DIRPAD) & ~DIRPAD) - slen,
UIO_READ, auio, code);
}
+#endif
AFS_MOVE_LOCK();
#endif /* AFS_SGI_ENV */
-
+#if !defined(AFS_NBSD_ENV)
/* pad out the difference between rlen and slen... */
if (DIRSIZ_LEN(slen) < rlen) {
AFS_MOVE_UNLOCK();
}
AFS_MOVE_LOCK();
}
+#endif
#endif /* AFS_SUN5_ENV */
#endif /* AFS_SGI53_ENV */
return (code);
*/
void
-afs_bulkstat_send(avc, req)
- struct vcache *avc;
- struct vrequest *req;
+afs_bulkstat_send(struct vcache *avc, struct vrequest *req)
{
afs_rd_stash_i = 0;
}
*/
int
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_readdir(OSI_VC_ARG(avc), auio, acred, eofp)
- int *eofp;
+#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred,
+ int *eofp)
#else
#if defined(AFS_HPUX100_ENV)
-afs_readdir2(OSI_VC_ARG(avc), auio, acred)
+afs_readdir2(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
#else
-afs_readdir(OSI_VC_ARG(avc), auio, acred)
+afs_readdir(OSI_VC_DECL(avc), struct uio *auio, afs_ucred_t *acred)
#endif
#endif
- OSI_VC_DECL(avc);
- struct uio *auio;
- struct AFS_UCRED *acred;
{
- struct vrequest treq;
- register struct dcache *tdc;
+ struct vrequest *treq = NULL;
+ struct dcache *tdc;
afs_size_t origOffset, tlen;
afs_int32 len;
int code = 0;
+ struct DirBuffer oldEntry, nextEntry;
struct DirEntry *ode = 0, *nde = 0;
int o_slen = 0, n_slen = 0;
afs_uint32 us;
#if defined(AFS_SGI53_ENV)
afs_int32 use64BitDirent, dirsiz;
#endif /* defined(AFS_SGI53_ENV) */
+#ifndef AFS_HPUX_ENV
OSI_VC_CONVERT(avc);
-#ifdef AFS_HPUX_ENV
+#else
/*
* XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
* it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
* translator side XXX
*/
- struct min_direct *sdirEntry =
- (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
+ struct min_direct *sdirEntry = osi_AllocSmallSpace(sizeof(struct min_direct));
afs_int32 rlen;
#endif
*/
AFS_STATCNT(afs_readdir);
+ memset(&oldEntry, 0, sizeof(struct DirBuffer));
+ memset(&nextEntry, 0, sizeof(struct DirBuffer));
+
#if defined(AFS_SGI53_ENV)
#ifdef AFS_SGI61_ENV
#ifdef AFS_SGI62_ENV
#endif /* AFS_SGI61_ENV */
#endif /* defined(AFS_SGI53_ENV) */
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
/* Not really used by the callee so we ignore it for now */
if (eofp)
*eofp = 0;
#endif
+#ifndef AFS_64BIT_CLIENT
if (AfsLargeFileUio(auio) /* file is large than 2 GB */
- ||AfsLargeFileSize(auio->uio_offset, auio->uio_resid))
+ ||AfsLargeFileSize(AFS_UIO_OFFSET(auio), AFS_UIO_RESID(auio)))
return EFBIG;
+#endif
- if ((code = afs_InitReq(&treq, acred))) {
+ if ((code = afs_CreateReq(&treq, acred))) {
#ifdef AFS_HPUX_ENV
osi_FreeSmallSpace((char *)sdirEntry);
#endif
}
/* update the cache entry */
afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
+
+ AFS_DISCON_LOCK();
+
+ code = afs_EvalFakeStat(&avc, &fakestate, treq);
if (code)
goto done;
tagain:
- code = afs_VerifyVCache(avc, &treq);
+ code = afs_VerifyVCache(avc, treq);
if (code)
goto done;
/* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
- len = tlen;
+ tdc = afs_GetDCache(avc, (afs_size_t) 0, treq, &origOffset, &tlen, 1);
if (!tdc) {
code = ENOENT;
goto done;
* 1. The cache data is being fetched by another process.
* 2. The cache data is no longer valid
*/
- while ((avc->states & CStatd)
+ while ((avc->f.states & CStatd)
&& (tdc->dflags & DFFetching)
- && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+ && hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
__FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
ICL_TYPE_INT32, tdc->dflags);
ObtainReadLock(&avc->lock);
ObtainReadLock(&tdc->lock);
}
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
+ if (!(avc->f.states & CStatd)
+ || !hsame(avc->f.m.DataVersion, tdc->f.versionNo)) {
ReleaseReadLock(&tdc->lock);
ReleaseReadLock(&avc->lock);
afs_PutDCache(tdc);
auio->uio_fpflags = 0;
#endif
while (code == 0) {
- origOffset = auio->afsio_offset;
+ 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 */
- if (!(us = BlobScan(&tdc->f, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f, us))) {
+ us = BlobScan(tdc, (origOffset >> 5));
+
+ if (us)
+ code = afs_dir_GetVerifiedBlob(tdc, us, &nextEntry);
+
+ if (us == 0 || code != 0) {
+ code = 0; /* Reset code - keep old failure behaviour */
/* failed to setup nde, return what we've got, and release ode */
if (len) {
/* something to hand over. */
#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
+ sdirEntry->d_fileno = afs_calc_inum(avc->f.fid.Cell,
+ avc->f.fid.Fid.Volume,
+ ntohl(ode->fid.vnode));
+ sdirEntry->d_reclen = rlen = AFS_UIO_RESID(auio);
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
}
#else
code = afs_readdir_move(ode, avc, auio, o_slen,
-#if defined(AFS_SUN5_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_NBSD_ENV)
len, origOffset);
#else
- auio->afsio_resid, origOffset);
+ AFS_UIO_RESID(auio), origOffset);
#endif
#endif /* AFS_HPUX_ENV */
-#if !defined(AFS_SUN5_ENV)
- auio->afsio_resid = 0;
+#if !defined(AFS_SUN5_ENV) && !defined(AFS_NBSD_ENV)
+ AFS_UIO_SETRESID(auio, 0);
#endif
} else {
/* nothin to hand over */
}
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
if (eofp)
*eofp = 1; /* Set it properly */
#endif
- if (ode)
- DRelease((struct buffer *)ode, 0);
+ DRelease(&oldEntry, 0);
goto dirend;
}
- /* by here nde is set */
-
+ nde = (struct DirEntry *)nextEntry.data;
+
/* Do we have enough user space to carry out our mission? */
#if defined(AFS_SGI_ENV)
n_slen = strlen(nde->name) + 1; /* NULL terminate */
#ifdef AFS_SGI53_ENV
dirsiz =
use64BitDirent ? DIRENTSIZE(n_slen) : IRIX5_DIRENTSIZE(n_slen);
- if (dirsiz >= (auio->afsio_resid - len)) {
+ if (dirsiz >= (AFS_UIO_RESID(auio) - len)) {
#else
- if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
+ if (DIRSIZ_LEN(n_slen) >= (AFS_UIO_RESID(auio) - len)) {
#endif /* AFS_SGI53_ENV */
/* No can do no more now; ya know... at this time */
- DRelease((struct buffer *)nde, 0); /* can't use this one. */
+ DRelease(&nextEntry, 0); /* can't use this one. */
if (len) {
#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
+ sdirEntry->d_fileno = afs_calc_inum(avc->f.fid.Cell,
+ avc->f.fid.Fid.Volume,
+ ntohl(ode->fid.vnode));
+ sdirEntry->d_reclen = rlen = AFS_UIO_RESID(auio);
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
#else /* AFS_HPUX_ENV */
code =
afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
+ AFS_UIO_RESID(auio), origOffset);
#endif /* AFS_HPUX_ENV */
/* this next line used to be AFSVFS40 or AIX 3.1, but is
* really generic */
- auio->afsio_offset = origOffset;
- auio->afsio_resid = 0;
+ AFS_UIO_SETOFFSET(auio, origOffset);
+#if !defined(AFS_NBSD_ENV)
+ AFS_UIO_SETRESID(auio, 0);
+#endif
} else { /* trouble, can't give anything to the user! */
/* even though he has given us a buffer,
* even though we have something to give us,
*/
code = EINVAL;
}
- if (ode)
- DRelease((struct buffer *)ode, 0);
+ DRelease(&oldEntry, 0);
goto dirend;
}
*/
if (len) {
#ifdef AFS_HPUX_ENV
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
+ sdirEntry->d_fileno = afs_calc_inum(avc->f.fid.Cell,
+ avc->f.fid.Fid.Volume,
+ ntohl(ode->fid.vnode));
sdirEntry->d_reclen = rlen = len;
sdirEntry->d_namlen = o_slen;
-#if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
+#if defined(AFS_SUN5_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
sdirEntry->d_off = origOffset;
#endif
AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
#else
len = DIRSIZ_LEN(o_slen = n_slen);
#endif /* AFS_SGI53_ENV */
- if (ode)
- DRelease((struct buffer *)ode, 0);
+
+ DRelease(&oldEntry, 0);
+ oldEntry = nextEntry;
ode = nde;
- auio->afsio_offset =
- (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5);
+ AFS_UIO_SETOFFSET(auio, (afs_int32) ((us + afs_dir_NameBlobs(nde->name)) << 5));
}
- if (ode)
- DRelease((struct buffer *)ode, 0);
+
+ DRelease(&oldEntry, 0);
dirend:
ReleaseReadLock(&tdc->lock);
#ifdef AFS_HPUX_ENV
osi_FreeSmallSpace((char *)sdirEntry);
#endif
+ AFS_DISCON_UNLOCK();
afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 28);
- return code;
-}
-
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
-#ifdef AFS_OSF_ENV
-afs1_readdir(avc, auio, acred, eofp)
- int *eofp;
-#else
-afs1_readdir(avc, auio, acred)
-#endif
- struct vcache *avc;
- struct uio *auio;
- struct AFS_UCRED *acred;
-{
- struct vrequest treq;
- register struct dcache *tdc;
- afs_size_t origOffset, len;
- int code = 0;
- struct DirEntry *ode = 0, *nde = 0;
- int o_slen = 0, n_slen = 0;
- afs_uint32 us;
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- /*
- * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
- * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
- * translator side XXX
- */
- struct minnfs_direct *sdirEntry = (struct minnfs_direct *)
- osi_AllocSmallSpace(sizeof(struct min_direct));
- afs_int32 rlen;
-#endif
- struct afs_fakestat_state fakestate;
-
- AFS_STATCNT(afs_readdir);
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
- if (eofp)
- *eofp = 0;
-#endif
- if (code = afs_InitReq(&treq, acred)) {
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- return code;
- }
- afs_InitFakeStat(&fakestate);
- code = afs_EvalFakeStat(&avc, &fakestate, &treq);
- if (code) {
-#ifdef AFS_HPUX_ENV
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- afs_PutFakeStat(&fakestate);
- return code;
- }
- /* update the cache entry */
- tagain:
- code = afs_VerifyVCache(avc, &treq);
- if (code)
- goto done;
- /* get a reference to the entire directory */
- tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &len, 1);
- if (!tdc) {
- code = ENOENT;
- goto done;
- }
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
-
- /*
- * Make sure that the data in the cache is current. There are two
- * cases we need to worry about:
- * 1. The cache data is being fetched by another process.
- * 2. The cache data is no longer valid
- */
- while ((avc->states & CStatd)
- && (tdc->dflags & DFFetching)
- && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT, ICL_TYPE_STRING,
- __FILE__, ICL_TYPE_INT32, __LINE__, ICL_TYPE_POINTER, tdc,
- ICL_TYPE_INT32, tdc->dflags);
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_osi_Sleep(&tdc->validPos);
- ObtainReadLock(&avc->lock);
- ObtainReadLock(&tdc->lock);
- }
- if (!(avc->states & CStatd)
- || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
- ReleaseReadLock(&tdc->lock);
- ReleaseReadLock(&avc->lock);
- afs_PutDCache(tdc);
- goto tagain;
- }
-
- len = 0;
-#ifdef AFS_HPUX_ENV
- auio->uio_fpflags = 0;
-#endif
- while (code == 0) {
- origOffset = auio->afsio_offset;
-
- /* 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 */
- if (!(us = BlobScan(&tdc->f, (origOffset >> 5)))
- || !(nde = (struct DirEntry *)afs_dir_GetBlob(&tdc->f, us))) {
- /* failed to setup nde, return what we've got, and release ode */
- if (len) {
- /* something to hand over. */
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0) {
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- }
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code =
- afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
-#endif /* AFS_HPUX_ENV */
- auio->afsio_resid = 0;
- } else {
- /* nothin to hand over */
- }
-#if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
- if (eofp)
- *eofp = 1;
-#endif
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
- /* by here nde is set */
-
- /* Do we have enough user space to carry out our mission? */
-#if defined(AFS_SGI_ENV)
- n_slen = strlen(nde->name) + 1; /* NULL terminate */
-#else
- n_slen = strlen(nde->name);
-#endif
- if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid - len)) {
- /* No can do no more now; ya know... at this time */
- DRelease(nde, 0); /* can't use this one. */
- if (len) {
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = auio->afsio_resid;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
- auio, code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code =
- afs_readdir_move(ode, avc, auio, o_slen,
- auio->afsio_resid, origOffset);
-#endif /* AFS_HPUX_ENV */
- /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
- auio->afsio_offset = origOffset;
- auio->afsio_resid = 0;
- } else { /* trouble, can't give anything to the user! */
- /* even though he has given us a buffer,
- * even though we have something to give us,
- * Looks like we lost something somewhere.
- */
- code = EINVAL;
- }
- if (ode)
- DRelease(ode, 0);
- goto dirend;
- }
-
- /*
- * In any event, we move out the LAST de entry, getting ready
- * to set up for the next one.
- */
- if (len) {
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- sdirEntry->d_fileno =
- (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
- FIXUPSTUPIDINODE(sdirEntry->d_fileno);
- sdirEntry->d_reclen = rlen = len;
- sdirEntry->d_namlen = o_slen;
- sdirEntry->d_off = origOffset;
- AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio,
- code);
- if (code == 0)
- AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
- /* pad out the remaining characters with zeros */
- if (code == 0) {
- AFS_UIOMOVE(bufofzeros,
- ((o_slen + 1 + DIRPAD) & ~DIRPAD) - o_slen,
- UIO_READ, auio, code);
- }
- /* pad out the difference between rlen and slen... */
- if (NDIRSIZ_LEN(o_slen) < rlen) {
- while (NDIRSIZ_LEN(o_slen) < rlen) {
- int minLen = rlen - NDIRSIZ_LEN(o_slen);
- if (minLen > sizeof(bufofzeros))
- minLen = sizeof(bufofzeros);
- AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
- rlen -= minLen;
- }
- }
-#else
- code = afs_readdir_move(ode, avc, auio, o_slen, len, origOffset);
-#endif /* AFS_HPUX_ENV */
- }
- len = NDIRSIZ_LEN(o_slen = n_slen);
- if (ode)
- DRelease(ode, 0);
- ode = nde;
- auio->afsio_offset = ((us + afs_dir_NameBlobs(nde->name)) << 5);
- }
- if (ode)
- DRelease(ode, 0);
-
- dirend:
- ReleaseReadLock(&tdc->lock);
- afs_PutDCache(tdc);
- ReleaseReadLock(&avc->lock);
-
- done:
-#if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
- osi_FreeSmallSpace((char *)sdirEntry);
-#endif
- afs_PutFakeStat(&fakestate);
- code = afs_CheckCode(code, &treq, 29);
+ code = afs_CheckCode(code, treq, 28);
+ afs_DestroyReq(treq);
return code;
}
-#endif
#endif /* !AFS_LINUX20_ENV */