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