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