Home | History | Annotate | Download | only in nfs
      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