xref: /illumos-gate/usr/src/uts/common/fs/nfs/nfs4_srv_readdir.c (revision da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <sys/param.h>
29 #include <sys/types.h>
30 #include <sys/systm.h>
31 #include <sys/cred.h>
32 #include <sys/buf.h>
33 #include <sys/vfs.h>
34 #include <sys/vnode.h>
35 #include <sys/uio.h>
36 #include <sys/errno.h>
37 #include <sys/sysmacros.h>
38 #include <sys/statvfs.h>
39 #include <sys/kmem.h>
40 #include <sys/dirent.h>
41 #include <rpc/types.h>
42 #include <rpc/auth.h>
43 #include <rpc/rpcsec_gss.h>
44 #include <rpc/svc.h>
45 #include <sys/strsubr.h>
46 #include <sys/strsun.h>
47 #include <sys/sdt.h>
48 
49 #include <nfs/nfs.h>
50 #include <nfs/export.h>
51 #include <nfs/nfs4.h>
52 
53 
54 /*
55  * RFS4_MINLEN_ENTRY4: XDR-encoded size of smallest possible dirent.
56  *	This is used to return NFS4ERR_TOOSMALL when clients specify
57  *	maxcount that isn't large enough to hold the smallest possible
58  *	XDR encoded dirent.
59  *
60  *	    sizeof cookie (8 bytes) +
61  *	    sizeof name_len (4 bytes) +
62  *	    sizeof smallest (padded) name (4 bytes) +
63  *	    sizeof bitmap4_len (12 bytes) +   NOTE: we always encode len=2 bm4
64  *	    sizeof attrlist4_len (4 bytes) +
65  *	    sizeof next boolean (4 bytes)
66  *
67  * RFS4_MINLEN_RDDIR4: XDR-encoded size of READDIR op reply containing
68  * the smallest possible entry4 (assumes no attrs requested).
69  *	sizeof nfsstat4 (4 bytes) +
70  *	sizeof verifier4 (8 bytes) +
71  *	sizeof entsecond_to_ry4list bool (4 bytes) +
72  *	sizeof entry4 	(36 bytes) +
73  *	sizeof eof bool  (4 bytes)
74  *
75  * RFS4_MINLEN_RDDIR_BUF: minimum length of buffer server will provide to
76  *	VOP_READDIR.  Its value is the size of the maximum possible dirent
77  *	for solaris.  The DIRENT64_RECLEN macro returns	the size of dirent
78  *	required for a given name length.  MAXNAMELEN is the maximum
79  *	filename length allowed in Solaris.  The first two DIRENT64_RECLEN()
80  *	macros are to allow for . and .. entries -- just a minor tweak to try
81  *	and guarantee that buffer we give to VOP_READDIR will be large enough
82  *	to hold ., .., and the largest possible solaris dirent64.
83  */
84 #define	RFS4_MINLEN_ENTRY4 36
85 #define	RFS4_MINLEN_RDDIR4 (4 + NFS4_VERIFIER_SIZE + 4 + RFS4_MINLEN_ENTRY4 + 4)
86 #define	RFS4_MINLEN_RDDIR_BUF \
87 	(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2) + DIRENT64_RECLEN(MAXNAMELEN))
88 
89 
90 #ifdef	nextdp
91 #undef nextdp
92 #endif
93 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
94 
95 verifier4	Readdir4verf = 0x0;
96 
97 static nfs_ftype4 vt_to_nf4[] = {
98 	0, NF4REG, NF4DIR, NF4BLK, NF4CHR, NF4LNK, NF4FIFO, 0, 0, NF4SOCK, 0
99 };
100 
101 
102 int
103 nfs4_readdir_getvp(vnode_t *dvp, char *d_name, vnode_t **vpp,
104 		struct exportinfo **exi, struct svc_req *req,
105 		struct compound_state *cs, int expseudo)
106 {
107 	int error;
108 	int ismntpt;
109 	fid_t fid;
110 	vnode_t *vp, *pre_tvp;
111 	nfsstat4 status;
112 	struct exportinfo *newexi, *saveexi;
113 	cred_t *scr;
114 
115 	*vpp = vp = NULL;
116 
117 	if (error = VOP_LOOKUP(dvp, d_name, &vp, NULL, 0, NULL, cs->cr,
118 	    NULL, NULL, NULL))
119 		return (error);
120 
121 	/* Is this object mounted upon? */
122 	ismntpt = vn_ismntpt(vp);
123 	/*
124 	 * Nothing more to do if object is not a mount point or
125 	 * a possible LOFS shadow of an LOFS mount (which won't
126 	 * have v_vfsmountedhere set)
127 	 */
128 	if (ismntpt == 0 && dvp->v_vfsp == vp->v_vfsp && expseudo == 0) {
129 		*vpp = vp;
130 		return (0);
131 	}
132 
133 	if (ismntpt) {
134 		/*
135 		 * Something is mounted here. Traverse and manage the
136 		 * namespace
137 		 */
138 		pre_tvp = vp;
139 		VN_HOLD(pre_tvp);
140 
141 		if ((error = traverse(&vp)) != 0) {
142 			VN_RELE(pre_tvp);
143 			return (error);
144 		}
145 	}
146 
147 	bzero(&fid, sizeof (fid));
148 	fid.fid_len = MAXFIDSZ;
149 
150 	/*
151 	 * If VOP_FID not supported by underlying fs (mntfs, procfs,
152 	 * etc.), then return attrs for stub instead of VROOT object.
153 	 * If it fails for any other reason, then return the error.
154 	 */
155 	if (error = VOP_FID(vp, &fid, NULL)) {
156 		if (ismntpt == 0) {
157 			VN_RELE(vp);
158 			return (error);
159 		}
160 
161 		if (error != ENOSYS && error != ENOTSUP) {
162 			VN_RELE(vp);
163 			VN_RELE(pre_tvp);
164 			return (error);
165 		}
166 		/* go back to vnode that is "under" mount */
167 		VN_RELE(vp);
168 		*vpp = pre_tvp;
169 		return (0);
170 	}
171 
172 	newexi = checkexport4(&vp->v_vfsp->vfs_fsid, &fid, vp);
173 	if (newexi == NULL) {
174 		if (ismntpt == 0) {
175 			*vpp = vp;
176 		} else {
177 			VN_RELE(vp);
178 			*vpp = pre_tvp;
179 		}
180 		return (0);
181 	}
182 
183 	if (ismntpt)
184 		VN_RELE(pre_tvp);
185 
186 	/* Save the exi and present the new one to checkauth4() */
187 	saveexi = cs->exi;
188 	cs->exi = newexi;
189 
190 	/* Get the right cred like lookup does */
191 	scr = cs->cr;
192 	cs->cr = crdup(cs->basecr);
193 
194 	status = call_checkauth4(cs, req);
195 
196 	crfree(cs->cr);
197 	cs->cr = scr;
198 	cs->exi = saveexi;
199 
200 	/* Reset what call_checkauth4() may have set */
201 	*cs->statusp = NFS4_OK;
202 
203 	if (status != NFS4_OK) {
204 		VN_RELE(vp);
205 		if (status == NFS4ERR_DELAY)
206 			status = NFS4ERR_ACCESS;
207 		return (status);
208 	}
209 	*vpp = vp;
210 	*exi = newexi;
211 
212 	return (0);
213 }
214 
215 /* This is the set of pathconf data for vfs */
216 typedef struct {
217 	uint64_t maxfilesize;
218 	uint32_t maxlink;
219 	uint32_t maxname;
220 } rfs4_pc_encode_t;
221 
222 
223 static int
224 rfs4_get_pc_encode(vnode_t *vp, rfs4_pc_encode_t *pce, bitmap4 ar, cred_t *cr)
225 {
226 	int error;
227 	ulong_t pc_val;
228 
229 	pce->maxfilesize = 0;
230 	pce->maxlink = 0;
231 	pce->maxname = 0;
232 
233 	if (ar & FATTR4_MAXFILESIZE_MASK) {
234 		/* Maximum File Size */
235 		if (error = VOP_PATHCONF(vp, _PC_FILESIZEBITS, &pc_val, cr,
236 		    NULL))
237 			return (error);
238 
239 		if (pc_val >= (sizeof (uint64_t) * 8))
240 			pce->maxfilesize = UINT64_MAX;
241 		else
242 			pce->maxfilesize = ((1LL << pc_val) - 1);
243 	}
244 
245 	if (ar & FATTR4_MAXLINK_MASK) {
246 		/* Maximum Link Count */
247 		if (error = VOP_PATHCONF(vp, _PC_LINK_MAX, &pc_val, cr, NULL))
248 			return (error);
249 
250 		pce->maxlink = pc_val;
251 	}
252 
253 	if (ar & FATTR4_MAXNAME_MASK) {
254 		/* Maximum Name Length */
255 		if (error = VOP_PATHCONF(vp, _PC_NAME_MAX, &pc_val, cr, NULL))
256 			return (error);
257 
258 		pce->maxname = pc_val;
259 	}
260 
261 	return (0);
262 }
263 
264 /* This is the set of statvfs data that is ready for encoding */
265 typedef struct {
266 	uint64_t space_avail;
267 	uint64_t space_free;
268 	uint64_t space_total;
269 	u_longlong_t fa;
270 	u_longlong_t ff;
271 	u_longlong_t ft;
272 } rfs4_sb_encode_t;
273 
274 static int
275 rfs4_get_sb_encode(vfs_t *vfsp, rfs4_sb_encode_t *psbe)
276 {
277 	int error;
278 	struct statvfs64 sb;
279 
280 	/* Grab the per filesystem info */
281 	if (error = VFS_STATVFS(vfsp, &sb)) {
282 		return (error);
283 	}
284 
285 	/* Calculate space available */
286 	if (sb.f_bavail != (fsblkcnt64_t)-1) {
287 		psbe->space_avail =
288 			(fattr4_space_avail) sb.f_frsize *
289 			(fattr4_space_avail) sb.f_bavail;
290 	} else {
291 		psbe->space_avail =
292 			(fattr4_space_avail) sb.f_bavail;
293 	}
294 
295 	/* Calculate space free */
296 	if (sb.f_bfree != (fsblkcnt64_t)-1) {
297 		psbe->space_free =
298 			(fattr4_space_free) sb.f_frsize *
299 			(fattr4_space_free) sb.f_bfree;
300 	} else {
301 		psbe->space_free =
302 			(fattr4_space_free) sb.f_bfree;
303 	}
304 
305 	/* Calculate space total */
306 	if (sb.f_blocks != (fsblkcnt64_t)-1) {
307 		psbe->space_total =
308 			(fattr4_space_total) sb.f_frsize *
309 			(fattr4_space_total) sb.f_blocks;
310 	} else {
311 		psbe->space_total =
312 			(fattr4_space_total) sb.f_blocks;
313 	}
314 
315 	/* For use later on attr encode */
316 	psbe->fa = sb.f_favail;
317 	psbe->ff = sb.f_ffree;
318 	psbe->ft = sb.f_files;
319 
320 	return (0);
321 }
322 
323 /*
324  * Macros to handle if we have don't have enough space for the requested
325  * attributes and this is the first entry and the
326  * requested attributes are more than the minimal useful
327  * set, reset the attributes to the minimal set and
328  * retry the encoding. If the client has asked for both
329  * mounted_on_fileid and fileid, prefer mounted_on_fileid.
330  */
331 #define	MINIMAL_RD_ATTRS						\
332 	(FATTR4_MOUNTED_ON_FILEID_MASK|					\
333 	FATTR4_FILEID_MASK|						\
334 	FATTR4_RDATTR_ERROR_MASK)
335 
336 #define	MINIMIZE_ATTR_MASK(m) {						\
337 	if ((m) & FATTR4_MOUNTED_ON_FILEID_MASK)			\
338 	    (m) &= FATTR4_RDATTR_ERROR_MASK|FATTR4_MOUNTED_ON_FILEID_MASK;\
339 	else								\
340 	    (m) &= FATTR4_RDATTR_ERROR_MASK|FATTR4_FILEID_MASK;		\
341 }
342 
343 #define	IS_MIN_ATTR_MASK(m)	(((m) & ~MINIMAL_RD_ATTRS) == 0)
344 /*
345  * If readdir only needs to return FILEID, we can take it from the
346  * dirent struct and save doing the lookup.
347  */
348 /* ARGSUSED */
349 void
350 rfs4_op_readdir(nfs_argop4 *argop, nfs_resop4 *resop,
351 	struct svc_req *req, struct compound_state *cs)
352 {
353 	READDIR4args *args = &argop->nfs_argop4_u.opreaddir;
354 	READDIR4res *resp = &resop->nfs_resop4_u.opreaddir;
355 	struct exportinfo *newexi = NULL;
356 	int error;
357 	mblk_t *mp;
358 	uint_t mpcount;
359 	int alloc_err = 0;
360 	vnode_t *dvp = cs->vp;
361 	vnode_t *vp;
362 	vattr_t va;
363 	struct dirent64 *dp;
364 	rfs4_sb_encode_t dsbe, sbe;
365 	int vfs_different;
366 	int rddir_data_len, rddir_result_size;
367 	caddr_t rddir_data;
368 	offset_t rddir_next_offset;
369 	int dircount;
370 	int no_space;
371 	int iseofdir;
372 	uint_t eof;
373 	struct iovec iov;
374 	struct uio uio;
375 	int tsize;
376 	int check_visible;
377 	int expseudo = 0;
378 
379 	uint32_t *ptr, *ptr_redzone;
380 	uint32_t *beginning_ptr;
381 	uint32_t *lastentry_ptr;
382 	uint32_t *attrmask_ptr;
383 	uint32_t *attr_offset_ptr;
384 	uint32_t attr_length;
385 	uint32_t rndup;
386 	uint32_t namelen;
387 	uint32_t rddirattr_error = 0;
388 	int nents;
389 	bitmap4 ar = args->attr_request & NFS4_SRV_RDDIR_SUPPORTED_ATTRS;
390 	bitmap4 ae;
391 	rfs4_pc_encode_t dpce, pce;
392 	ulong_t pc_val;
393 	uint64_t maxread;
394 	uint64_t maxwrite;
395 	uint_t true = TRUE;
396 	uint_t false = FALSE;
397 	uid_t lastuid;
398 	gid_t lastgid;
399 	int lu_set, lg_set;
400 	utf8string owner, group;
401 	int owner_error, group_error;
402 
403 	lu_set = lg_set = 0;
404 	owner.utf8string_len = group.utf8string_len = 0;
405 	owner.utf8string_val = group.utf8string_val = NULL;
406 
407 	resp->mblk = NULL;
408 
409 	/* Maximum read and write size */
410 	maxread = maxwrite = rfs4_tsize(req);
411 
412 	if (dvp == NULL) {
413 		*cs->statusp = resp->status = NFS4ERR_NOFILEHANDLE;
414 		return;
415 	}
416 
417 	/*
418 	 * If there is an unshared filesystem mounted on this vnode,
419 	 * do not allow readdir in this directory.
420 	 */
421 	if (vn_ismntpt(dvp)) {
422 		*cs->statusp = resp->status = NFS4ERR_ACCESS;
423 		return;
424 	}
425 
426 	if (dvp->v_type != VDIR) {
427 		*cs->statusp = resp->status = NFS4ERR_NOTDIR;
428 		return;
429 	}
430 
431 	if (args->maxcount <= RFS4_MINLEN_RDDIR4) {
432 		*cs->statusp = resp->status = NFS4ERR_TOOSMALL;
433 		return;
434 	}
435 
436 	/*
437 	 * If write-only attrs are requested, then fail the readdir op
438 	 */
439 	if (args->attr_request &
440 	    (FATTR4_TIME_MODIFY_SET_MASK | FATTR4_TIME_ACCESS_SET_MASK)) {
441 		*cs->statusp = resp->status = NFS4ERR_INVAL;
442 		return;
443 	}
444 
445 	error = VOP_ACCESS(dvp, VREAD, 0, cs->cr, NULL);
446 	if (error) {
447 		*cs->statusp = resp->status = puterrno4(error);
448 		return;
449 	}
450 
451 	if (args->cookieverf != Readdir4verf) {
452 		*cs->statusp = resp->status = NFS4ERR_NOT_SAME;
453 		return;
454 	}
455 
456 	/* Is there pseudo-fs work that is needed for this readdir? */
457 	check_visible = PSEUDO(cs->exi) ||
458 		! is_exported_sec(cs->nfsflavor, cs->exi) ||
459 		cs->access & CS_ACCESS_LIMITED;
460 
461 	/* Check the requested attributes and only do the work if needed */
462 
463 	if (ar & (FATTR4_MAXFILESIZE_MASK |
464 		FATTR4_MAXLINK_MASK |
465 		FATTR4_MAXNAME_MASK)) {
466 		if (error = rfs4_get_pc_encode(cs->vp, &dpce, ar, cs->cr)) {
467 			*cs->statusp = resp->status = puterrno4(error);
468 			return;
469 		}
470 		pce = dpce;
471 	}
472 
473 	/* If there is statvfs data requested, pick it up once */
474 	if (ar &
475 	    (FATTR4_FILES_AVAIL_MASK |
476 	    FATTR4_FILES_FREE_MASK |
477 	    FATTR4_FILES_TOTAL_MASK |
478 	    FATTR4_FILES_AVAIL_MASK |
479 	    FATTR4_FILES_FREE_MASK |
480 	    FATTR4_FILES_TOTAL_MASK)) {
481 		if (error = rfs4_get_sb_encode(dvp->v_vfsp, &dsbe)) {
482 			*cs->statusp = resp->status = puterrno4(error);
483 			return;
484 		}
485 		sbe = dsbe;
486 	}
487 
488 	/*
489 	 * Max transfer size of the server is the absolute limite.
490 	 * If the client has decided to max out with something really
491 	 * tiny, then return toosmall.  Otherwise, move forward and
492 	 * see if a single entry can be encoded.
493 	 */
494 	tsize = rfs4_tsize(req);
495 	if (args->maxcount > tsize)
496 		args->maxcount = tsize;
497 	else if (args->maxcount < RFS4_MINLEN_RDDIR_BUF) {
498 		if (args->maxcount < RFS4_MINLEN_ENTRY4) {
499 			*cs->statusp = resp->status = NFS4ERR_TOOSMALL;
500 			return;
501 		}
502 	}
503 
504 	/*
505 	 * How large should the mblk be for outgoing encoding.
506 	 */
507 	if (args->maxcount < MAXBSIZE)
508 		mpcount = MAXBSIZE;
509 	else
510 		mpcount = args->maxcount;
511 
512 	/*
513 	 * mp will contain the data to be sent out in the readdir reply.
514 	 * It will be freed after the reply has been sent.
515 	 * Let's roundup the data to a BYTES_PER_XDR_UNIX multiple,
516 	 * so that the call to xdrmblk_putmblk() never fails.
517 	 */
518 	mp = allocb(RNDUP(mpcount), BPRI_MED);
519 
520 	if (mp == NULL) {
521 		/*
522 		 * The allocation of the client's requested size has
523 		 * failed.  It may be that the size is too large for
524 		 * current system utilization; step down to a "common"
525 		 * size and wait for the allocation to occur.
526 		 */
527 		if (mpcount > MAXBSIZE)
528 			args->maxcount = mpcount = MAXBSIZE;
529 		mp = allocb_wait(RNDUP(mpcount), BPRI_MED,
530 				STR_NOSIG, &alloc_err);
531 	}
532 
533 	ASSERT(mp != NULL);
534 	ASSERT(alloc_err == 0);
535 
536 	resp->mblk = mp;
537 
538 	ptr = beginning_ptr = (uint32_t *)mp->b_datap->db_base;
539 
540 	/*
541 	 * The "redzone" at the end of the encoding buffer is used
542 	 * to deal with xdr encoding length.  Instead of checking
543 	 * each encoding of an attribute value before it is done,
544 	 * make the assumption that it will fit into the buffer and
545 	 * check occasionally.
546 	 *
547 	 * The largest block of attributes that are encoded without
548 	 * checking the redzone is 18 * BYTES_PER_XDR_UNIT (72 bytes)
549 	 * "round" to 128 as the redzone size.
550 	 */
551 	if (args->maxcount < (mpcount - 128))
552 		ptr_redzone =
553 			(uint32_t *)(((char *)ptr) + RNDUP(args->maxcount));
554 	else
555 		ptr_redzone =
556 			(uint32_t *)((((char *)ptr) + RNDUP(mpcount)) - 128);
557 
558 	/*
559 	 * Set the dircount; this will be used as the size for the
560 	 * readdir of the underlying filesystem.  First make sure
561 	 * that it is large enough to do a reasonable readdir (client
562 	 * may have short changed us - it is an advisory number);
563 	 * then make sure that it isn't too large.
564 	 * After all of that, if maxcount is "small" then just use
565 	 * that for the dircount number.
566 	 */
567 	dircount = (args->dircount < MAXBSIZE) ? MAXBSIZE : args->dircount;
568 	dircount = (dircount > tsize) ? tsize : dircount;
569 	if (dircount > args->maxcount)
570 		dircount = args->maxcount;
571 	if (args->maxcount <= MAXBSIZE) {
572 		if (args->maxcount < RFS4_MINLEN_RDDIR_BUF)
573 			dircount = RFS4_MINLEN_RDDIR_BUF;
574 		else
575 			dircount = args->maxcount;
576 	}
577 
578 	/* number of entries fully encoded in outgoing buffer */
579 	nents = 0;
580 
581 	/* ENCODE READDIR4res.cookieverf */
582 	IXDR_PUT_HYPER(ptr, Readdir4verf);
583 
584 	rddir_data_len = dircount;
585 	rddir_data = kmem_alloc(rddir_data_len, KM_NOSLEEP);
586 	if (rddir_data == NULL) {
587 		/* The allocation failed; downsize and wait for it this time */
588 		if (rddir_data_len > MAXBSIZE)
589 			rddir_data_len = dircount = MAXBSIZE;
590 		rddir_data = kmem_alloc(rddir_data_len, KM_SLEEP);
591 	}
592 
593 	rddir_next_offset = (offset_t)args->cookie;
594 
595 readagain:
596 
597 	no_space = FALSE;
598 	iseofdir = FALSE;
599 
600 	vp = NULL;
601 
602 	/* Move on to reading the directory contents */
603 	iov.iov_base = rddir_data;
604 	iov.iov_len = rddir_data_len;
605 	uio.uio_iov = &iov;
606 	uio.uio_iovcnt = 1;
607 	uio.uio_segflg = UIO_SYSSPACE;
608 	uio.uio_extflg = UIO_COPY_CACHED;
609 	uio.uio_loffset = rddir_next_offset;
610 	uio.uio_resid = rddir_data_len;
611 
612 	(void) VOP_RWLOCK(dvp, V_WRITELOCK_FALSE, NULL);
613 
614 	error = VOP_READDIR(dvp, &uio, cs->cr, &iseofdir, NULL, 0);
615 
616 	VOP_RWUNLOCK(dvp, V_WRITELOCK_FALSE, NULL);
617 
618 	if (error) {
619 		kmem_free((caddr_t)rddir_data, rddir_data_len);
620 		freeb(resp->mblk);
621 		resp->mblk = NULL;
622 		resp->data_len = 0;
623 		*cs->statusp = resp->status = puterrno4(error);
624 		return;
625 	}
626 
627 
628 	rddir_result_size = rddir_data_len - uio.uio_resid;
629 
630 	/* Reading at the end of the directory */
631 	if (iseofdir && (rddir_result_size == 0)) {
632 		/* encode the BOOLEAN marking no further entries */
633 		IXDR_PUT_U_INT32(ptr, false);
634 		/* encode the BOOLEAN signifying end of directory */
635 		IXDR_PUT_U_INT32(ptr, true);
636 		resp->data_len = (char *)ptr - (char *)beginning_ptr;
637 		resp->mblk->b_wptr += resp->data_len;
638 		kmem_free((caddr_t)rddir_data, rddir_data_len);
639 		*cs->statusp = resp->status = NFS4_OK;
640 		return;
641 	}
642 
643 	lastentry_ptr = ptr;
644 	no_space = 0;
645 	for (dp = (struct dirent64 *)rddir_data;
646 			!no_space && rddir_result_size > 0; dp = nextdp(dp)) {
647 
648 		/* reset expseudo */
649 		expseudo = 0;
650 
651 		if (vp) {
652 			VN_RELE(vp);
653 			vp = NULL;
654 		}
655 
656 		if (newexi)
657 			newexi = NULL;
658 
659 		rddir_result_size -= dp->d_reclen;
660 
661 		/* skip "." and ".." entries */
662 		if (dp->d_ino == 0 || NFS_IS_DOTNAME(dp->d_name)) {
663 			rddir_next_offset = dp->d_off;
664 			continue;
665 		}
666 
667 		if (check_visible &&
668 		    !nfs_visible_inode(cs->exi, dp->d_ino, &expseudo)) {
669 			rddir_next_offset = dp->d_off;
670 			continue;
671 		}
672 
673 		/*
674 		 * Only if the client requested attributes...
675 		 * If the VOP_LOOKUP fails ENOENT, then skip this entry
676 		 * for the readdir response.  If there was another error,
677 		 * then set the rddirattr_error and the error will be
678 		 * encoded later in the "attributes" section.
679 		 */
680 		ae = ar;
681 		if (ar != 0) {
682 			error = nfs4_readdir_getvp(dvp, dp->d_name,
683 						&vp, &newexi, req, cs,
684 						expseudo);
685 			if (error == ENOENT) {
686 				rddir_next_offset = dp->d_off;
687 				continue;
688 			}
689 
690 			rddirattr_error = error;
691 
692 			/*
693 			 * The vp obtained from above may be from a
694 			 * different filesystem mount and the vfs-like
695 			 * attributes should be obtained from that
696 			 * different vfs; only do this if appropriate.
697 			 */
698 			if (vp &&
699 			    (vfs_different = (dvp->v_vfsp != vp->v_vfsp))) {
700 				if (ar & (FATTR4_FILES_AVAIL_MASK |
701 					FATTR4_FILES_FREE_MASK |
702 					FATTR4_FILES_TOTAL_MASK |
703 					FATTR4_FILES_AVAIL_MASK |
704 					FATTR4_FILES_FREE_MASK |
705 					FATTR4_FILES_TOTAL_MASK)) {
706 				    if (error =
707 					rfs4_get_sb_encode(dvp->v_vfsp, &sbe)) {
708 					    /* Remove attrs from encode */
709 					    ae &= ~(FATTR4_FILES_AVAIL_MASK |
710 						FATTR4_FILES_FREE_MASK |
711 						FATTR4_FILES_TOTAL_MASK |
712 						FATTR4_FILES_AVAIL_MASK |
713 						FATTR4_FILES_FREE_MASK |
714 						FATTR4_FILES_TOTAL_MASK);
715 					    rddirattr_error = error;
716 				    }
717 				}
718 				if (ar & (FATTR4_MAXFILESIZE_MASK |
719 					FATTR4_MAXLINK_MASK |
720 					FATTR4_MAXNAME_MASK)) {
721 				    if (error =
722 					rfs4_get_pc_encode(cs->vp,
723 							&pce, ar, cs->cr)) {
724 					    ar &= ~(FATTR4_MAXFILESIZE_MASK |
725 						    FATTR4_MAXLINK_MASK |
726 						    FATTR4_MAXNAME_MASK);
727 					    rddirattr_error = error;
728 				    }
729 				}
730 			}
731 		}
732 
733 reencode_attrs:
734 		/* encode the BOOLEAN for the existence of the next entry */
735 		IXDR_PUT_U_INT32(ptr, true);
736 		/* encode the COOKIE for the entry */
737 		IXDR_PUT_U_HYPER(ptr, dp->d_off);
738 
739 		/* Calculate the dirent name length */
740 		namelen = strlen(dp->d_name);
741 
742 		rndup = RNDUP(namelen) / BYTES_PER_XDR_UNIT;
743 
744 		/* room for LENGTH + string ? */
745 		if ((ptr + (1 + rndup)) > ptr_redzone) {
746 			no_space = TRUE;
747 			continue;
748 		}
749 
750 		/* encode the LENGTH of the name */
751 		IXDR_PUT_U_INT32(ptr, namelen);
752 		/* encode the RNDUP FILL first */
753 		ptr[rndup - 1] = 0;
754 		/* encode the NAME of the entry */
755 		bcopy(dp->d_name, (char *)ptr, namelen);
756 		/* now bump the ptr after... */
757 		ptr += rndup;
758 
759 		/*
760 		 * Keep checking on the dircount to see if we have
761 		 * reached the limit; from the RFC, dircount is to be
762 		 * the XDR encoded limit of the cookie plus name.
763 		 * So the count is the name, XDR_UNIT of length for
764 		 * that name and 2 * XDR_UNIT bytes of cookie;
765 		 * However, use the regular DIRENT64 to match most
766 		 * client's APIs.
767 		 */
768 		dircount -= DIRENT64_RECLEN(namelen);
769 		if (nents != 0 && dircount < 0) {
770 			no_space = TRUE;
771 			continue;
772 		}
773 
774 		/*
775 		 * Attributes requested?
776 		 * Gather up the attribute info and the previous VOP_LOOKUP()
777 		 * succeeded; if an error occurs on the VOP_GETATTR() then
778 		 * return just the error (again if it is requested).
779 		 * Note that the previous VOP_LOOKUP() could have failed
780 		 * itself which leaves this code without anything for
781 		 * a VOP_GETATTR().
782 		 * Also note that the readdir_attr_error is left in the
783 		 * encoding mask if requested and so is the mounted_on_fileid.
784 		 */
785 		if (ae != 0) {
786 			if (!vp) {
787 				ae = ar & (FATTR4_RDATTR_ERROR_MASK |
788 					FATTR4_MOUNTED_ON_FILEID_MASK);
789 			} else {
790 				va.va_mask = AT_ALL;
791 				rddirattr_error =
792 					VOP_GETATTR(vp, &va, 0, cs->cr, NULL);
793 				if (rddirattr_error)
794 					ae = ar & (FATTR4_RDATTR_ERROR_MASK |
795 						FATTR4_MOUNTED_ON_FILEID_MASK);
796 			}
797 		}
798 
799 		/* START OF ATTRIBUTE ENCODING */
800 
801 		/* encode the LENGTH of the BITMAP4 array */
802 		IXDR_PUT_U_INT32(ptr, 2);
803 		/* encode the BITMAP4 */
804 		attrmask_ptr = ptr;
805 		IXDR_PUT_HYPER(ptr, ae);
806 		attr_offset_ptr = ptr;
807 		/* encode the default LENGTH of the attributes for entry */
808 		IXDR_PUT_U_INT32(ptr, 0);
809 
810 		if (ptr > ptr_redzone) {
811 			no_space = TRUE;
812 			continue;
813 		}
814 
815 		/* Check if any of the first 32 attributes are being encoded */
816 		if (ae & 0xffffffff00000000) {
817 			/*
818 			 * Redzone check is done at the end of this section.
819 			 * This particular section will encode a maximum of
820 			 * 18 * BYTES_PER_XDR_UNIT of data
821 			 */
822 			if (ae &
823 			    (FATTR4_SUPPORTED_ATTRS_MASK |
824 			    FATTR4_TYPE_MASK |
825 			    FATTR4_FH_EXPIRE_TYPE_MASK |
826 			    FATTR4_CHANGE_MASK |
827 			    FATTR4_SIZE_MASK |
828 			    FATTR4_LINK_SUPPORT_MASK |
829 			    FATTR4_SYMLINK_SUPPORT_MASK |
830 			    FATTR4_NAMED_ATTR_MASK |
831 			    FATTR4_FSID_MASK |
832 			    FATTR4_UNIQUE_HANDLES_MASK |
833 			    FATTR4_LEASE_TIME_MASK |
834 			    FATTR4_RDATTR_ERROR_MASK)) {
835 
836 				if (ae & FATTR4_SUPPORTED_ATTRS_MASK) {
837 					IXDR_PUT_INT32(ptr, 2);
838 					IXDR_PUT_HYPER(ptr,
839 							rfs4_supported_attrs);
840 				}
841 				if (ae & FATTR4_TYPE_MASK) {
842 					uint_t ftype = vt_to_nf4[va.va_type];
843 					if (dvp->v_flag & V_XATTRDIR) {
844 						if (va.va_type == VDIR)
845 							ftype = NF4ATTRDIR;
846 						else
847 							ftype = NF4NAMEDATTR;
848 					}
849 					IXDR_PUT_U_INT32(ptr, ftype);
850 				}
851 				if (ae & FATTR4_FH_EXPIRE_TYPE_MASK) {
852 					uint_t expire_type = FH4_PERSISTENT;
853 					IXDR_PUT_U_INT32(ptr, expire_type);
854 				}
855 				if (ae & FATTR4_CHANGE_MASK) {
856 					u_longlong_t change;
857 					NFS4_SET_FATTR4_CHANGE(change,
858 							va.va_ctime);
859 					IXDR_PUT_HYPER(ptr, change);
860 				}
861 				if (ae & FATTR4_SIZE_MASK) {
862 					u_longlong_t size = va.va_size;
863 					IXDR_PUT_HYPER(ptr, size);
864 				}
865 				if (ae & FATTR4_LINK_SUPPORT_MASK) {
866 					IXDR_PUT_U_INT32(ptr, true);
867 				}
868 				if (ae & FATTR4_SYMLINK_SUPPORT_MASK) {
869 					IXDR_PUT_U_INT32(ptr, true);
870 				}
871 				if (ae & FATTR4_NAMED_ATTR_MASK) {
872 					uint_t isit;
873 					pc_val = FALSE;
874 
875 					if (!(vp->v_vfsp->vfs_flag &
876 						VFS_XATTR)) {
877 						isit = FALSE;
878 					} else {
879 						(void) VOP_PATHCONF(vp,
880 							_PC_XATTR_EXISTS,
881 							&pc_val, cs->cr, NULL);
882 					}
883 					isit = (pc_val ? TRUE : FALSE);
884 					IXDR_PUT_U_INT32(ptr, isit);
885 				}
886 				if (ae & FATTR4_FSID_MASK) {
887 					u_longlong_t major, minor;
888 					struct exportinfo *exi;
889 
890 					exi = newexi ? newexi : cs->exi;
891 					if (exi->exi_volatile_dev) {
892 						int *pmaj = (int *)&major;
893 
894 						pmaj[0] = exi->exi_fsid.val[0];
895 						pmaj[1] = exi->exi_fsid.val[1];
896 						minor = 0;
897 					} else {
898 						major = getmajor(va.va_fsid);
899 						minor = getminor(va.va_fsid);
900 					}
901 					IXDR_PUT_HYPER(ptr, major);
902 					IXDR_PUT_HYPER(ptr, minor);
903 				}
904 				if (ae & FATTR4_UNIQUE_HANDLES_MASK) {
905 					IXDR_PUT_U_INT32(ptr, false);
906 				}
907 				if (ae & FATTR4_LEASE_TIME_MASK) {
908 					uint_t lt = rfs4_lease_time;
909 					IXDR_PUT_U_INT32(ptr, lt);
910 				}
911 				if (ae & FATTR4_RDATTR_ERROR_MASK) {
912 					rddirattr_error =
913 						(rddirattr_error == 0 ?
914 						0 : puterrno4(rddirattr_error));
915 					IXDR_PUT_U_INT32(ptr, rddirattr_error);
916 				}
917 
918 				/* Check the redzone boundary */
919 				if (ptr > ptr_redzone) {
920 					if (nents || IS_MIN_ATTR_MASK(ar)) {
921 						no_space = TRUE;
922 						continue;
923 					}
924 					MINIMIZE_ATTR_MASK(ar);
925 					ae = ar;
926 					ptr = lastentry_ptr;
927 					goto reencode_attrs;
928 				}
929 			}
930 			/*
931 			 * Redzone check is done at the end of this section.
932 			 * This particular section will encode a maximum of
933 			 * 4 * BYTES_PER_XDR_UNIT of data.
934 			 * NOTE: that if ACLs are supported that the
935 			 * redzone calculations will need to change.
936 			 */
937 			if (ae &
938 			    (FATTR4_ACL_MASK |
939 			    FATTR4_ACLSUPPORT_MASK |
940 			    FATTR4_ARCHIVE_MASK |
941 			    FATTR4_CANSETTIME_MASK |
942 			    FATTR4_CASE_INSENSITIVE_MASK |
943 			    FATTR4_CASE_PRESERVING_MASK |
944 			    FATTR4_CHOWN_RESTRICTED_MASK)) {
945 
946 				if (ae & FATTR4_ACL_MASK) {
947 					ASSERT(0);
948 				}
949 				if (ae & FATTR4_ACLSUPPORT_MASK) {
950 					ASSERT(0);
951 				}
952 				if (ae & FATTR4_ARCHIVE_MASK) {
953 					ASSERT(0);
954 				}
955 				if (ae & FATTR4_CANSETTIME_MASK) {
956 					IXDR_PUT_U_INT32(ptr, true);
957 				}
958 				if (ae & FATTR4_CASE_INSENSITIVE_MASK) {
959 					IXDR_PUT_U_INT32(ptr, false);
960 				}
961 				if (ae & FATTR4_CASE_PRESERVING_MASK) {
962 					IXDR_PUT_U_INT32(ptr, true);
963 				}
964 				if (ae & FATTR4_CHOWN_RESTRICTED_MASK) {
965 					uint_t isit;
966 					pc_val = FALSE;
967 					(void) VOP_PATHCONF(vp,
968 							_PC_CHOWN_RESTRICTED,
969 							&pc_val, cs->cr, NULL);
970 					isit = (pc_val ? TRUE : FALSE);
971 					IXDR_PUT_U_INT32(ptr, isit);
972 				}
973 				/* Check the redzone boundary */
974 				if (ptr > ptr_redzone) {
975 					if (nents || IS_MIN_ATTR_MASK(ar)) {
976 						no_space = TRUE;
977 						continue;
978 					}
979 					MINIMIZE_ATTR_MASK(ar);
980 					ae = ar;
981 					ptr = lastentry_ptr;
982 					goto reencode_attrs;
983 				}
984 			}
985 			/*
986 			 * Redzone check is done before the filehandle
987 			 * is encoded.
988 			 */
989 			if (ae &
990 			    (FATTR4_FILEHANDLE_MASK |
991 			    FATTR4_FILEID_MASK)) {
992 
993 				if (ae & FATTR4_FILEHANDLE_MASK) {
994 					struct {
995 						uint_t len;
996 						char *val;
997 						char fh[NFS_FH4_LEN];
998 					} fh;
999 					fh.len = 0;
1000 					fh.val = fh.fh;
1001 					(void) makefh4((nfs_fh4 *)&fh, vp,
1002 					    (newexi ? newexi : cs->exi));
1003 
1004 					if (!xdr_inline_encode_nfs_fh4(
1005 					    &ptr, ptr_redzone,
1006 					    (nfs_fh4_fmt_t *)fh.val)) {
1007 						if (nents ||
1008 						    IS_MIN_ATTR_MASK(ar)) {
1009 							no_space = TRUE;
1010 							continue;
1011 						}
1012 						MINIMIZE_ATTR_MASK(ar);
1013 						ae = ar;
1014 						ptr = lastentry_ptr;
1015 						goto reencode_attrs;
1016 					}
1017 				}
1018 				if (ae & FATTR4_FILEID_MASK) {
1019 					IXDR_PUT_HYPER(ptr, va.va_nodeid);
1020 				}
1021 				/* Check the redzone boundary */
1022 				if (ptr > ptr_redzone) {
1023 					if (nents || IS_MIN_ATTR_MASK(ar)) {
1024 						no_space = TRUE;
1025 						continue;
1026 					}
1027 					MINIMIZE_ATTR_MASK(ar);
1028 					ae = ar;
1029 					ptr = lastentry_ptr;
1030 					goto reencode_attrs;
1031 				}
1032 			}
1033 			/*
1034 			 * Redzone check is done at the end of this section.
1035 			 * This particular section will encode a maximum of
1036 			 * 15 * BYTES_PER_XDR_UNIT of data.
1037 			 */
1038 			if (ae &
1039 			    (FATTR4_FILES_AVAIL_MASK |
1040 			    FATTR4_FILES_FREE_MASK |
1041 			    FATTR4_FILES_TOTAL_MASK |
1042 			    FATTR4_FS_LOCATIONS_MASK |
1043 			    FATTR4_HIDDEN_MASK |
1044 			    FATTR4_HOMOGENEOUS_MASK |
1045 			    FATTR4_MAXFILESIZE_MASK |
1046 			    FATTR4_MAXLINK_MASK |
1047 			    FATTR4_MAXNAME_MASK |
1048 			    FATTR4_MAXREAD_MASK |
1049 			    FATTR4_MAXWRITE_MASK)) {
1050 
1051 				if (ae & FATTR4_FILES_AVAIL_MASK) {
1052 					IXDR_PUT_HYPER(ptr, sbe.fa);
1053 				}
1054 				if (ae & FATTR4_FILES_FREE_MASK) {
1055 					IXDR_PUT_HYPER(ptr, sbe.ff);
1056 				}
1057 				if (ae & FATTR4_FILES_TOTAL_MASK) {
1058 					IXDR_PUT_HYPER(ptr, sbe.ft);
1059 				}
1060 				if (ae & FATTR4_FS_LOCATIONS_MASK) {
1061 					ASSERT(0);
1062 				}
1063 				if (ae & FATTR4_HIDDEN_MASK) {
1064 					ASSERT(0);
1065 				}
1066 				if (ae & FATTR4_HOMOGENEOUS_MASK) {
1067 					IXDR_PUT_U_INT32(ptr, true);
1068 				}
1069 				if (ae & FATTR4_MAXFILESIZE_MASK) {
1070 					IXDR_PUT_HYPER(ptr, pce.maxfilesize);
1071 				}
1072 				if (ae & FATTR4_MAXLINK_MASK) {
1073 					IXDR_PUT_U_INT32(ptr, pce.maxlink);
1074 				}
1075 				if (ae & FATTR4_MAXNAME_MASK) {
1076 					IXDR_PUT_U_INT32(ptr, pce.maxname);
1077 				}
1078 				if (ae & FATTR4_MAXREAD_MASK) {
1079 					IXDR_PUT_HYPER(ptr, maxread);
1080 				}
1081 				if (ae & FATTR4_MAXWRITE_MASK) {
1082 					IXDR_PUT_HYPER(ptr, maxwrite);
1083 				}
1084 				/* Check the redzone boundary */
1085 				if (ptr > ptr_redzone) {
1086 					if (nents || IS_MIN_ATTR_MASK(ar)) {
1087 						no_space = TRUE;
1088 						continue;
1089 					}
1090 					MINIMIZE_ATTR_MASK(ar);
1091 					ae = ar;
1092 					ptr = lastentry_ptr;
1093 					goto reencode_attrs;
1094 				}
1095 			}
1096 		}
1097 		if (ae & 0x00000000ffffffff) {
1098 			/*
1099 			 * Redzone check is done at the end of this section.
1100 			 * This particular section will encode a maximum of
1101 			 * 3 * BYTES_PER_XDR_UNIT of data.
1102 			 */
1103 			if (ae &
1104 			    (FATTR4_MIMETYPE_MASK |
1105 			    FATTR4_MODE_MASK |
1106 			    FATTR4_NO_TRUNC_MASK |
1107 			    FATTR4_NUMLINKS_MASK)) {
1108 
1109 				if (ae & FATTR4_MIMETYPE_MASK) {
1110 					ASSERT(0);
1111 				}
1112 				if (ae & FATTR4_MODE_MASK) {
1113 					uint_t m = va.va_mode;
1114 					IXDR_PUT_U_INT32(ptr, m);
1115 				}
1116 				if (ae & FATTR4_NO_TRUNC_MASK) {
1117 					IXDR_PUT_U_INT32(ptr, true);
1118 				}
1119 				if (ae & FATTR4_NUMLINKS_MASK) {
1120 					IXDR_PUT_U_INT32(ptr, va.va_nlink);
1121 				}
1122 				/* Check the redzone boundary */
1123 				if (ptr > ptr_redzone) {
1124 					if (nents || IS_MIN_ATTR_MASK(ar)) {
1125 						no_space = TRUE;
1126 						continue;
1127 					}
1128 					MINIMIZE_ATTR_MASK(ar);
1129 					ae = ar;
1130 					ptr = lastentry_ptr;
1131 					goto reencode_attrs;
1132 				}
1133 			}
1134 			/*
1135 			 * Redzone check is done before the encoding of the
1136 			 * owner string since the length is indeterminate.
1137 			 */
1138 			if (ae & FATTR4_OWNER_MASK) {
1139 				if (!lu_set) {
1140 				    owner_error = nfs_idmap_uid_str(va.va_uid,
1141 								&owner, TRUE);
1142 				    if (!owner_error) {
1143 					    lu_set = TRUE;
1144 					    lastuid = va.va_uid;
1145 				    }
1146 				} else {
1147 				    if (va.va_uid != lastuid) {
1148 					if (owner.utf8string_len != 0) {
1149 					    kmem_free(owner.utf8string_val,
1150 						owner.utf8string_len);
1151 						owner.utf8string_len = 0;
1152 						owner.utf8string_val = NULL;
1153 					}
1154 					owner_error = nfs_idmap_uid_str(
1155 							va.va_uid,
1156 							&owner, TRUE);
1157 					if (!owner_error) {
1158 						lastuid = va.va_uid;
1159 					} else {
1160 						lu_set = FALSE;
1161 					}
1162 				    }
1163 				}
1164 				if (!owner_error) {
1165 					if ((ptr +
1166 					    (owner.utf8string_len /
1167 					    BYTES_PER_XDR_UNIT)
1168 					    + 2) > ptr_redzone) {
1169 						if (nents ||
1170 						    IS_MIN_ATTR_MASK(ar)) {
1171 							no_space = TRUE;
1172 							continue;
1173 						}
1174 						MINIMIZE_ATTR_MASK(ar);
1175 						ae = ar;
1176 						ptr = lastentry_ptr;
1177 						goto reencode_attrs;
1178 					}
1179 					/* encode the LENGTH of owner string */
1180 					IXDR_PUT_U_INT32(ptr,
1181 							owner.utf8string_len);
1182 					/* encode the RNDUP FILL first */
1183 					rndup = RNDUP(owner.utf8string_len) /
1184 						BYTES_PER_XDR_UNIT;
1185 					ptr[rndup - 1] = 0;
1186 					/* encode the OWNER */
1187 					bcopy(owner.utf8string_val, ptr,
1188 						owner.utf8string_len);
1189 					ptr += rndup;
1190 				}
1191 			}
1192 			/*
1193 			 * Redzone check is done before the encoding of the
1194 			 * group string since the length is indeterminate.
1195 			 */
1196 			if (ae & FATTR4_OWNER_GROUP_MASK) {
1197 				if (!lg_set) {
1198 				    group_error =
1199 					    nfs_idmap_gid_str(va.va_gid,
1200 							&group, TRUE);
1201 				    if (!group_error) {
1202 					    lg_set = TRUE;
1203 					    lastgid = va.va_gid;
1204 				    }
1205 				} else {
1206 				    if (va.va_gid != lastgid) {
1207 					if (group.utf8string_len != 0) {
1208 					    kmem_free(group.utf8string_val,
1209 						group.utf8string_len);
1210 					    group.utf8string_len = 0;
1211 					    group.utf8string_val = NULL;
1212 					}
1213 					group_error =
1214 						nfs_idmap_gid_str(va.va_gid,
1215 								&group, TRUE);
1216 					if (!group_error)
1217 						lastgid = va.va_gid;
1218 					else
1219 						lg_set = FALSE;
1220 				    }
1221 				}
1222 				if (!group_error) {
1223 					if ((ptr +
1224 					    (group.utf8string_len /
1225 					    BYTES_PER_XDR_UNIT)
1226 					    + 2) > ptr_redzone) {
1227 						if (nents ||
1228 						    IS_MIN_ATTR_MASK(ar)) {
1229 							no_space = TRUE;
1230 							continue;
1231 						}
1232 						MINIMIZE_ATTR_MASK(ar);
1233 						ae = ar;
1234 						ptr = lastentry_ptr;
1235 						goto reencode_attrs;
1236 					}
1237 					/* encode the LENGTH of owner string */
1238 					IXDR_PUT_U_INT32(ptr,
1239 							group.utf8string_len);
1240 					/* encode the RNDUP FILL first */
1241 					rndup = RNDUP(group.utf8string_len) /
1242 						BYTES_PER_XDR_UNIT;
1243 					ptr[rndup - 1] = 0;
1244 					/* encode the OWNER */
1245 					bcopy(group.utf8string_val, ptr,
1246 						group.utf8string_len);
1247 					ptr += rndup;
1248 				}
1249 			}
1250 			if (ae &
1251 			    (FATTR4_QUOTA_AVAIL_HARD_MASK |
1252 			    FATTR4_QUOTA_AVAIL_SOFT_MASK |
1253 			    FATTR4_QUOTA_USED_MASK)) {
1254 				if (ae & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1255 					ASSERT(0);
1256 				}
1257 				if (ae & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1258 					ASSERT(0);
1259 				}
1260 				if (ae & FATTR4_QUOTA_USED_MASK) {
1261 					ASSERT(0);
1262 				}
1263 			}
1264 			/*
1265 			 * Redzone check is done at the end of this section.
1266 			 * This particular section will encode a maximum of
1267 			 * 10 * BYTES_PER_XDR_UNIT of data.
1268 			 */
1269 			if (ae &
1270 			    (FATTR4_RAWDEV_MASK |
1271 			    FATTR4_SPACE_AVAIL_MASK |
1272 			    FATTR4_SPACE_FREE_MASK |
1273 			    FATTR4_SPACE_TOTAL_MASK |
1274 			    FATTR4_SPACE_USED_MASK |
1275 			    FATTR4_SYSTEM_MASK)) {
1276 
1277 				if (ae & FATTR4_RAWDEV_MASK) {
1278 					fattr4_rawdev rd;
1279 					rd.specdata1 =
1280 						(uint32)getmajor(va.va_rdev);
1281 					rd.specdata2 =
1282 						(uint32)getminor(va.va_rdev);
1283 					IXDR_PUT_U_INT32(ptr, rd.specdata1);
1284 					IXDR_PUT_U_INT32(ptr, rd.specdata2);
1285 				}
1286 				if (ae & FATTR4_SPACE_AVAIL_MASK) {
1287 					IXDR_PUT_HYPER(ptr, sbe.space_avail);
1288 				}
1289 				if (ae & FATTR4_SPACE_FREE_MASK) {
1290 					IXDR_PUT_HYPER(ptr, sbe.space_free);
1291 				}
1292 				if (ae & FATTR4_SPACE_TOTAL_MASK) {
1293 					IXDR_PUT_HYPER(ptr, sbe.space_total);
1294 				}
1295 				if (ae & FATTR4_SPACE_USED_MASK) {
1296 					u_longlong_t su;
1297 					su = (fattr4_space_used) DEV_BSIZE *
1298 					    (fattr4_space_used) va.va_nblocks;
1299 					IXDR_PUT_HYPER(ptr, su);
1300 				}
1301 				if (ae & FATTR4_SYSTEM_MASK) {
1302 					ASSERT(0);
1303 				}
1304 				/* Check the redzone boundary */
1305 				if (ptr > ptr_redzone) {
1306 					if (nents || IS_MIN_ATTR_MASK(ar)) {
1307 						no_space = TRUE;
1308 						continue;
1309 					}
1310 					MINIMIZE_ATTR_MASK(ar);
1311 					ae = ar;
1312 					ptr = lastentry_ptr;
1313 					goto reencode_attrs;
1314 				}
1315 			}
1316 			/*
1317 			 * Redzone check is done at the end of this section.
1318 			 * This particular section will encode a maximum of
1319 			 * 14 * BYTES_PER_XDR_UNIT of data.
1320 			 */
1321 			if (ae &
1322 			    (FATTR4_TIME_ACCESS_MASK |
1323 			    FATTR4_TIME_ACCESS_SET_MASK |
1324 			    FATTR4_TIME_BACKUP_MASK |
1325 			    FATTR4_TIME_CREATE_MASK |
1326 			    FATTR4_TIME_DELTA_MASK |
1327 			    FATTR4_TIME_METADATA_MASK |
1328 			    FATTR4_TIME_MODIFY_MASK |
1329 			    FATTR4_TIME_MODIFY_SET_MASK |
1330 			    FATTR4_MOUNTED_ON_FILEID_MASK)) {
1331 
1332 				if (ae & FATTR4_TIME_ACCESS_MASK) {
1333 					u_longlong_t sec =
1334 					    (u_longlong_t)va.va_atime.tv_sec;
1335 					uint_t nsec =
1336 						(uint_t)va.va_atime.tv_nsec;
1337 					IXDR_PUT_HYPER(ptr, sec);
1338 					IXDR_PUT_INT32(ptr, nsec);
1339 				}
1340 				if (ae & FATTR4_TIME_ACCESS_SET_MASK) {
1341 					ASSERT(0);
1342 				}
1343 				if (ae & FATTR4_TIME_BACKUP_MASK) {
1344 					ASSERT(0);
1345 				}
1346 				if (ae & FATTR4_TIME_CREATE_MASK) {
1347 					ASSERT(0);
1348 				}
1349 				if (ae & FATTR4_TIME_DELTA_MASK) {
1350 					u_longlong_t sec = 0;
1351 					uint_t nsec = 1000;
1352 					IXDR_PUT_HYPER(ptr, sec);
1353 					IXDR_PUT_INT32(ptr, nsec);
1354 				}
1355 				if (ae & FATTR4_TIME_METADATA_MASK) {
1356 					u_longlong_t sec =
1357 					    (u_longlong_t)va.va_ctime.tv_sec;
1358 					uint_t nsec =
1359 						(uint_t)va.va_ctime.tv_nsec;
1360 					IXDR_PUT_HYPER(ptr, sec);
1361 					IXDR_PUT_INT32(ptr, nsec);
1362 				}
1363 				if (ae & FATTR4_TIME_MODIFY_MASK) {
1364 					u_longlong_t sec =
1365 					    (u_longlong_t)va.va_mtime.tv_sec;
1366 					uint_t nsec =
1367 						(uint_t)va.va_mtime.tv_nsec;
1368 					IXDR_PUT_HYPER(ptr, sec);
1369 					IXDR_PUT_INT32(ptr, nsec);
1370 				}
1371 				if (ae & FATTR4_TIME_MODIFY_SET_MASK) {
1372 					ASSERT(0);
1373 				}
1374 				if (ae & FATTR4_MOUNTED_ON_FILEID_MASK) {
1375 					IXDR_PUT_HYPER(ptr, dp->d_ino);
1376 				}
1377 				/* Check the redzone boundary */
1378 				if (ptr > ptr_redzone) {
1379 					if (nents || IS_MIN_ATTR_MASK(ar)) {
1380 						no_space = TRUE;
1381 						continue;
1382 					}
1383 					MINIMIZE_ATTR_MASK(ar);
1384 					ae = ar;
1385 					ptr = lastentry_ptr;
1386 					goto reencode_attrs;
1387 				}
1388 			}
1389 		}
1390 
1391 		/* Reset to directory's vfs info when encoding complete */
1392 		if (vfs_different) {
1393 			dsbe = sbe;
1394 			dpce = pce;
1395 			vfs_different = 0;
1396 		}
1397 
1398 		/* "go back" and encode the attributes' length */
1399 		attr_length =
1400 			(char *)ptr -
1401 			(char *)attr_offset_ptr -
1402 			BYTES_PER_XDR_UNIT;
1403 		IXDR_PUT_U_INT32(attr_offset_ptr, attr_length);
1404 
1405 		/*
1406 		 * If there was trouble obtaining a mapping for either
1407 		 * the owner or group attributes, then remove them from
1408 		 * bitmap4 for this entry and reset the bitmap value
1409 		 * in the data stream.
1410 		 */
1411 		if (owner_error || group_error) {
1412 			if (owner_error)
1413 				ae &= ~FATTR4_OWNER_MASK;
1414 			if (group_error)
1415 				ae &= ~FATTR4_OWNER_GROUP_MASK;
1416 			IXDR_PUT_HYPER(attrmask_ptr, ae);
1417 		}
1418 
1419 		/* END OF ATTRIBUTE ENCODING */
1420 
1421 		lastentry_ptr = ptr;
1422 		nents++;
1423 		rddir_next_offset = dp->d_off;
1424 	}
1425 
1426 	/*
1427 	 * Check for the case that another VOP_READDIR() has to be done.
1428 	 * - no space encoding error
1429 	 * - no entry successfully encoded
1430 	 * - still more directory to read
1431 	 */
1432 	if (!no_space && nents == 0 && !iseofdir)
1433 		goto readagain;
1434 
1435 	*cs->statusp = resp->status = NFS4_OK;
1436 
1437 	/*
1438 	 * If no_space is set then we terminated prematurely,
1439 	 * rewind to the last entry and this can never be EOF.
1440 	 */
1441 	if (no_space) {
1442 		ptr = lastentry_ptr;
1443 		eof = FALSE; /* ended encoded prematurely */
1444 	} else {
1445 		eof = (iseofdir ? TRUE : FALSE);
1446 	}
1447 
1448 	/*
1449 	 * If we have entries, always return them, otherwise only error
1450 	 * if we ran out of space.
1451 	 */
1452 	if (nents || !no_space) {
1453 		ASSERT(ptr != NULL);
1454 		/* encode the BOOLEAN marking no further entries */
1455 		IXDR_PUT_U_INT32(ptr, false);
1456 		/* encode the BOOLEAN signifying end of directory */
1457 		IXDR_PUT_U_INT32(ptr, eof);
1458 
1459 		resp->data_len = (char *)ptr - (char *)beginning_ptr;
1460 		resp->mblk->b_wptr += resp->data_len;
1461 	} else {
1462 		freeb(mp);
1463 		resp->mblk = NULL;
1464 		resp->data_len = 0;
1465 		*cs->statusp = resp->status = NFS4ERR_TOOSMALL;
1466 	}
1467 
1468 	kmem_free((caddr_t)rddir_data, rddir_data_len);
1469 	if (vp)
1470 		VN_RELE(vp);
1471 	if (owner.utf8string_len != 0)
1472 		kmem_free(owner.utf8string_val,	owner.utf8string_len);
1473 	if (group.utf8string_len != 0)
1474 		kmem_free(group.utf8string_val, group.utf8string_len);
1475 }
1476