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 "../afs/param.h" /* Should be always first */
23 #include "../afs/sysincludes.h" /* Standard vendor system headers */
24 #include "../afs/afsincludes.h" /* Afs-based standard headers */
25 #include "../afs/afs_stats.h" /* statistics */
26 #include "../afs/afs_cbqueue.h"
27 #include "../afs/nfsclient.h"
28 #include "../afs/afs_osidnlc.h"
32 * A few definitions. This is until we have a proper header file
33 * which ahs prototypes for all functions
36 extern struct DirEntry * afs_dir_GetBlob();
38 * AFS readdir vnodeop and bulk stat support.
41 /* Saber C hates negative inode #s. We're not going to talk about software
42 * that could fail if it sees a negative inode #.
44 #define FIXUPSTUPIDINODE(a) ((a) &= 0x7fffffff)
46 /* BlobScan is supposed to ensure that the blob reference refers to a valid
47 directory entry. It consults the allocation map in the page header
48 to determine whether a blob is actually in use or not.
50 More formally, BlobScan is supposed to return a new blob number which is just like
51 the input parameter, only it is advanced over header or free blobs.
53 Note that BlobScan switches pages if necessary. BlobScan may return
54 either 0 or an out-of-range blob number for end of file.
56 BlobScan is used by the Linux port in a separate file, so it should not
59 #if defined(AFS_SGI62_ENV) || defined(AFS_SUN57_64BIT_ENV)
60 int BlobScan(ino64_t *afile, afs_int32 ablob)
62 int BlobScan(afs_int32 *afile, afs_int32 ablob)
65 register afs_int32 relativeBlob;
67 register struct PageHeader *tpe;
70 AFS_STATCNT(BlobScan);
71 /* advance ablob over free and header blobs */
73 pageBlob = ablob & ~(EPP-1); /* base blob in same page */
74 tpe = (struct PageHeader *) afs_dir_GetBlob(afile, pageBlob);
75 if (!tpe) return 0; /* we've past the end */
76 relativeBlob = ablob - pageBlob; /* relative to page's first blob */
77 /* first watch for headers */
78 if (pageBlob == 0) { /* first dir page has extra-big header */
80 if (relativeBlob < DHE+1) relativeBlob = DHE+1;
82 else { /* others have one header blob */
83 if (relativeBlob == 0) relativeBlob = 1;
85 /* make sure blob is allocated */
86 for(i = relativeBlob; i < EPP; i++) {
87 if (tpe->freebitmap[i>>3] & (1<<(i&7))) break;
89 /* now relativeBlob is the page-relative first allocated blob,
90 or EPP (if there are none in this page). */
92 if (i != EPP) return i+pageBlob;
93 ablob = pageBlob + EPP; /* go around again */
98 #if !defined(AFS_LINUX20_ENV)
99 /* Changes to afs_readdir which affect dcache or vcache handling or use of
100 * bulk stat data should also be reflected in the Linux specific verison of
101 * the readdir routine.
105 * The kernel don't like it so much to have large stuff on the stack.
106 * Here we use a watered down version of the direct struct, since
107 * its not too bright to double copy the strings anyway.
109 #if !defined(UKERNEL)
110 #if defined(AFS_SGI_ENV)
111 /* Long form for 64 bit apps and kernel requests. */
112 struct min_dirent { /* miniature dirent structure */
113 /* If struct dirent changes, this must too */
114 ino_t d_fileno; /* This is 32 bits for 3.5, 64 for 6.2+ */
118 /* Short form for 32 bit apps. */
119 struct irix5_min_dirent { /* miniature dirent structure */
120 /* If struct dirent changes, this must too */
126 #define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
127 #define AFS_DIRENT64BASESIZE DIRENT64BASESIZE
129 #define AFS_DIRENT32BASESIZE IRIX5_DIRENTBASESIZE
130 #define AFS_DIRENT64BASESIZE DIRENTBASESIZE
131 #endif /* AFS_SGI62_ENV */
133 struct min_direct { /* miniature direct structure */
134 /* If struct direct changes, this must too */
140 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV)
143 #if defined(AFS_HPUX100_ENV)
144 unsigned long long d_off;
151 #endif /* AFS_SGI_ENV */
153 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
154 struct minnfs_direct {
155 afs_int32 d_off; /* XXX */
160 #define NDIRSIZ_LEN(len) ((sizeof (struct dirent)+4 - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
162 #endif /* !defined(UKERNEL) */
166 *------------------------------------------------------------------------------
168 * Keep a stack of about 256 fids for the bulk stat call.
169 * Fill it during the readdir_move. Later empty it...
172 #define READDIR_STASH AFSCBMAX
173 struct AFSFid afs_readdir_stash[READDIR_STASH];
174 int afs_rd_stash_i = 0;
177 *------------------------------------------------------------------------------
180 * mainly a kind of macro... makes getting the struct direct
181 * out to the user space easy... could take more parameters,
182 * but now just takes what it needs.
186 #if defined(AFS_HPUX100_ENV)
187 #define DIRSIZ_LEN(len) \
188 ((sizeof (struct __dirent) - (_MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
190 #if defined(AFS_SUN56_ENV)
191 #define DIRSIZ_LEN(len) ((18 + (len) + 1 + 7) & ~7 )
194 #define DIRSIZ_LEN(len) ((10 + (len) + 1 + (NBPW-1)) & ~(NBPW-1))
197 #define DIRSIZ_LEN(len) \
198 ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
200 #if defined(AFS_SGI_ENV)
201 #ifndef AFS_SGI53_ENV
202 /* SGI 5.3 and later use 32/64 bit versions of directory size. */
203 #define DIRSIZ_LEN(len) DIRENTSIZE(len)
205 #else /* AFS_SGI_ENV */
206 #define DIRSIZ_LEN(len) \
207 ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((len)+1 + 3) &~ 3))
208 #endif /* AFS_SGI_ENV */
209 #endif /* AFS_DIRENT */
210 #endif /* AFS_SUN5_ENV */
211 #endif /* AFS_SUN56_ENV */
212 #endif /* AFS_HPUX100_ENV */
215 #define AFS_MOVE_LOCK() AFS_GLOCK()
216 #define AFS_MOVE_UNLOCK() AFS_GUNLOCK()
218 #define AFS_MOVE_LOCK()
219 #define AFS_MOVE_UNLOCK()
222 char bufofzeros[64]; /* gotta fill with something */
223 afs_readdir_move (de, vc, auio, slen, rlen, off)
224 struct DirEntry * de;
236 #if defined(AFS_SUN56_ENV)
237 struct dirent64 *direntp;
240 struct dirent *direntp;
242 #endif /* AFS_SUN56_ENV */
243 #ifndef AFS_SGI53_ENV
244 struct min_direct sdirEntry;
245 #endif /* AFS_SGI53_ENV */
247 AFS_STATCNT(afs_readdir_move);
250 afs_int32 use64BitDirent;
254 use64BitDirent = ABI_IS(ABI_IRIX5_64,
255 GETDENTS_ABI*OSI_GET_CURRENT_ABI(), auio));
257 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
258 (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
260 #else /* AFS_SGI61_ENV */
261 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
262 (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
263 #endif /* AFS_SGI61_ENV */
265 if (use64BitDirent) {
266 struct min_dirent sdirEntry;
267 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
268 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
269 sdirEntry.d_reclen = rlen;
270 sdirEntry.d_off = (off_t)off;
271 AFS_UIOMOVE(&sdirEntry, AFS_DIRENT64BASESIZE, UIO_READ, auio, code);
273 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
275 AFS_UIOMOVE(bufofzeros,
276 DIRENTSIZE(slen) - (AFS_DIRENT64BASESIZE + slen - 1),
277 UIO_READ, auio, code);
278 if (DIRENTSIZE(slen) < rlen) {
279 while(DIRENTSIZE(slen) < rlen) {
280 int minLen = rlen - DIRENTSIZE(slen);
281 if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
282 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
287 struct irix5_min_dirent sdirEntry;
288 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
289 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
290 sdirEntry.d_reclen = rlen;
291 sdirEntry.d_off = (afs_int32)off;
292 AFS_UIOMOVE(&sdirEntry, AFS_DIRENT32BASESIZE, UIO_READ, auio, code);
294 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
296 AFS_UIOMOVE(bufofzeros,
297 IRIX5_DIRENTSIZE(slen) -
298 (AFS_DIRENT32BASESIZE + slen - 1),
299 UIO_READ, auio, code);
300 if (IRIX5_DIRENTSIZE(slen) < rlen) {
301 while(IRIX5_DIRENTSIZE(slen) < rlen) {
302 int minLen = rlen - IRIX5_DIRENTSIZE(slen);
303 if (minLen > sizeof(bufofzeros)) minLen = sizeof(bufofzeros);
304 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
310 #else /* AFS_SGI53_ENV */
312 #if defined(AFS_SUN56_ENV)
313 direntp = (struct dirent64 *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
315 direntp = (struct dirent *) osi_AllocLargeSpace(AFS_LRALLOCSIZ);
317 direntp->d_ino = (vc->fid.Fid.Volume << 16) + ntohl(de->fid.vnode);
318 FIXUPSTUPIDINODE(direntp->d_ino);
319 direntp->d_off = off;
320 direntp->d_reclen = rlen;
321 strcpy(direntp->d_name, de->name);
322 AFS_UIOMOVE((caddr_t)direntp, rlen, UIO_READ, auio, code);
323 osi_FreeLargeSpace((char *)direntp);
324 #else /* AFS_SUN5_ENV */
325 /* Note the odd mechanism for building the inode number */
326 sdirEntry.d_fileno = (vc->fid.Fid.Volume << 16) +
327 ntohl(de->fid.vnode);
328 FIXUPSTUPIDINODE(sdirEntry.d_fileno);
329 sdirEntry.d_reclen = rlen;
330 #if !defined(AFS_SGI_ENV)
331 sdirEntry.d_namlen = slen;
333 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_SGI_ENV)
334 sdirEntry.d_off = off;
337 #if defined(AFS_SGI_ENV)
338 AFS_UIOMOVE(&sdirEntry, DIRENTBASESIZE, UIO_READ, auio, code);
340 AFS_UIOMOVE(de->name, slen-1, UIO_READ, auio, code);
342 AFS_UIOMOVE(bufofzeros, DIRSIZ_LEN(slen) - (DIRENTBASESIZE + slen - 1), UIO_READ, auio, code);
343 #else /* AFS_SGI_ENV */
345 AFS_UIOMOVE((char *)&sdirEntry, sizeof(sdirEntry), UIO_READ, auio, code);
348 AFS_UIOMOVE(de->name, slen, UIO_READ, auio, code);
351 /* pad out the remaining characters with zeros */
353 AFS_UIOMOVE(bufofzeros, ((slen + 4) & ~3) - slen, UIO_READ,
357 #endif /* AFS_SGI_ENV */
359 /* pad out the difference between rlen and slen... */
360 if (DIRSIZ_LEN(slen) < rlen)
363 while(DIRSIZ_LEN(slen) < rlen)
365 int minLen = rlen - DIRSIZ_LEN(slen);
366 if (minLen > sizeof(bufofzeros))
367 minLen = sizeof(bufofzeros);
368 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
373 #endif /* AFS_SUN5_ENV */
374 #endif /* AFS_SGI53_ENV */
380 *------------------------------------------------------------------------------
382 * Read directory entries.
383 * There are some weird things to look out for here. The uio_offset
384 * field is either 0 or it is the offset returned from a previous
385 * readdir. It is an opaque value used by the server to find the
386 * correct directory block to read. The byte count must be at least
387 * vtoblksz(vp) bytes. The count field is the number of blocks to
388 * read on the server. This is advisory only, the server may return
389 * only one block's worth of entries. Entries may be compressed on
392 * This routine encodes knowledge of Vice dirs.
395 void afs_bulkstat_send( avc, req )
397 struct vrequest * req;
404 * Here is the bad, bad, really bad news.
405 * It has to do with 'offset' (seek locations).
408 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
409 afs_readdir(OSI_VC_ARG(avc), auio, acred, eofp)
412 #if defined(AFS_HPUX100_ENV)
413 afs_readdir2(OSI_VC_ARG(avc), auio, acred)
415 afs_readdir(OSI_VC_ARG(avc), auio, acred)
420 struct AFS_UCRED *acred; {
421 struct vrequest treq;
422 register struct dcache *tdc;
423 afs_int32 origOffset, len, dirsiz;
425 struct DirEntry *ode = 0, *nde = 0;
426 int o_slen = 0, n_slen = 0;
428 #if defined(AFS_SGI53_ENV)
429 afs_int32 use64BitDirent;
430 #endif /* defined(AFS_SGI53_ENV) */
434 * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
435 * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
436 * translator side XXX
438 struct min_direct *sdirEntry = (struct min_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
442 /* opaque value is pointer into a vice dir; use bit map to decide
443 if the entries are in use. Always assumed to be valid. 0 is
444 special, means start of a new dir. Int32 inode, followed by
445 short reclen and short namelen. Namelen does not include
446 the null byte. Followed by null-terminated string.
448 AFS_STATCNT(afs_readdir);
450 #if defined(AFS_SGI53_ENV)
453 use64BitDirent = ABI_IS(ABI_IRIX5_64,
454 GETDENTS_ABI(OSI_GET_CURRENT_ABI(), auio));
456 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
457 (ABI_IS(ABI_IRIX5_64 | ABI_IRIX5_N32, u.u_procp->p_abi));
458 #endif /* AFS_SGI62_ENV */
459 #else /* AFS_SGI61_ENV */
460 use64BitDirent = (auio->uio_segflg != UIO_USERSPACE) ? ABI_IRIX5_64 :
461 (ABI_IS(ABI_IRIX5_64, u.u_procp->p_abi));
462 #endif /* AFS_SGI61_ENV */
463 #endif /* defined(AFS_SGI53_ENV) */
465 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
466 /* Not really used by the callee so we ignore it for now */
469 if ( AfsLargeFileUio(auio) /* file is large than 2 GB */
470 || AfsLargeFileSize(auio->uio_offset, auio->uio_resid) )
473 if (code = afs_InitReq(&treq, acred)) {
475 osi_FreeSmallSpace((char *)sdirEntry);
479 /* update the cache entry */
481 code = afs_VerifyVCache(avc, &treq);
483 /* get a reference to the entire directory */
484 tdc = afs_GetDCache(avc, 0, &treq, &origOffset, &len, 1);
489 ObtainReadLock(&avc->lock);
492 * Make sure that the data in the cache is current. There are two
493 * cases we need to worry about:
494 * 1. The cache data is being fetched by another process.
495 * 2. The cache data is no longer valid
497 while ((avc->states & CStatd)
498 && (tdc->flags & DFFetching)
499 && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
500 tdc->flags |= DFWaiting;
501 ReleaseReadLock(&avc->lock);
502 afs_osi_Sleep(&tdc->validPos);
503 ObtainReadLock(&avc->lock);
505 if (!(avc->states & CStatd)
506 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
507 ReleaseReadLock(&avc->lock);
513 * iterator for the directory reads. Takes the AFS DirEntry
514 * structure and slams them into UFS direct structures.
515 * uses afs_readdir_move to get the struct to the user space.
517 * The routine works by looking ahead one AFS directory entry.
518 * That's because the AFS entry we are currenly working with
519 * may not fit into the buffer the user has provided. If it
520 * doesn't we have to change the size of the LAST AFS directory
521 * entry, so that it will FIT perfectly into the block the
524 * The 'forward looking' of the code makes it a bit tough to read.
525 * Remember we need to get an entry, see if it it fits, then
526 * set it up as the LAST entry, and find the next one.
528 * Tough to take: We give out an EINVAL if we don't have enough
529 * space in the buffer, and at the same time, don't have an entry
530 * to put into the buffer. This CAN happen if the first AFS entry
531 * we get can't fit into the 512 character buffer provided. Seems
532 * it ought not happen...
534 * Assumption: don't need to use anything but one dc entry:
535 * this means the directory ought not be greater than 64k.
539 auio->uio_fpflags = 0;
542 origOffset = auio->afsio_offset;
543 /* scan for the next interesting entry scan for in-use blob otherwise up point at
544 * this blob note that ode, if non-zero, also represents a held dir page */
545 if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
546 || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
547 /* failed to setup nde, return what we've got, and release ode */
549 /* something to hand over. */
551 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
552 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
553 sdirEntry->d_reclen = rlen = auio->afsio_resid;
554 sdirEntry->d_namlen = o_slen;
555 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
556 sdirEntry->d_off = origOffset;
558 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
560 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
561 /* pad out the remaining characters with zeros */
563 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
565 /* pad out the difference between rlen and slen... */
566 if (DIRSIZ_LEN(o_slen) < rlen) {
567 while(DIRSIZ_LEN(o_slen) < rlen) {
568 int minLen = rlen - DIRSIZ_LEN(o_slen);
569 if (minLen > sizeof(bufofzeros))
570 minLen = sizeof(bufofzeros);
571 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
576 code = afs_readdir_move(ode, avc, auio, o_slen,
577 #if defined(AFS_SUN5_ENV)
580 auio->afsio_resid, origOffset);
582 #endif /* AFS_HPUX_ENV */
583 #if !defined(AFS_SUN5_ENV)
584 auio->afsio_resid = 0;
587 /* nothin to hand over */
589 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
590 if (eofp) *eofp = 1; /* Set it properly */
592 if (ode) DRelease(ode, 0);
595 /* by here nde is set */
597 /* Do we have enough user space to carry out our mission? */
598 #if defined(AFS_SGI_ENV)
599 n_slen = strlen(nde->name) + 1; /* NULL terminate */
601 n_slen = strlen(nde->name);
604 dirsiz = use64BitDirent ? DIRENTSIZE(n_slen) :
605 IRIX5_DIRENTSIZE(n_slen);
606 if (dirsiz >= (auio->afsio_resid-len)) {
608 if (DIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
609 #endif /* AFS_SGI53_ENV */
610 /* No can do no more now; ya know... at this time */
611 DRelease (nde, 0); /* can't use this one. */
614 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
615 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
616 sdirEntry->d_reclen = rlen = auio->afsio_resid;
617 sdirEntry->d_namlen = o_slen;
618 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
619 sdirEntry->d_off = origOffset;
621 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
623 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
624 /* pad out the remaining characters with zeros */
626 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
628 /* pad out the difference between rlen and slen... */
629 if (DIRSIZ_LEN(o_slen) < rlen) {
630 while(DIRSIZ_LEN(o_slen) < rlen) {
631 int minLen = rlen - DIRSIZ_LEN(o_slen);
632 if (minLen > sizeof(bufofzeros))
633 minLen = sizeof(bufofzeros);
634 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
638 #else /* AFS_HPUX_ENV */
639 code = afs_readdir_move(ode, avc, auio, o_slen,
640 #ifdef defined(AFS_SUN5_ENV)
643 auio->afsio_resid, origOffset);
645 #endif /* AFS_HPUX_ENV */
646 /* this next line used to be AFSVFS40 or AIX 3.1, but is
648 auio->afsio_offset = origOffset;
649 auio->afsio_resid = 0;
650 } else { /* trouble, can't give anything to the user! */
651 /* even though he has given us a buffer,
652 * even though we have something to give us,
653 * Looks like we lost something somewhere.
657 if (ode) DRelease(ode, 0);
662 * In any event, we move out the LAST de entry, getting ready
663 * to set up for the next one.
667 sdirEntry->d_fileno =
668 (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
669 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
670 sdirEntry->d_reclen = rlen = len;
671 sdirEntry->d_namlen = o_slen;
672 #if defined(AFS_SUN_ENV) || defined(AFS_AIX32_ENV) || defined(AFS_HPUX100_ENV)
673 sdirEntry->d_off = origOffset;
675 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ,
678 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
679 /* pad out the remaining characters with zeros */
681 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen,
682 UIO_READ, auio, code);
684 /* pad out the difference between rlen and slen... */
685 if (DIRSIZ_LEN(o_slen) < rlen) {
686 while(DIRSIZ_LEN(o_slen) < rlen) {
687 int minLen = rlen - DIRSIZ_LEN(o_slen);
688 if (minLen > sizeof(bufofzeros))
689 minLen = sizeof(bufofzeros);
690 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
694 #else /* AFS_HPUX_ENV */
695 code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
696 #endif /* AFS_HPUX_ENV */
699 len = use64BitDirent ? DIRENTSIZE(o_slen = n_slen) :
700 IRIX5_DIRENTSIZE(o_slen = n_slen);
702 len = DIRSIZ_LEN( o_slen = n_slen );
703 #endif /* AFS_SGI53_ENV */
704 if (ode) DRelease(ode, 0);
706 auio->afsio_offset = (afs_int32)((us + afs_dir_NameBlobs(nde->name)) << 5);
708 if (ode) DRelease(ode, 0);
712 ReleaseReadLock(&avc->lock);
716 osi_FreeSmallSpace((char *)sdirEntry);
718 code = afs_CheckCode(code, &treq, 28);
722 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
724 afs1_readdir(avc, auio, acred, eofp)
727 afs1_readdir(avc, auio, acred)
729 register struct vcache *avc;
731 struct AFS_UCRED *acred; {
732 struct vrequest treq;
733 register struct dcache *tdc;
734 afs_int32 origOffset, len;
736 struct DirEntry *ode = 0, *nde = 0;
737 int o_slen = 0, n_slen = 0;
739 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
741 * XXX All the hacks for alloced sdirEntry and inlining of afs_readdir_move instead of calling
742 * it is necessary for hpux due to stack problems that seem to occur when coming thru the nfs
743 * translator side XXX
745 struct minnfs_direct *sdirEntry = (struct minnfs_direct *)osi_AllocSmallSpace(sizeof(struct min_direct));
749 AFS_STATCNT(afs_readdir);
750 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
753 if (code = afs_InitReq(&treq, acred)) {
755 osi_FreeSmallSpace((char *)sdirEntry);
759 /* update the cache entry */
761 code = afs_VerifyVCache(avc, &treq);
763 /* get a reference to the entire directory */
764 tdc = afs_GetDCache(avc, 0, &treq, &origOffset, &len, 1);
769 ObtainReadLock(&avc->lock);
772 * Make sure that the data in the cache is current. There are two
773 * cases we need to worry about:
774 * 1. The cache data is being fetched by another process.
775 * 2. The cache data is no longer valid
777 while ((avc->states & CStatd)
778 && (tdc->flags & DFFetching)
779 && hsame(avc->m.DataVersion, tdc->f.versionNo)) {
780 tdc->flags |= DFWaiting;
781 ReleaseReadLock(&avc->lock);
782 afs_osi_Sleep(&tdc->validPos);
783 ObtainReadLock(&avc->lock);
785 if (!(avc->states & CStatd)
786 || !hsame(avc->m.DataVersion, tdc->f.versionNo)) {
787 ReleaseReadLock(&avc->lock);
794 auio->uio_fpflags = 0;
797 origOffset = auio->afsio_offset;
799 /* scan for the next interesting entry scan for in-use blob otherwise up point at
800 * this blob note that ode, if non-zero, also represents a held dir page */
801 if (!(us = BlobScan(&tdc->f.inode, (origOffset >> 5)) )
802 || !(nde = (struct DirEntry *) afs_dir_GetBlob(&tdc->f.inode, us) ) ) {
803 /* failed to setup nde, return what we've got, and release ode */
805 /* something to hand over. */
806 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
807 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
808 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
809 sdirEntry->d_reclen = rlen = auio->afsio_resid;
810 sdirEntry->d_namlen = o_slen;
811 sdirEntry->d_off = origOffset;
812 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
814 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
816 /* pad out the remaining characters with zeros */
818 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
820 /* pad out the difference between rlen and slen... */
821 if (NDIRSIZ_LEN(o_slen) < rlen) {
822 while(NDIRSIZ_LEN(o_slen) < rlen) {
823 int minLen = rlen - NDIRSIZ_LEN(o_slen);
824 if (minLen > sizeof(bufofzeros))
825 minLen = sizeof(bufofzeros);
826 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
831 code = afs_readdir_move(ode, avc, auio, o_slen,
832 auio->afsio_resid, origOffset);
833 #endif /* AFS_HPUX_ENV */
834 auio->afsio_resid = 0;
836 /* nothin to hand over */
838 #if defined(AFS_SUN5_ENV) || defined(AFS_SGI_ENV) || defined(AFS_OSF_ENV)
841 if (ode) DRelease(ode, 0);
844 /* by here nde is set */
846 /* Do we have enough user space to carry out our mission? */
847 #if defined(AFS_SGI_ENV)
848 n_slen = strlen(nde->name) + 1; /* NULL terminate */
850 n_slen = strlen(nde->name);
852 if (NDIRSIZ_LEN(n_slen) >= (auio->afsio_resid-len)) {
853 /* No can do no more now; ya know... at this time */
854 DRelease (nde, 0); /* can't use this one. */
856 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
857 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
858 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
859 sdirEntry->d_reclen = rlen = auio->afsio_resid;
860 sdirEntry->d_namlen = o_slen;
861 sdirEntry->d_off = origOffset;
862 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
864 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
865 /* pad out the remaining characters with zeros */
867 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
869 /* pad out the difference between rlen and slen... */
870 if (NDIRSIZ_LEN(o_slen) < rlen) {
871 while(NDIRSIZ_LEN(o_slen) < rlen) {
872 int minLen = rlen - NDIRSIZ_LEN(o_slen);
873 if (minLen > sizeof(bufofzeros))
874 minLen = sizeof(bufofzeros);
875 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
880 code = afs_readdir_move(ode, avc, auio, o_slen,
881 auio->afsio_resid, origOffset);
882 #endif /* AFS_HPUX_ENV */
883 /* this next line used to be AFSVFS40 or AIX 3.1, but is really generic */
884 auio->afsio_offset = origOffset;
885 auio->afsio_resid = 0;
886 } else { /* trouble, can't give anything to the user! */
887 /* even though he has given us a buffer,
888 * even though we have something to give us,
889 * Looks like we lost something somewhere.
893 if (ode) DRelease(ode, 0);
898 * In any event, we move out the LAST de entry, getting ready
899 * to set up for the next one.
902 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
903 sdirEntry->d_fileno = (avc->fid.Fid.Volume << 16) + ntohl(ode->fid.vnode);
904 FIXUPSTUPIDINODE(sdirEntry->d_fileno);
905 sdirEntry->d_reclen = rlen = len;
906 sdirEntry->d_namlen = o_slen;
907 sdirEntry->d_off = origOffset;
908 AFS_UIOMOVE((char *)sdirEntry, sizeof(*sdirEntry), UIO_READ, auio, code);
910 AFS_UIOMOVE(ode->name, o_slen, UIO_READ, auio, code);
911 /* pad out the remaining characters with zeros */
913 AFS_UIOMOVE(bufofzeros, ((o_slen + 4) & ~3) - o_slen, UIO_READ, auio, code);
915 /* pad out the difference between rlen and slen... */
916 if (NDIRSIZ_LEN(o_slen) < rlen) {
917 while(NDIRSIZ_LEN(o_slen) < rlen) {
918 int minLen = rlen - NDIRSIZ_LEN(o_slen);
919 if (minLen > sizeof(bufofzeros))
920 minLen = sizeof(bufofzeros);
921 AFS_UIOMOVE(bufofzeros, minLen, UIO_READ, auio, code);
926 code = afs_readdir_move (ode, avc, auio, o_slen, len, origOffset);
927 #endif /* AFS_HPUX_ENV */
929 len = NDIRSIZ_LEN( o_slen = n_slen );
930 if (ode) DRelease(ode, 0);
932 auio->afsio_offset = ((us + afs_dir_NameBlobs(nde->name)) << 5);
934 if (ode) DRelease(ode, 0);
938 ReleaseReadLock(&avc->lock);
941 #if defined(AFS_HPUX_ENV) || defined(AFS_OSF_ENV)
942 osi_FreeSmallSpace((char *)sdirEntry);
944 code = afs_CheckCode(code, &treq, 29);
949 #endif /* !AFS_LINUX20_ENV */