2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
11 * afs_vnop_readdir.c - afs_readdir and bulk stat
17 * afs_readdir/afs_readdir2(HP)
18 * afs_readdir1 - HP and DUX NFS versions
22 #include <afsconfig.h>
23 #include "../afs/param.h"
27 #include "../afs/sysincludes.h" /* Standard vendor system headers */
28 #include "../afs/afsincludes.h" /* Afs-based standard headers */
29 #include "../afs/afs_stats.h" /* statistics */
30 #include "../afs/afs_cbqueue.h"
31 #include "../afs/nfsclient.h"
32 #include "../afs/afs_osidnlc.h"
36 * A few definitions. This is until we have a proper header file
37 * which ahs prototypes for all functions
40 extern struct DirEntry * afs_dir_GetBlob();
42 * AFS readdir vnodeop and bulk stat support.
45 /* Saber C hates negative inode #s. We're not going to talk about software
46 * that could fail if it sees a negative inode #.
48 #define FIXUPSTUPIDINODE(a) ((a) &= 0x7fffffff)
50 /* BlobScan is supposed to ensure that the blob reference refers to a valid
51 directory entry. It consults the allocation map in the page header
52 to determine whether a blob is actually in use or not.
54 More formally, BlobScan is supposed to return a new blob number which is just like
55 the input parameter, only it is advanced over header or free blobs.
57 Note that BlobScan switches pages if necessary. BlobScan may return
58 either 0 or an out-of-range blob number for end of file.
60 BlobScan is used by the Linux port in a separate file, so it should not
63 #if defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)
64 int BlobScan(ino64_t *afile, afs_int32 ablob)
66 #ifdef AFS_LINUX_64BIT_KERNEL
67 int BlobScan(long *afile, afs_int32 ablob)
69 int BlobScan(afs_int32 *afile, afs_int32 ablob)
73 register afs_int32 relativeBlob;
75 register struct PageHeader *tpe;
78 AFS_STATCNT(BlobScan);
79 /* advance ablob over free and header blobs */
81 pageBlob = ablob & ~(EPP-1); /* base blob in same page */
82 tpe = (struct PageHeader *) afs_dir_GetBlob(afile, pageBlob);
83 if (!tpe) return 0; /* we've past the end */
84 relativeBlob = ablob - pageBlob; /* relative to page's first blob */
85 /* first watch for headers */
86 if (pageBlob == 0) { /* first dir page has extra-big header */
88 if (relativeBlob < DHE+1) relativeBlob = DHE+1;
90 else { /* others have one header blob */
91 if (relativeBlob == 0) relativeBlob = 1;
93 /* make sure blob is allocated */
94 for(i = relativeBlob; i < EPP; i++) {
95 if (tpe->freebitmap[i>>3] & (1<<(i&7))) break;
97 /* now relativeBlob is the page-relative first allocated blob,
98 or EPP (if there are none in this page). */
100 if (i != EPP) return i+pageBlob;
101 ablob = pageBlob + EPP; /* go around again */
106 #if !defined(AFS_LINUX20_ENV)
107 /* Changes to afs_readdir which affect dcache or vcache handling or use of
108 * bulk stat data should also be reflected in the Linux specific verison of
109 * the readdir routine.
113 * The kernel don't like it so much to have large stuff on the stack.
114 * Here we use a watered down version of the direct struct, since
115 * its not too bright to double copy the strings anyway.
117 #if !defined(UKERNEL)
118 #if defined(AFS_SGI_ENV)
119 /* Long form for 64 bit apps and kernel requests. */
120 struct min_dirent { /* miniature dirent structure */
121 /* If struct dirent changes, this must too */
122 ino_t d_fileno; /* This is 32 bits for 3.5, 64 for 6.2+ */
126 /* Short form for 32 bit apps. */
127 struct irix5_min_dirent { /* miniature dirent structure */
128 /* If struct dirent changes, this must too */
134 #define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
135 #define AFS_DIRENT64BASESIZE DIRENT64BASESIZE
137 #define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
138 #define AFS_DIRENT64BASESIZE DIRENTBASESIZE
139 #endif /* AFS_SGI62_ENV */
141 struct min_direct { /* miniature direct structure */
142 /* If struct direct changes, this must too */
143 #ifdef AFS_DARWIN_ENV
154 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
157 #if defined(AFS_HPUX100_ENV)
158 unsigned long long d_off;
166 #endif /* AFS_SGI_ENV */
168 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
169 struct minnfs_direct {
170 afs_int32 d_off; /* XXX */
175 #define NDIRSIZ_LEN(len) ((sizeof (struct dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
177 #endif /* !defined(UKERNEL) */
181 *------------------------------------------------------------------------------
183 * Keep a stack of about 256 fids for the bulk stat call.
184 * Fill it during the readdir_move. Later empty it...
187 #define READDIR_STASH AFSCBMAX
188 struct AFSFid afs_readdir_stash[READDIR_STASH];
189 int afs_rd_stash_i = 0;
192 *------------------------------------------------------------------------------
195 * mainly a kind of macro... makes getting the struct direct
196 * out to the user space easy... could take more parameters,
197 * but now just takes what it needs.
201 #if defined(AFS_HPUX100_ENV)
202 #define DIRSIZ_LEN(len) \
203 ((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
205 #if defined(AFS_SUN56_ENV)
206 #define DIRSIZ_LEN(len) ((18 + (len) + 1 + 7) & ~7 )
209 #define DIRSIZ_LEN(len) ((10 + (len) + 1 + (NBPW-1)) & ~(NBPW-1))
212 #define DIRSIZ_LEN(len) \
213 ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
215 #if defined(AFS_SGI_ENV)
216 #ifndef AFS_SGI53_ENV
217 /* SGI 5.3 and later use 32/64 bit versions of directory size. */
218 #define DIRSIZ_LEN(len) DIRENTSIZE(len)
220 #else /* AFS_SGI_ENV */
221 #define DIRSIZ_LEN(len) \
222 ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
223 #endif /* AFS_SGI_ENV */
224 #endif /* AFS_DIRENT */
225 #endif /* AFS_SUN5_ENV */
226 #endif /* AFS_SUN56_ENV */
227 #endif /* AFS_HPUX100_ENV */
230 #define AFS_MOVE_LOCK() AFS_GLOCK()
231 #define AFS_MOVE_UNLOCK() AFS_GUNLOCK()
233 #define AFS_MOVE_LOCK()
234 #define AFS_MOVE_UNLOCK()
237 char bufofzeros[64]; /* gotta fill with something */
238 afs_readdir_move (de, vc, auio, slen, rlen, off)
239 struct DirEntry * de;
251 #if defined(AFS_SUN56_ENV)
252 struct dirent64 *direntp;
255 struct dirent *direntp;
257 #endif /* AFS_SUN56_ENV */
258 #ifndef AFS_SGI53_ENV
259 struct min_direct sdirEntry;
260 #endif /* AFS_SGI53_ENV */
262 AFS_STATCNT(afs_readdir_move);
265 afs_int32 use64BitDirent;
269 use64BitDirent = ABI_IS(ABI_IRIX5_64,
270 GETDENTS_ABI*OSI_GET_CURRENT_ABI(), auio));
272 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
273 (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
275 #else /* AFS_SGI61_ENV */
276 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
277 (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
278 #endif /* AFS_SGI61_ENV */
280 if (use64BitDirent) {
281 struct min_dirent sdirEntry;
282 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
283 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
284 sdirEntry.d_reclen = rlen;
285 sdirEntry.d_off = (off_t)off;
286 AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio, code);
288 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
290 AFS_UIOMOVE(bufofzeros,
291 DIRENTSIZE(slen) - (AFS_DIRENT64BASESIZE + slen - 1),
292 UIO_READ, auio, code);
293 if (DIRENTSIZE(slen) < rlen) {
294 while(DIRENTSIZE(slen) < rlen) {
295 int minLen = rlen - DIRENTSIZE(slen);
296 if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
297 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
302 struct irix5_min_dirent sdirEntry;
303 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
304 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
305 sdirEntry.d_reclen = rlen;
306 sdirEntry.d_off = (afs_int32)off;
307 AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio, code);
309 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
311 AFS_UIOMOVE(bufofzeros,
312 IRIX5_DIRENTSIZE(slen) -
313 (AFS_DIRENT32BASESIZE + slen - 1),
314 UIO_READ, auio, code);
315 if (IRIX5_DIRENTSIZE(slen) < rlen) {
316 while(IRIX5_DIRENTSIZE(slen) < rlen) {
317 int minLen = rlen - IRIX5_DIRENTSIZE(slen);
318 if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
319 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
325 #else /* AFS_SGI53_ENV */
327 #if defined(AFS_SUN56_ENV)
328 direntp = (struct dirent64 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
330 direntp = (struct dirent *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
332 direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
333 FIXUPSTUPIDINODE(direntp->d_ino);
334 direntp->d_off = off;
335 direntp->d_reclen = rlen;
336 strcpy(direntp->d_name, de->name);
337 AFS_UIOMOVE((caddr_t)direntp, rlen, UIO_READ, auio, code);
338 osi_FreeLargeSpace((char *)direntp);
339 #else /* AFS_SUN5_ENV */
340 /* Note the odd mechanism for building the inode number */
341 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) +
342 ntohl(de->fid.vnode);
343 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
344 sdirEntry.d_reclen = rlen;
345 #if !defined(AFS_SGI_ENV)
346 sdirEntry.d_namlen = slen;
348 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
349 sdirEntry.d_off = off;
351 #if defined(AFS_DARWIN_ENV)
352 sdirEntry.d_type=DT_UNKNOWN;
355 #if defined(AFS_SGI_ENV)
356 AFS_UIOMOVE(&sdirEntry, DIRENTBASESIZE, UIO_READ, auio, code);
358 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
360 AFS_UIOMOVE(bufofzeros, DIRSIZ_LEN(slen) - (DIRENTBASESIZE + slen - 1), UIO_READ, auio, code);
361 #else /* AFS_SGI_ENV */
363 AFS_UIOMOVE((char *)&sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
366 AFS_UIOMOVE(de->name, slen, UIO_READ, auio, code);
369 /* pad out the remaining characters with zeros */
371 AFS_UIOMOVE(bufofzeros, ((slen + 4) & ~3) - slen, UIO_READ,
375 #endif /* AFS_SGI_ENV */
377 /* pad out the difference between rlen and slen... */
378 if (DIRSIZ_LEN(slen) < rlen)
381 while(DIRSIZ_LEN(slen) < rlen)
383 int minLen = rlen - DIRSIZ_LEN(slen);
384 if (minLen > sizeof(bufofzeros))
385 minLen = sizeof(bufofzeros);
386 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
391 #endif /* AFS_SUN5_ENV */
392 #endif /* AFS_SGI53_ENV */
398 *------------------------------------------------------------------------------
400 * Read directory entries.
401 * There are some weird things to look out for here. The uio_offset
402 * field is either 0 or it is the offset returned from a previous
403 * readdir. It is an opaque value used by the server to find the
404 * correct directory block to read. The byte count must be at least
405 * vtoblksz(vp) bytes. The count field is the number of blocks to
406 * read on the server. This is advisory only, the server may return
407 * only one block's worth of entries. Entries may be compressed on
410 * This routine encodes knowledge of Vice dirs.
413 void afs_bulkstat_send( avc, req )
415 struct vrequest * req;
422 * Here is the bad, bad, really bad news.
423 * It has to do with 'offset' (seek locations).
426 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
427 afs_readdir(OSI_VC_ARG(avc), auio, acred, eofp)
430 #if defined(AFS_HPUX100_ENV)
431 afs_readdir2(OSI_VC_ARG(avc), auio, acred)
433 afs_readdir(OSI_VC_ARG(avc), auio, acred)
438 struct AFS_UCRED *acred;
440 struct vrequest treq;
441 register struct dcache *tdc;
442 afs_size_t origOffset, tlen;
443 afs_int32 len, dirsiz;
445 struct DirEntry *ode = 0, *nde = 0;
446 int o_slen = 0, n_slen = 0;
448 #if defined(AFS_SGI53_ENV)
449 afs_int32 use64BitDirent;
450 #endif /* defined(AFS_SGI53_ENV) */
454 * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
455 * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
456 * translator side XXX
458 struct min_direct *sdirEntry = (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
462 /* opaque value is pointer into a vice dir; use bit map to decide
463 if the entries are in use. Always assumed to be valid. 0 is
464 special, means start of a new dir. Int32 inode, followed by
465 short reclen and short namelen. Namelen does not include
466 the null byte. Followed by null-terminated string.
468 AFS_STATCNT(afs_readdir);
470 #if defined(AFS_SGI53_ENV)
473 use64BitDirent = ABI_IS(ABI_IRIX5_64,
474 GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
476 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
477 (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
478 #endif /* AFS_SGI62_ENV */
479 #else /* AFS_SGI61_ENV */
480 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
481 (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
482 #endif /* AFS_SGI61_ENV */
483 #endif /* defined(AFS_SGI53_ENV) */
485 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV) || defined(AFS_DARWIN_ENV)
486 /* Not really used by the callee so we ignore it for now */
489 if ( AfsLargeFileUio(auio) /* file is large than 2 GB */
490 || AfsLargeFileSize(auio->uio_offset, auio->uio_resid) )
493 if (code = afs_InitReq(&treq, acred)) {
495 osi_FreeSmallSpace((char *)sdirEntry);
499 /* update the cache entry */
501 code = afs_VerifyVCache(avc, &treq);
503 /* get a reference to the entire directory */
504 tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &tlen, 1);
510 ObtainReadLock(&avc->lock);
513 * Make sure that the data in the cache is current. There are two
514 * cases we need to worry about:
515 * 1. The cache data is being fetched by another process.
516 * 2. The cache data is no longer valid
518 while ((avc->states & CStatd)
519 && (tdc->flags & DFFetching)
520 && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
521 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
522 ICL_TYPE_STRING, __FILE__,
523 ICL_TYPE_INT32, __LINE__,
524 ICL_TYPE_POINTER, tdc,
525 ICL_TYPE_INT32, tdc->flags);
526 tdc->flags |= DFWaiting;
527 ReleaseReadLock(&avc->lock);
528 afs_osi_Sleep(&tdc->validPos);
529 ObtainReadLock(&avc->lock);
531 if (!(avc->states & CStatd)
532 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
533 ReleaseReadLock(&avc->lock);
539 * iterator for the directory reads. Takes the AFS DirEntry
540 * structure and slams them into UFS direct structures.
541 * uses afs_readdir_move to get the struct to the user space.
543 * The routine works by looking ahead one AFS directory entry.
544 * That's because the AFS entry we are currenly working with
545 * may not fit into the buffer the user has provided. If it
546 * doesn't we have to change the size of the LAST AFS directory
547 * entry, so that it will FIT perfectly into the block the
550 * The 'forward looking' of the code makes it a bit tough to read.
551 * Remember we need to get an entry, see if it it fits, then
552 * set it up as the LAST entry, and find the next one.
554 * Tough to take: We give out an EINVAL if we don't have enough
555 * space in the buffer, and at the same time, don't have an entry
556 * to put into the buffer. This CAN happen if the first AFS entry
557 * we get can't fit into the 512 character buffer provided. Seems
558 * it ought not happen...
560 * Assumption: don't need to use anything but one dc entry:
561 * this means the directory ought not be greater than 64k.
565 auio->uio_fpflags = 0;
568 origOffset = auio->afsio_offset;
569 /* scan for the next interesting entry scan for in-use blob otherwise up point at
570 * this blob note that ode, if non-zero, also represents a held dir page */
571 if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
572 || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
573 /* failed to setup nde, return what we've got, and release ode */
575 /* something to hand over. */
577 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
578 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
579 sdirEntry->d_reclen = rlen = auio->afsio_resid;
580 sdirEntry->d_namlen = o_slen;
581 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
582 sdirEntry->d_off = origOffset;
584 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
586 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
587 /* pad out the remaining characters with zeros */
589 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
591 /* pad out the difference between rlen and slen... */
592 if (DIRSIZ_LEN(o_slen) < rlen) {
593 while(DIRSIZ_LEN(o_slen) < rlen) {
594 int minLen = rlen - DIRSIZ_LEN(o_slen);
595 if (minLen > sizeof(bufofzeros))
596 minLen = sizeof(bufofzeros);
597 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
602 code = afs_readdir_move(ode, avc, auio, o_slen,
603 #if defined(AFS_SUN5_ENV)
606 auio->afsio_resid, origOffset);
608 #endif /* AFS_HPUX_ENV */
609 #if !defined(AFS_SUN5_ENV)
610 auio->afsio_resid = 0;
613 /* nothin to hand over */
615 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
616 if (eofp) *eofp = 1; /* Set it properly */
618 if (ode) DRelease(ode, 0);
621 /* by here nde is set */
623 /* Do we have enough user space to carry out our mission? */
624 #if defined(AFS_SGI_ENV)
625 n_slen = strlen(nde->name) + 1; /* NULL terminate */
627 n_slen = strlen(nde->name);
630 dirsiz = use64BitDirent ? DIRENTSIZE(n_slen) :
631 IRIX5_DIRENTSIZE(n_slen);
632 if (dirsiz >= (auio->afsio_resid-len)) {
634 if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
635 #endif /* AFS_SGI53_ENV */
636 /* No can do no more now; ya know... at this time */
637 DRelease (nde, 0); /* can't use this one. */
640 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
641 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
642 sdirEntry->d_reclen = rlen = auio->afsio_resid;
643 sdirEntry->d_namlen = o_slen;
644 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
645 sdirEntry->d_off = origOffset;
647 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
649 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
650 /* pad out the remaining characters with zeros */
652 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
654 /* pad out the difference between rlen and slen... */
655 if (DIRSIZ_LEN(o_slen) < rlen) {
656 while(DIRSIZ_LEN(o_slen) < rlen) {
657 int minLen = rlen - DIRSIZ_LEN(o_slen);
658 if (minLen > sizeof(bufofzeros))
659 minLen = sizeof(bufofzeros);
660 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
664 #else /* AFS_HPUX_ENV */
665 code = afs_readdir_move(ode, avc, auio, o_slen,
666 auio->afsio_resid, origOffset);
667 #endif /* AFS_HPUX_ENV */
668 /* this next line used to be AFSVFS40 or AIX 3.1, but is
670 auio->afsio_offset = origOffset;
671 auio->afsio_resid = 0;
672 } else { /* trouble, can't give anything to the user! */
673 /* even though he has given us a buffer,
674 * even though we have something to give us,
675 * Looks like we lost something somewhere.
679 if (ode) DRelease(ode, 0);
684 * In any event, we move out the LAST de entry, getting ready
685 * to set up for the next one.
689 sdirEntry->d_fileno =
690 (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
691 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
692 sdirEntry->d_reclen = rlen = len;
693 sdirEntry->d_namlen = o_slen;
694 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
695 sdirEntry->d_off = origOffset;
697 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
700 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
701 /* pad out the remaining characters with zeros */
703 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen,
704 UIO_READ, auio, code);
706 /* pad out the difference between rlen and slen... */
707 if (DIRSIZ_LEN(o_slen) < rlen) {
708 while(DIRSIZ_LEN(o_slen) < rlen) {
709 int minLen = rlen - DIRSIZ_LEN(o_slen);
710 if (minLen > sizeof(bufofzeros))
711 minLen = sizeof(bufofzeros);
712 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
716 #else /* AFS_HPUX_ENV */
717 code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
718 #endif /* AFS_HPUX_ENV */
721 len = use64BitDirent ? DIRENTSIZE(o_slen = n_slen) :
722 IRIX5_DIRENTSIZE(o_slen = n_slen);
724 len = DIRSIZ_LEN( o_slen = n_slen );
725 #endif /* AFS_SGI53_ENV */
726 if (ode) DRelease(ode, 0);
728 auio->afsio_offset = (afs_int32)((us + afs_dir_NameBlobs(nde->name)) << 5);
730 if (ode) DRelease(ode, 0);
734 ReleaseReadLock(&avc->lock);
738 osi_FreeSmallSpace((char *)sdirEntry);
740 code = afs_CheckCode(code, &treq, 28);
744 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
746 afs1_readdir(avc, auio, acred, eofp)
749 afs1_readdir(avc, auio, acred)
751 register struct vcache *avc;
753 struct AFS_UCRED *acred; {
754 struct vrequest treq;
755 register struct dcache *tdc;
756 afs_size_t origOffset, len;
758 struct DirEntry *ode = 0, *nde = 0;
759 int o_slen = 0, n_slen = 0;
761 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
763 * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
764 * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
765 * translator side XXX
767 struct minnfs_direct *sdirEntry = (struct minnfs_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
771 AFS_STATCNT(afs_readdir);
772 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
775 if (code = afs_InitReq(&treq, acred)) {
777 osi_FreeSmallSpace((char *)sdirEntry);
781 /* update the cache entry */
783 code = afs_VerifyVCache(avc, &treq);
785 /* get a reference to the entire directory */
786 tdc = afs_GetDCache(avc, (afs_size_t) 0, &treq, &origOffset, &len, 1);
791 ObtainReadLock(&avc->lock);
794 * Make sure that the data in the cache is current. There are two
795 * cases we need to worry about:
796 * 1. The cache data is being fetched by another process.
797 * 2. The cache data is no longer valid
799 while ((avc->states & CStatd)
800 && (tdc->flags & DFFetching)
801 && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
802 afs_Trace4(afs_iclSetp, CM_TRACE_DCACHEWAIT,
803 ICL_TYPE_STRING, __FILE__,
804 ICL_TYPE_INT32, __LINE__,
805 ICL_TYPE_POINTER, tdc,
806 ICL_TYPE_INT32, tdc->flags);
807 tdc->flags |= DFWaiting;
808 ReleaseReadLock(&avc->lock);
809 afs_osi_Sleep(&tdc->validPos);
810 ObtainReadLock(&avc->lock);
812 if (!(avc->states & CStatd)
813 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
814 ReleaseReadLock(&avc->lock);
821 auio->uio_fpflags = 0;
824 origOffset = auio->afsio_offset;
826 /* scan for the next interesting entry scan for in-use blob otherwise up point at
827 * this blob note that ode, if non-zero, also represents a held dir page */
828 if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
829 || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
830 /* failed to setup nde, return what we've got, and release ode */
832 /* something to hand over. */
833 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
834 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
835 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
836 sdirEntry->d_reclen = rlen = auio->afsio_resid;
837 sdirEntry->d_namlen = o_slen;
838 sdirEntry->d_off = origOffset;
839 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
841 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
843 /* pad out the remaining characters with zeros */
845 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
847 /* pad out the difference between rlen and slen... */
848 if (NDIRSIZ_LEN(o_slen) < rlen) {
849 while(NDIRSIZ_LEN(o_slen) < rlen) {
850 int minLen = rlen - NDIRSIZ_LEN(o_slen);
851 if (minLen > sizeof(bufofzeros))
852 minLen = sizeof(bufofzeros);
853 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
858 code = afs_readdir_move(ode, avc, auio, o_slen,
859 auio->afsio_resid, origOffset);
860 #endif /* AFS_HPUX_ENV */
861 auio->afsio_resid = 0;
863 /* nothin to hand over */
865 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
868 if (ode) DRelease(ode, 0);
871 /* by here nde is set */
873 /* Do we have enough user space to carry out our mission? */
874 #if defined(AFS_SGI_ENV)
875 n_slen = strlen(nde->name) + 1; /* NULL terminate */
877 n_slen = strlen(nde->name);
879 if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
880 /* No can do no more now; ya know... at this time */
881 DRelease (nde, 0); /* can't use this one. */
883 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
884 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
885 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
886 sdirEntry->d_reclen = rlen = auio->afsio_resid;
887 sdirEntry->d_namlen = o_slen;
888 sdirEntry->d_off = origOffset;
889 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
891 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
892 /* pad out the remaining characters with zeros */
894 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
896 /* pad out the difference between rlen and slen... */
897 if (NDIRSIZ_LEN(o_slen) < rlen) {
898 while(NDIRSIZ_LEN(o_slen) < rlen) {
899 int minLen = rlen - NDIRSIZ_LEN(o_slen);
900 if (minLen > sizeof(bufofzeros))
901 minLen = sizeof(bufofzeros);
902 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
907 code = afs_readdir_move(ode, avc, auio, o_slen,
908 auio->afsio_resid, origOffset);
909 #endif /* AFS_HPUX_ENV */
910 /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
911 auio->afsio_offset = origOffset;
912 auio->afsio_resid = 0;
913 } else { /* trouble, can't give anything to the user! */
914 /* even though he has given us a buffer,
915 * even though we have something to give us,
916 * Looks like we lost something somewhere.
920 if (ode) DRelease(ode, 0);
925 * In any event, we move out the LAST de entry, getting ready
926 * to set up for the next one.
929 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
930 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
931 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
932 sdirEntry->d_reclen = rlen = len;
933 sdirEntry->d_namlen = o_slen;
934 sdirEntry->d_off = origOffset;
935 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
937 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
938 /* pad out the remaining characters with zeros */
940 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
942 /* pad out the difference between rlen and slen... */
943 if (NDIRSIZ_LEN(o_slen) < rlen) {
944 while(NDIRSIZ_LEN(o_slen) < rlen) {
945 int minLen = rlen - NDIRSIZ_LEN(o_slen);
946 if (minLen > sizeof(bufofzeros))
947 minLen = sizeof(bufofzeros);
948 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
953 code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
954 #endif /* AFS_HPUX_ENV */
956 len = NDIRSIZ_LEN( o_slen = n_slen );
957 if (ode) DRelease(ode, 0);
959 auio->afsio_offset = ((us + afs_dir_NameBlobs(nde->name)) << 5);
961 if (ode) DRelease(ode, 0);
965 ReleaseReadLock(&avc->lock);
968 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
969 osi_FreeSmallSpace((char *)sdirEntry);
971 code = afs_CheckCode(code, &treq, 29);
976 #endif /* !AFS_LINUX20_ENV */