xref: /titanic_41/usr/src/uts/common/fs/nfs/nfs4_xdr.c (revision 0dc2366f7b9f9f36e10909b1e95edbf2a261c2ac)
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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * A handcoded version based on the original rpcgen code.
28  *
29  * Note: All future NFS4 protocol changes should be added by hand
30  * to this file.
31  *
32  * CAUTION: All protocol changes must also be propagated to:
33  *     usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
34  */
35 
36 #include <sys/types.h>
37 #include <sys/sunddi.h>
38 #include <sys/dnlc.h>
39 #include <nfs/nfs.h>
40 #include <nfs/nfs4_kprot.h>
41 #include <nfs/rnode4.h>
42 #include <nfs/nfs4.h>
43 #include <nfs/nfs4_clnt.h>
44 #include <sys/sdt.h>
45 #include <sys/mkdev.h>
46 #include <rpc/rpc_rdma.h>
47 #include <rpc/xdr.h>
48 
49 #define	xdr_dev_t xdr_u_int
50 
51 extern bool_t xdr_netbuf(XDR *, struct netbuf *);
52 extern bool_t xdr_vector(XDR *, char *, const uint_t, const uint_t,
53 	const xdrproc_t);
54 bool_t xdr_knetconfig(XDR *, struct knetconfig *);
55 
56 bool_t
57 xdr_bitmap4(XDR *xdrs, bitmap4 *objp)
58 {
59 	int32_t len, size;
60 
61 	if (xdrs->x_op == XDR_FREE)
62 		return (TRUE);
63 
64 	/*
65 	 * Simplified bitmap4 processing, always encode from uint64_t
66 	 * to 2 uint32_t's, always decode first 2 uint32_t's into a
67 	 * uint64_t and ignore all of the rest.
68 	 */
69 	if (xdrs->x_op == XDR_ENCODE) {
70 		len = 2;
71 
72 		if (!XDR_PUTINT32(xdrs, &len))
73 			return (FALSE);
74 
75 #if defined(_LITTLE_ENDIAN)
76 		if (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
77 		    BYTES_PER_XDR_UNIT)) == TRUE) {
78 			return (XDR_PUTINT32(xdrs, (int32_t *)objp));
79 		}
80 #elif defined(_BIG_ENDIAN)
81 		if (XDR_PUTINT32(xdrs, (int32_t *)objp) == TRUE) {
82 			return (XDR_PUTINT32(xdrs, (int32_t *)((char *)objp +
83 			    BYTES_PER_XDR_UNIT)));
84 		}
85 #endif
86 		return (FALSE);
87 	}
88 
89 	if (!XDR_GETINT32(xdrs, &len))
90 		return (FALSE);
91 
92 	/*
93 	 * Common fast DECODE cases
94 	 */
95 	if (len == 2) {
96 #if defined(_LITTLE_ENDIAN)
97 		if (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
98 		    BYTES_PER_XDR_UNIT)) == TRUE) {
99 			return (XDR_GETINT32(xdrs, (int32_t *)objp));
100 		}
101 #elif defined(_BIG_ENDIAN)
102 		if (XDR_GETINT32(xdrs, (int32_t *)objp) == TRUE) {
103 			return (XDR_GETINT32(xdrs, (int32_t *)((char *)objp +
104 			    BYTES_PER_XDR_UNIT)));
105 		}
106 #endif
107 		return (FALSE);
108 	}
109 
110 	*objp = 0;
111 	if (len == 0)
112 		return (TRUE);
113 
114 	/*
115 	 * The not so common DECODE cases, len == 1 || len > 2
116 	 */
117 #if defined(_LITTLE_ENDIAN)
118 	if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
119 		return (FALSE);
120 	if (--len == 0)
121 		return (TRUE);
122 	if (!XDR_GETINT32(xdrs, (int32_t *)objp))
123 		return (FALSE);
124 #elif defined(_BIG_ENDIAN)
125 	if (!XDR_GETINT32(xdrs, (int32_t *)objp))
126 		return (FALSE);
127 	if (--len == 0)
128 		return (TRUE);
129 	if (!XDR_GETINT32(xdrs, (int32_t *)((char *)objp + BYTES_PER_XDR_UNIT)))
130 		return (FALSE);
131 #else
132 	return (FALSE);
133 #endif
134 
135 	if (--len == 0)
136 		return (TRUE);
137 
138 	size = len * BYTES_PER_XDR_UNIT;
139 	return (XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size));
140 }
141 
142 /* Called by xdr_array, nfsid_map_xdr */
143 bool_t
144 xdr_utf8string(XDR *xdrs, utf8string *objp)
145 {
146 	if (xdrs->x_op != XDR_FREE)
147 		return (xdr_bytes(xdrs, (char **)&objp->utf8string_val,
148 		    (uint_t *)&objp->utf8string_len, NFS4_MAX_UTF8STRING));
149 
150 	if (objp->utf8string_val != NULL) {
151 		kmem_free(objp->utf8string_val, objp->utf8string_len);
152 		objp->utf8string_val = NULL;
153 	}
154 	return (TRUE);
155 }
156 
157 /*
158  * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
159  */
160 bool_t
161 xdr_nfs_fsl_info(XDR *xdrs, struct nfs_fsl_info *objp)
162 {
163 
164 	if (!xdr_u_int(xdrs, &objp->netbuf_len))
165 		return (FALSE);
166 	if (!xdr_u_int(xdrs, &objp->netnm_len))
167 		return (FALSE);
168 	if (!xdr_u_int(xdrs, &objp->knconf_len))
169 		return (FALSE);
170 
171 #if defined(_LP64)
172 	/*
173 	 * The object can come from a 32-bit binary; nfsmapid.
174 	 * To be safe we double the size of the knetconfig to
175 	 * allow some buffering for decoding.
176 	 */
177 	if (xdrs->x_op == XDR_DECODE)
178 		objp->knconf_len += sizeof (struct knetconfig);
179 #endif
180 
181 	if (!xdr_string(xdrs, &objp->netname, ~0))
182 		return (FALSE);
183 	if (!xdr_pointer(xdrs, (char **)&objp->addr, objp->netbuf_len,
184 	    (xdrproc_t)xdr_netbuf))
185 		return (FALSE);
186 	if (!xdr_pointer(xdrs, (char **)&objp->knconf,
187 	    objp->knconf_len, (xdrproc_t)xdr_knetconfig))
188 		return (FALSE);
189 	return (TRUE);
190 }
191 
192 bool_t
193 xdr_knetconfig(XDR *xdrs, struct knetconfig *objp)
194 {
195 	rpc_inline_t *buf;
196 	u_longlong_t dev64;
197 #if !defined(_LP64)
198 	uint32_t major, minor;
199 #endif
200 	int i;
201 
202 	if (!xdr_u_int(xdrs, &objp->knc_semantics))
203 		return (FALSE);
204 	if (xdrs->x_op == XDR_DECODE) {
205 		objp->knc_protofmly = (((char *)objp) +
206 		    sizeof (struct knetconfig));
207 		objp->knc_proto = objp->knc_protofmly + KNC_STRSIZE;
208 	}
209 	if (!xdr_opaque(xdrs, objp->knc_protofmly, KNC_STRSIZE))
210 		return (FALSE);
211 	if (!xdr_opaque(xdrs, objp->knc_proto, KNC_STRSIZE))
212 		return (FALSE);
213 
214 	/*
215 	 * For interoperability between 32-bit daemon and 64-bit kernel,
216 	 * we always treat dev_t as 64-bit number and do the expanding
217 	 * or compression of dev_t as needed.
218 	 * We have to hand craft the conversion since there is no available
219 	 * function in ddi.c. Besides ddi.c is available only in the kernel
220 	 * and we want to keep both user and kernel of xdr_knetconfig() the
221 	 * same for consistency.
222 	 */
223 	if (xdrs->x_op == XDR_ENCODE) {
224 #if defined(_LP64)
225 		dev64 = objp->knc_rdev;
226 #else
227 		major = (objp->knc_rdev >> NBITSMINOR32) & MAXMAJ32;
228 		minor = objp->knc_rdev & MAXMIN32;
229 		dev64 = (((unsigned long long)major) << NBITSMINOR64) | minor;
230 #endif
231 		if (!xdr_u_longlong_t(xdrs, &dev64))
232 			return (FALSE);
233 	}
234 	if (xdrs->x_op == XDR_DECODE) {
235 #if defined(_LP64)
236 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->knc_rdev))
237 			return (FALSE);
238 #else
239 		if (!xdr_u_longlong_t(xdrs, &dev64))
240 			return (FALSE);
241 
242 		major = (dev64 >> NBITSMINOR64) & L_MAXMAJ32;
243 		minor = dev64 & L_MAXMIN32;
244 		objp->knc_rdev = (major << L_BITSMINOR32) | minor;
245 #endif
246 	}
247 
248 	if (xdrs->x_op == XDR_ENCODE) {
249 		buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
250 		if (buf == NULL) {
251 			if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
252 			    sizeof (uint_t), (xdrproc_t)xdr_u_int))
253 				return (FALSE);
254 		} else {
255 			uint_t *genp;
256 
257 			for (i = 0, genp = objp->knc_unused;
258 			    i < 8; i++) {
259 #if defined(_LP64) || defined(_KERNEL)
260 				IXDR_PUT_U_INT32(buf, *genp++);
261 #else
262 				IXDR_PUT_U_LONG(buf, *genp++);
263 #endif
264 			}
265 		}
266 		return (TRUE);
267 	} else if (xdrs->x_op == XDR_DECODE) {
268 		buf = XDR_INLINE(xdrs, (8) * BYTES_PER_XDR_UNIT);
269 		if (buf == NULL) {
270 			if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
271 			    sizeof (uint_t), (xdrproc_t)xdr_u_int))
272 				return (FALSE);
273 		} else {
274 			uint_t *genp;
275 
276 			for (i = 0, genp = objp->knc_unused;
277 			    i < 8; i++) {
278 #if defined(_LP64) || defined(_KERNEL)
279 					*genp++ = IXDR_GET_U_INT32(buf);
280 #else
281 					*genp++ = IXDR_GET_U_LONG(buf);
282 #endif
283 			}
284 		}
285 		return (TRUE);
286 	}
287 
288 	if (!xdr_vector(xdrs, (char *)objp->knc_unused, 8,
289 	    sizeof (uint_t), (xdrproc_t)xdr_u_int))
290 		return (FALSE);
291 	return (TRUE);
292 }
293 
294 /*
295  * XDR_INLINE decode a filehandle.
296  */
297 bool_t
298 xdr_inline_decode_nfs_fh4(uint32_t *ptr, nfs_fh4_fmt_t *fhp, uint32_t fhsize)
299 {
300 	uchar_t *bp = (uchar_t *)ptr;
301 	uchar_t *cp;
302 	uint32_t dsize;
303 	uintptr_t resid;
304 
305 	/*
306 	 * Check to see if what the client sent us is bigger or smaller
307 	 * than what we can ever possibly send out. NFS_FHMAXDATA is
308 	 * unfortunately badly named as it is no longer the max and is
309 	 * really the min of what is sent over the wire.
310 	 */
311 	if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
312 	    sizeof (ushort_t) + NFS_FHMAXDATA +
313 	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
314 		return (FALSE);
315 	}
316 
317 	/*
318 	 * All internal parts of a filehandle are in native byte order.
319 	 *
320 	 * Decode what should be fh4_fsid, it is aligned.
321 	 */
322 	fhp->fh4_fsid.val[0] = *(uint32_t *)bp;
323 	bp += BYTES_PER_XDR_UNIT;
324 	fhp->fh4_fsid.val[1] = *(uint32_t *)bp;
325 	bp += BYTES_PER_XDR_UNIT;
326 
327 	/*
328 	 * Decode what should be fh4_len.  fh4_len is two bytes, so we're
329 	 * unaligned now.
330 	 */
331 	cp = (uchar_t *)&fhp->fh4_len;
332 	*cp++ = *bp++;
333 	*cp++ = *bp++;
334 	fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
335 
336 	/*
337 	 * For backwards compatibility, the fid length may be less than
338 	 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
339 	 */
340 	dsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
341 
342 	/*
343 	 * Make sure the client isn't sending us a bogus length for fh4_data.
344 	 */
345 	if (fhsize < dsize)
346 		return (FALSE);
347 	bcopy(bp, fhp->fh4_data, dsize);
348 	bp += dsize;
349 	fhsize -= dsize;
350 
351 	if (fhsize < sizeof (ushort_t))
352 		return (FALSE);
353 	cp = (uchar_t *)&fhp->fh4_xlen;
354 	*cp++ = *bp++;
355 	*cp++ = *bp++;
356 	fhsize -= sizeof (ushort_t);
357 
358 	dsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
359 
360 	/*
361 	 * Make sure the client isn't sending us a bogus length for fh4_xdata.
362 	 */
363 	if (fhsize < dsize)
364 		return (FALSE);
365 	bcopy(bp, fhp->fh4_xdata, dsize);
366 	fhsize -= dsize;
367 	bp += dsize;
368 
369 	/*
370 	 * We realign things on purpose, so skip any padding
371 	 */
372 	resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
373 	if (resid != 0) {
374 		if (fhsize < (BYTES_PER_XDR_UNIT - resid))
375 			return (FALSE);
376 		bp += BYTES_PER_XDR_UNIT - resid;
377 		fhsize -= BYTES_PER_XDR_UNIT - resid;
378 	}
379 
380 	if (fhsize < BYTES_PER_XDR_UNIT)
381 		return (FALSE);
382 	fhp->fh4_flag = *(uint32_t *)bp;
383 	bp += BYTES_PER_XDR_UNIT;
384 	fhsize -= BYTES_PER_XDR_UNIT;
385 
386 #ifdef VOLATILE_FH_TEST
387 	if (fhsize < BYTES_PER_XDR_UNIT)
388 		return (FALSE);
389 	fhp->fh4_volatile_id = *(uint32_t *)bp;
390 	bp += BYTES_PER_XDR_UNIT;
391 	fhsize -= BYTES_PER_XDR_UNIT;
392 #endif
393 	/*
394 	 * Make sure client didn't send extra bytes
395 	 */
396 	if (fhsize != 0)
397 		return (FALSE);
398 	return (TRUE);
399 }
400 
401 static bool_t
402 xdr_decode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
403 {
404 	uint32_t fhsize;		/* filehandle size */
405 	uint32_t bufsize;
406 	rpc_inline_t *ptr;
407 	uchar_t *bp;
408 
409 	ASSERT(xdrs->x_op == XDR_DECODE);
410 
411 	/*
412 	 * Retrieve the filehandle length.
413 	 */
414 	if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
415 		return (FALSE);
416 
417 	objp->nfs_fh4_val = NULL;
418 	objp->nfs_fh4_len = 0;
419 
420 	/*
421 	 * Check to see if what the client sent us is bigger or smaller
422 	 * than what we can ever possibly send out. NFS_FHMAXDATA is
423 	 * unfortunately badly named as it is no longer the max and is
424 	 * really the min of what is sent over the wire.
425 	 */
426 	if (fhsize > sizeof (nfs_fh4_fmt_t) || fhsize < (sizeof (fsid_t) +
427 	    sizeof (ushort_t) + NFS_FHMAXDATA +
428 	    sizeof (ushort_t) + NFS_FHMAXDATA)) {
429 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
430 			return (FALSE);
431 		return (TRUE);
432 	}
433 
434 	/*
435 	 * bring in fhsize plus any padding
436 	 */
437 	bufsize = RNDUP(fhsize);
438 	ptr = XDR_INLINE(xdrs, bufsize);
439 	bp = (uchar_t *)ptr;
440 	if (ptr == NULL) {
441 		bp = kmem_alloc(bufsize, KM_SLEEP);
442 		if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
443 			kmem_free(bp, bufsize);
444 			return (FALSE);
445 		}
446 	}
447 
448 	objp->nfs_fh4_val = kmem_zalloc(sizeof (nfs_fh4_fmt_t), KM_SLEEP);
449 	objp->nfs_fh4_len = sizeof (nfs_fh4_fmt_t);
450 
451 	if (xdr_inline_decode_nfs_fh4((uint32_t *)bp,
452 	    (nfs_fh4_fmt_t *)objp->nfs_fh4_val, fhsize) == FALSE) {
453 		/*
454 		 * If in the process of decoding we find the file handle
455 		 * is not correctly formed, we need to continue decoding
456 		 * and trigger an NFS layer error. Set the nfs_fh4_len to
457 		 * zero so it gets caught as a bad length.
458 		 */
459 		kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
460 		objp->nfs_fh4_val = NULL;
461 		objp->nfs_fh4_len = 0;
462 	}
463 
464 	if (ptr == NULL)
465 		kmem_free(bp, bufsize);
466 	return (TRUE);
467 }
468 
469 /*
470  * XDR_INLINE encode a filehandle.
471  */
472 bool_t
473 xdr_inline_encode_nfs_fh4(uint32_t **ptrp, uint32_t *ptr_redzone,
474 	nfs_fh4_fmt_t *fhp)
475 {
476 	uint32_t *ptr = *ptrp;
477 	uchar_t *cp;
478 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
479 	uint32_t padword;
480 
481 	fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
482 	xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
483 
484 	/*
485 	 * First get the initial and variable sized part of the filehandle.
486 	 */
487 	otw_len = sizeof (fhp->fh4_fsid) +
488 	    sizeof (fhp->fh4_len) + fsize +
489 	    sizeof (fhp->fh4_xlen) + xsize;
490 
491 	/*
492 	 * Round out to a full word.
493 	 */
494 	otw_len = RNDUP(otw_len);
495 	padword = (otw_len / BYTES_PER_XDR_UNIT);	/* includes fhlen */
496 
497 	/*
498 	 * Add in the fixed sized pieces.
499 	 */
500 	otw_len += sizeof (fhp->fh4_flag);
501 #ifdef VOLATILE_FH_TEST
502 	otw_len += sizeof (fhp->fh4_volatile_id);
503 #endif
504 
505 	/*
506 	 * Make sure we don't exceed our buffer.
507 	 */
508 	if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
509 		return (FALSE);
510 
511 	/*
512 	 * Zero out the padding.
513 	 */
514 	ptr[padword] = 0;
515 
516 	IXDR_PUT_U_INT32(ptr, otw_len);
517 
518 	/*
519 	 * The rest of the filehandle is in native byteorder
520 	 */
521 	/* fh4_fsid */
522 	*ptr++ = (uint32_t)fhp->fh4_fsid.val[0];
523 	*ptr++ = (uint32_t)fhp->fh4_fsid.val[1];
524 
525 	/*
526 	 * Since the next pieces are unaligned, we need to
527 	 * do bytewise copies.
528 	 */
529 	cp = (uchar_t *)ptr;
530 
531 	/* fh4_len + fh4_data */
532 	bcopy(&fhp->fh4_len, cp, sizeof (fhp->fh4_len) + fsize);
533 	cp += sizeof (fhp->fh4_len) + fsize;
534 
535 	/* fh4_xlen + fh4_xdata */
536 	bcopy(&fhp->fh4_xlen, cp, sizeof (fhp->fh4_xlen) + xsize);
537 	cp += sizeof (fhp->fh4_xlen) + xsize;
538 
539 	/* do necessary rounding/padding */
540 	cp = (uchar_t *)RNDUP((uintptr_t)cp);
541 	ptr = (uint32_t *)cp;
542 
543 	/*
544 	 * With the above padding, we're word aligned again.
545 	 */
546 	ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
547 
548 	/* fh4_flag */
549 	*ptr++ = (uint32_t)fhp->fh4_flag;
550 
551 #ifdef VOLATILE_FH_TEST
552 	/* fh4_volatile_id */
553 	*ptr++ = (uint32_t)fhp->fh4_volatile_id;
554 #endif
555 	*ptrp = ptr;
556 
557 	return (TRUE);
558 }
559 
560 static bool_t
561 xdr_encode_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
562 {
563 	uint_t otw_len, fsize, xsize;   /* otw, file, and export sizes */
564 	bool_t ret;
565 	rpc_inline_t *ptr;
566 	rpc_inline_t *buf = NULL;
567 	uint32_t *ptr_redzone;
568 	nfs_fh4_fmt_t *fhp;
569 
570 	ASSERT(xdrs->x_op == XDR_ENCODE);
571 
572 	fhp = (nfs_fh4_fmt_t *)objp->nfs_fh4_val;
573 	fsize = fhp->fh4_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_len;
574 	xsize = fhp->fh4_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh4_xlen;
575 
576 	/*
577 	 * First get the over the wire size, it is the 4 bytes
578 	 * for the length, plus the combined size of the
579 	 * file handle components.
580 	 */
581 	otw_len = BYTES_PER_XDR_UNIT + sizeof (fhp->fh4_fsid) +
582 	    sizeof (fhp->fh4_len) + fsize +
583 	    sizeof (fhp->fh4_xlen) + xsize +
584 	    sizeof (fhp->fh4_flag);
585 #ifdef VOLATILE_FH_TEST
586 	otw_len += sizeof (fhp->fh4_volatile_id);
587 #endif
588 	/*
589 	 * Round out to a full word.
590 	 */
591 	otw_len = RNDUP(otw_len);
592 
593 	/*
594 	 * Next try to inline the XDR stream, if that fails (rare)
595 	 * allocate a buffer to encode the file handle and then
596 	 * copy it using xdr_opaque and free the buffer.
597 	 */
598 	ptr = XDR_INLINE(xdrs, otw_len);
599 	if (ptr == NULL)
600 		ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
601 
602 	ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
603 	ret = xdr_inline_encode_nfs_fh4((uint32_t **)&ptr, ptr_redzone, fhp);
604 
605 	if (buf != NULL) {
606 		if (ret == TRUE)
607 			ret = xdr_opaque(xdrs, (char *)buf, otw_len);
608 		kmem_free(buf, otw_len);
609 	}
610 	return (ret);
611 }
612 
613 /*
614  * XDR a NFSv4 filehandle.
615  * Encoding interprets the contents (server).
616  * Decoding the contents are opaque (client).
617  */
618 bool_t
619 xdr_nfs_fh4(XDR *xdrs, nfs_fh4 *objp)
620 {
621 	switch (xdrs->x_op) {
622 	case XDR_ENCODE:
623 		return (xdr_encode_nfs_fh4(xdrs, objp));
624 	case XDR_DECODE:
625 		return (xdr_bytes(xdrs, (char **)&objp->nfs_fh4_val,
626 		    (uint_t *)&objp->nfs_fh4_len, NFS4_FHSIZE));
627 	case XDR_FREE:
628 		if (objp->nfs_fh4_val != NULL) {
629 			kmem_free(objp->nfs_fh4_val, objp->nfs_fh4_len);
630 			objp->nfs_fh4_val = NULL;
631 		}
632 		return (TRUE);
633 	}
634 	return (FALSE);
635 }
636 
637 /* Called by xdr_array */
638 static bool_t
639 xdr_fs_location4(XDR *xdrs, fs_location4 *objp)
640 {
641 	if (xdrs->x_op == XDR_DECODE) {
642 		objp->server_val = NULL;
643 		objp->rootpath.pathname4_val = NULL;
644 	}
645 	if (!xdr_array(xdrs, (char **)&objp->server_val,
646 	    (uint_t *)&objp->server_len, NFS4_MAX_UTF8STRING,
647 	    sizeof (utf8string), (xdrproc_t)xdr_utf8string))
648 		return (FALSE);
649 	return (xdr_array(xdrs, (char **)&objp->rootpath.pathname4_val,
650 	    (uint_t *)&objp->rootpath.pathname4_len,
651 	    NFS4_MAX_PATHNAME4,
652 	    sizeof (utf8string), (xdrproc_t)xdr_utf8string));
653 }
654 
655 /* Called by xdr_array */
656 static bool_t
657 xdr_nfsace4(XDR *xdrs, nfsace4 *objp)
658 {
659 	if (xdrs->x_op != XDR_FREE) {
660 		if (!xdr_u_int(xdrs, &objp->type))
661 			return (FALSE);
662 		if (!xdr_u_int(xdrs, &objp->flag))
663 			return (FALSE);
664 		if (!xdr_u_int(xdrs, &objp->access_mask))
665 			return (FALSE);
666 
667 		if (xdrs->x_op == XDR_DECODE) {
668 			objp->who.utf8string_val = NULL;
669 			objp->who.utf8string_len = 0;
670 		}
671 
672 		return (xdr_bytes(xdrs, (char **)&objp->who.utf8string_val,
673 		    (uint_t *)&objp->who.utf8string_len,
674 		    NFS4_MAX_UTF8STRING));
675 	}
676 
677 	/*
678 	 * Optimized free case
679 	 */
680 	if (objp->who.utf8string_val != NULL) {
681 		kmem_free(objp->who.utf8string_val, objp->who.utf8string_len);
682 		objp->who.utf8string_val = NULL;
683 	}
684 	return (TRUE);
685 }
686 
687 /*
688  * These functions are called out of nfs4_attr.c
689  */
690 bool_t
691 xdr_fattr4_fsid(XDR *xdrs, fattr4_fsid *objp)
692 {
693 	if (xdrs->x_op == XDR_FREE)
694 		return (TRUE);
695 
696 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->major))
697 		return (FALSE);
698 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->minor));
699 }
700 
701 
702 bool_t
703 xdr_fattr4_acl(XDR *xdrs, fattr4_acl *objp)
704 {
705 	return (xdr_array(xdrs, (char **)&objp->fattr4_acl_val,
706 	    (uint_t *)&objp->fattr4_acl_len, NFS4_ACL_LIMIT,
707 	    sizeof (nfsace4), (xdrproc_t)xdr_nfsace4));
708 }
709 
710 bool_t
711 xdr_fattr4_fs_locations(XDR *xdrs, fattr4_fs_locations *objp)
712 {
713 	if (xdrs->x_op == XDR_DECODE) {
714 		objp->fs_root.pathname4_len = 0;
715 		objp->fs_root.pathname4_val = NULL;
716 		objp->locations_val = NULL;
717 	}
718 	if (!xdr_array(xdrs, (char **)&objp->fs_root.pathname4_val,
719 	    (uint_t *)&objp->fs_root.pathname4_len,
720 	    NFS4_MAX_PATHNAME4,
721 	    sizeof (utf8string), (xdrproc_t)xdr_utf8string))
722 		return (FALSE);
723 	return (xdr_array(xdrs, (char **)&objp->locations_val,
724 	    (uint_t *)&objp->locations_len, NFS4_FS_LOCATIONS_LIMIT,
725 	    sizeof (fs_location4), (xdrproc_t)xdr_fs_location4));
726 }
727 
728 bool_t
729 xdr_fattr4_rawdev(XDR *xdrs, fattr4_rawdev *objp)
730 {
731 	if (xdrs->x_op == XDR_FREE)
732 		return (TRUE);
733 
734 	if (!xdr_u_int(xdrs, &objp->specdata1))
735 		return (FALSE);
736 	return (xdr_u_int(xdrs, &objp->specdata2));
737 }
738 
739 bool_t
740 xdr_nfstime4(XDR *xdrs, nfstime4 *objp)
741 {
742 	if (xdrs->x_op == XDR_FREE)
743 		return (TRUE);
744 
745 	if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->seconds))
746 		return (FALSE);
747 	return (xdr_u_int(xdrs, &objp->nseconds));
748 }
749 
750 
751 /*
752  * structured used for calls into xdr_ga_fattr_res() as a means
753  * to do an immediate/short-term cache of owner/group strings
754  * for callers like the readdir processing.  In the case of readdir,
755  * it is likely that the directory objects will be owned by the same
756  * owner/group and if so there is no need to call into the uid/gid
757  * mapping code.  While the uid/gid interfaces have their own cache
758  * having one here will reduct pathlength further.
759  */
760 #define	MAX_OG_NAME 100
761 typedef struct ug_cache
762 {
763 	uid_t	uid;
764 	gid_t	gid;
765 	utf8string u_curr, u_last;
766 	utf8string g_curr, g_last;
767 	char	u_buf1[MAX_OG_NAME];
768 	char	u_buf2[MAX_OG_NAME];
769 	char	g_buf1[MAX_OG_NAME];
770 	char	g_buf2[MAX_OG_NAME];
771 } ug_cache_t;
772 
773 #define	U_SWAP_CURR_LAST(ug) \
774 	(ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len;	\
775 	if ((ug)->u_last.utf8string_val == (ug)->u_buf1) {		\
776 		(ug)->u_last.utf8string_val = (ug)->u_buf2;		\
777 		(ug)->u_curr.utf8string_val = (ug)->u_buf1;		\
778 	} else {							\
779 		(ug)->u_last.utf8string_val = (ug)->u_buf1;		\
780 		(ug)->u_curr.utf8string_val = (ug)->u_buf2;		\
781 	}
782 
783 #define	G_SWAP_CURR_LAST(ug) \
784 	(ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len;	\
785 	if ((ug)->g_last.utf8string_val == (ug)->g_buf1) {		\
786 		(ug)->g_last.utf8string_val = (ug)->g_buf2;		\
787 		(ug)->g_curr.utf8string_val = (ug)->g_buf1;		\
788 	} else {							\
789 		(ug)->g_last.utf8string_val = (ug)->g_buf1;		\
790 		(ug)->g_curr.utf8string_val = (ug)->g_buf2;		\
791 	}
792 
793 static ug_cache_t *
794 alloc_ugcache()
795 {
796 	ug_cache_t *pug = kmem_alloc(sizeof (ug_cache_t), KM_SLEEP);
797 
798 	pug->uid = pug->gid = 0;
799 	pug->u_curr.utf8string_len = 0;
800 	pug->u_last.utf8string_len = 0;
801 	pug->g_curr.utf8string_len = 0;
802 	pug->g_last.utf8string_len = 0;
803 	pug->u_curr.utf8string_val = pug->u_buf1;
804 	pug->u_last.utf8string_val = pug->u_buf2;
805 	pug->g_curr.utf8string_val = pug->g_buf1;
806 	pug->g_last.utf8string_val = pug->g_buf2;
807 
808 	return (pug);
809 }
810 
811 static void
812 xdr_ga_prefill_vattr(struct nfs4_ga_res *garp, struct mntinfo4 *mi)
813 {
814 	static vattr_t s_vattr = {
815 		AT_ALL,		/* va_mask */
816 		VNON,		/* va_type */
817 		0777,		/* va_mode */
818 		UID_NOBODY,	/* va_uid */
819 		GID_NOBODY,	/* va_gid */
820 		0,		/* va_fsid */
821 		0,		/* va_nodeid */
822 		1,		/* va_nlink */
823 		0,		/* va_size */
824 		{0, 0},		/* va_atime */
825 		{0, 0},		/* va_mtime */
826 		{0, 0},		/* va_ctime */
827 		0,		/* va_rdev */
828 		MAXBSIZE,	/* va_blksize */
829 		0,		/* va_nblocks */
830 		0		/* va_seq */
831 	};
832 
833 
834 	garp->n4g_va = s_vattr;
835 	garp->n4g_va.va_fsid = mi->mi_vfsp->vfs_dev;
836 	hrt2ts(gethrtime(), &garp->n4g_va.va_atime);
837 	garp->n4g_va.va_mtime = garp->n4g_va.va_ctime = garp->n4g_va.va_atime;
838 }
839 
840 static void
841 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res *gesp, struct mntinfo4 *mi)
842 {
843 	static statvfs64_t s_sb = {
844 		MAXBSIZE,	/* f_bsize */
845 		DEV_BSIZE,	/* f_frsize */
846 		(fsfilcnt64_t)-1, /* f_blocks */
847 		(fsfilcnt64_t)-1, /* f_bfree */
848 		(fsfilcnt64_t)-1, /* f_bavail */
849 		(fsfilcnt64_t)-1, /* f_files */
850 		(fsfilcnt64_t)-1, /* f_ffree */
851 		(fsfilcnt64_t)-1, /* f_favail */
852 		0,		/* f_fsid */
853 		"\0",		/* f_basetype */
854 		0,		/* f_flag */
855 		MAXNAMELEN,	/* f_namemax */
856 		"\0",		/* f_fstr */
857 	};
858 
859 	gesp->n4g_sb = s_sb;
860 	gesp->n4g_sb.f_fsid = mi->mi_vfsp->vfs_fsid.val[0];
861 }
862 
863 static bool_t
864 xdr_ga_fattr_res(XDR *xdrs, struct nfs4_ga_res *garp, bitmap4 resbmap,
865 		bitmap4 argbmap, struct mntinfo4 *mi, ug_cache_t *pug)
866 {
867 	int truefalse;
868 	struct nfs4_ga_ext_res ges, *gesp;
869 	vattr_t *vap = &garp->n4g_va;
870 	vsecattr_t *vsap = &garp->n4g_vsa;
871 
872 	ASSERT(xdrs->x_op == XDR_DECODE);
873 
874 	if (garp->n4g_ext_res)
875 		gesp = garp->n4g_ext_res;
876 	else
877 		gesp = &ges;
878 
879 	vap->va_mask = 0;
880 
881 	/* Check to see if the vattr should be pre-filled */
882 	if (argbmap & NFS4_VATTR_MASK)
883 		xdr_ga_prefill_vattr(garp, mi);
884 
885 	if (argbmap & NFS4_STATFS_ATTR_MASK)
886 		xdr_ga_prefill_statvfs(gesp, mi);
887 
888 	if (resbmap &
889 	    (FATTR4_SUPPORTED_ATTRS_MASK |
890 	    FATTR4_TYPE_MASK |
891 	    FATTR4_FH_EXPIRE_TYPE_MASK |
892 	    FATTR4_CHANGE_MASK |
893 	    FATTR4_SIZE_MASK |
894 	    FATTR4_LINK_SUPPORT_MASK |
895 	    FATTR4_SYMLINK_SUPPORT_MASK |
896 	    FATTR4_NAMED_ATTR_MASK)) {
897 
898 		if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
899 			if (!xdr_bitmap4(xdrs, &gesp->n4g_suppattrs))
900 				return (FALSE);
901 		}
902 		if (resbmap & FATTR4_TYPE_MASK) {
903 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_type))
904 				return (FALSE);
905 
906 			if (vap->va_type < NF4REG ||
907 			    vap->va_type > NF4NAMEDATTR)
908 				vap->va_type = VBAD;
909 			else
910 				vap->va_type = nf4_to_vt[vap->va_type];
911 			if (vap->va_type == VBLK)
912 				vap->va_blksize = DEV_BSIZE;
913 
914 			vap->va_mask |= AT_TYPE;
915 		}
916 		if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
917 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_fet))
918 				return (FALSE);
919 		}
920 		if (resbmap & FATTR4_CHANGE_MASK) {
921 			if (!xdr_u_longlong_t(xdrs,
922 			    (u_longlong_t *)&garp->n4g_change))
923 				return (FALSE);
924 			garp->n4g_change_valid = 1;
925 		}
926 		if (resbmap & FATTR4_SIZE_MASK) {
927 			if (!xdr_u_longlong_t(xdrs,
928 			    (u_longlong_t *)&vap->va_size))
929 				return (FALSE);
930 			if (!NFS4_SIZE_OK(vap->va_size)) {
931 				garp->n4g_attrerr = EFBIG;
932 				garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
933 			} else {
934 				vap->va_mask |= AT_SIZE;
935 			}
936 		}
937 		if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
938 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
939 				return (FALSE);
940 			gesp->n4g_pc4.pc4_link_support =
941 			    (truefalse ? TRUE : FALSE);
942 		}
943 		if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
944 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
945 				return (FALSE);
946 			gesp->n4g_pc4.pc4_symlink_support =
947 			    (truefalse ? TRUE : FALSE);
948 		}
949 		if (resbmap & FATTR4_NAMED_ATTR_MASK) {
950 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
951 				return (FALSE);
952 			gesp->n4g_pc4.pc4_xattr_exists = TRUE;
953 			gesp->n4g_pc4.pc4_xattr_exists =
954 			    (truefalse ? TRUE : FALSE);
955 		}
956 	}
957 	if (resbmap &
958 	    (FATTR4_FSID_MASK |
959 	    FATTR4_UNIQUE_HANDLES_MASK |
960 	    FATTR4_LEASE_TIME_MASK |
961 	    FATTR4_RDATTR_ERROR_MASK)) {
962 
963 		if (resbmap & FATTR4_FSID_MASK) {
964 			if ((!xdr_u_longlong_t(xdrs,
965 			    (u_longlong_t *)&garp->n4g_fsid.major)) ||
966 			    (!xdr_u_longlong_t(xdrs,
967 			    (u_longlong_t *)&garp->n4g_fsid.minor)))
968 				return (FALSE);
969 			garp->n4g_fsid_valid = 1;
970 		}
971 		if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
972 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
973 				return (FALSE);
974 			gesp->n4g_pc4.pc4_unique_handles =
975 			    (truefalse ? TRUE : FALSE);
976 		}
977 		if (resbmap & FATTR4_LEASE_TIME_MASK) {
978 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_leasetime))
979 				return (FALSE);
980 		}
981 		if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
982 			if (!XDR_GETINT32(xdrs,
983 			    (int *)&gesp->n4g_rdattr_error))
984 				return (FALSE);
985 		}
986 	}
987 	if (resbmap &
988 	    (FATTR4_ACL_MASK |
989 	    FATTR4_ACLSUPPORT_MASK |
990 	    FATTR4_ARCHIVE_MASK |
991 	    FATTR4_CANSETTIME_MASK)) {
992 
993 		if (resbmap & FATTR4_ACL_MASK) {
994 			fattr4_acl	acl;
995 
996 			acl.fattr4_acl_val = NULL;
997 			acl.fattr4_acl_len = 0;
998 
999 			if (!xdr_fattr4_acl(xdrs, &acl))
1000 				return (FALSE);
1001 
1002 			vsap->vsa_aclcnt = acl.fattr4_acl_len;
1003 			vsap->vsa_aclentp = acl.fattr4_acl_val;
1004 			vsap->vsa_mask = VSA_ACE | VSA_ACECNT;
1005 			vsap->vsa_aclentsz = vsap->vsa_aclcnt * sizeof (ace_t);
1006 
1007 		}
1008 		if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1009 			if (!XDR_GETINT32(xdrs, (int *)&gesp->n4g_aclsupport))
1010 				return (FALSE);
1011 		}
1012 		if (resbmap & FATTR4_ARCHIVE_MASK) {
1013 			ASSERT(0);
1014 		}
1015 		if (resbmap & FATTR4_CANSETTIME_MASK) {
1016 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1017 				return (FALSE);
1018 			gesp->n4g_pc4.pc4_cansettime =
1019 			    (truefalse ? TRUE : FALSE);
1020 		}
1021 	}
1022 	if (resbmap &
1023 	    (FATTR4_CASE_INSENSITIVE_MASK |
1024 	    FATTR4_CASE_PRESERVING_MASK |
1025 	    FATTR4_CHOWN_RESTRICTED_MASK |
1026 	    FATTR4_FILEHANDLE_MASK |
1027 	    FATTR4_FILEID_MASK |
1028 	    FATTR4_FILES_AVAIL_MASK |
1029 	    FATTR4_FILES_FREE_MASK |
1030 	    FATTR4_FILES_TOTAL_MASK)) {
1031 
1032 		if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1033 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1034 				return (FALSE);
1035 			gesp->n4g_pc4.pc4_case_insensitive =
1036 			    (truefalse ? TRUE : FALSE);
1037 		}
1038 		if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1039 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1040 				return (FALSE);
1041 			gesp->n4g_pc4.pc4_case_preserving =
1042 			    (truefalse ? TRUE : FALSE);
1043 		}
1044 		if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1045 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1046 				return (FALSE);
1047 			gesp->n4g_pc4.pc4_chown_restricted =
1048 			    (truefalse ? TRUE : FALSE);
1049 		}
1050 		if (resbmap & FATTR4_FILEHANDLE_MASK) {
1051 			gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1052 			gesp->n4g_fh_u.nfs_fh4_alt.val =
1053 			    gesp->n4g_fh_u.nfs_fh4_alt.data;
1054 			if (!xdr_bytes(xdrs,
1055 			    (char **)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_val,
1056 			    (uint_t *)&gesp->n4g_fh_u.n4g_fh.nfs_fh4_len,
1057 			    NFS4_FHSIZE))
1058 				return (FALSE);
1059 		}
1060 		if (resbmap & FATTR4_FILEID_MASK) {
1061 			if (!xdr_u_longlong_t(xdrs,
1062 			    (u_longlong_t *)&vap->va_nodeid))
1063 				return (FALSE);
1064 			vap->va_mask |= AT_NODEID;
1065 		}
1066 		if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1067 			if (!xdr_u_longlong_t(xdrs,
1068 			    (u_longlong_t *)&gesp->n4g_sb.f_favail))
1069 				return (FALSE);
1070 		}
1071 		if (resbmap & FATTR4_FILES_FREE_MASK) {
1072 			if (!xdr_u_longlong_t(xdrs,
1073 			    (u_longlong_t *)&gesp->n4g_sb.f_ffree))
1074 				return (FALSE);
1075 		}
1076 		if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1077 			if (!xdr_u_longlong_t(xdrs,
1078 			    (u_longlong_t *)&gesp->n4g_sb.f_files))
1079 				return (FALSE);
1080 		}
1081 	}
1082 	if (resbmap &
1083 	    (FATTR4_FS_LOCATIONS_MASK |
1084 	    FATTR4_HIDDEN_MASK |
1085 	    FATTR4_HOMOGENEOUS_MASK)) {
1086 
1087 		if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1088 			if (!xdr_fattr4_fs_locations(xdrs,
1089 			    &gesp->n4g_fslocations))
1090 				return (FALSE);
1091 		}
1092 		if (resbmap & FATTR4_HIDDEN_MASK) {
1093 			ASSERT(0);
1094 		}
1095 		if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1096 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1097 				return (FALSE);
1098 			gesp->n4g_pc4.pc4_homogeneous =
1099 			    (truefalse ? TRUE : FALSE);
1100 		}
1101 	}
1102 	if (resbmap &
1103 	    (FATTR4_MAXFILESIZE_MASK |
1104 	    FATTR4_MAXLINK_MASK |
1105 	    FATTR4_MAXNAME_MASK |
1106 	    FATTR4_MAXREAD_MASK |
1107 	    FATTR4_MAXWRITE_MASK)) {
1108 
1109 		if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1110 			if (!xdr_u_longlong_t(xdrs,
1111 			    (u_longlong_t *)&gesp->n4g_maxfilesize))
1112 				return (FALSE);
1113 		}
1114 		if (resbmap & FATTR4_MAXLINK_MASK) {
1115 			if (!XDR_GETINT32(xdrs,
1116 			    (int *)&gesp->n4g_pc4.pc4_link_max))
1117 				return (FALSE);
1118 		}
1119 		if (resbmap & FATTR4_MAXNAME_MASK) {
1120 			if (!XDR_GETINT32(xdrs,
1121 			    (int *)&gesp->n4g_pc4.pc4_name_max))
1122 				return (FALSE);
1123 			gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1124 		}
1125 		if (resbmap & FATTR4_MAXREAD_MASK) {
1126 			if (!xdr_u_longlong_t(xdrs,
1127 			    (u_longlong_t *)&gesp->n4g_maxread))
1128 				return (FALSE);
1129 		}
1130 		if (resbmap & FATTR4_MAXWRITE_MASK) {
1131 			if (!xdr_u_longlong_t(xdrs,
1132 			    (u_longlong_t *)&gesp->n4g_maxwrite))
1133 				return (FALSE);
1134 		}
1135 	}
1136 	if (resbmap &
1137 	    (FATTR4_MIMETYPE_MASK |
1138 	    FATTR4_MODE_MASK |
1139 	    FATTR4_NO_TRUNC_MASK |
1140 	    FATTR4_NUMLINKS_MASK)) {
1141 
1142 		if (resbmap & FATTR4_MIMETYPE_MASK) {
1143 			ASSERT(0);
1144 		}
1145 		if (resbmap & FATTR4_MODE_MASK) {
1146 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_mode))
1147 				return (FALSE);
1148 			vap->va_mask |= AT_MODE;
1149 		}
1150 		if (resbmap & FATTR4_NO_TRUNC_MASK) {
1151 			if (!XDR_GETINT32(xdrs, (int *)&truefalse))
1152 				return (FALSE);
1153 			gesp->n4g_pc4.pc4_no_trunc =
1154 			    (truefalse ? TRUE : FALSE);
1155 		}
1156 		if (resbmap & FATTR4_NUMLINKS_MASK) {
1157 			if (!XDR_GETINT32(xdrs, (int *)&vap->va_nlink))
1158 				return (FALSE);
1159 			vap->va_mask |= AT_NLINK;
1160 		}
1161 	}
1162 	if (resbmap &
1163 	    (FATTR4_OWNER_MASK |
1164 	    FATTR4_OWNER_GROUP_MASK |
1165 	    FATTR4_QUOTA_AVAIL_HARD_MASK |
1166 	    FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1167 
1168 		if (resbmap & FATTR4_OWNER_MASK) {
1169 			uint_t *owner_length, ol;
1170 			char *owner_val = NULL;
1171 			char *owner_alloc = NULL;
1172 			utf8string ov;
1173 			int error;
1174 
1175 			/* get the OWNER_LENGTH */
1176 			if (!xdr_u_int(xdrs, &ol))
1177 				return (FALSE);
1178 
1179 			/* Manage the owner length location */
1180 			if (pug && ol <= MAX_OG_NAME) {
1181 				owner_length = &pug->u_curr.utf8string_len;
1182 				*owner_length = ol;
1183 			} else {
1184 				owner_length = &ol;
1185 			}
1186 
1187 			/* find memory to store the decode */
1188 			if (*owner_length > MAX_OG_NAME || pug == NULL)
1189 				owner_val = owner_alloc =
1190 				    kmem_alloc(*owner_length, KM_SLEEP);
1191 			else
1192 				owner_val = pug->u_curr.utf8string_val;
1193 
1194 			/* get the OWNER string */
1195 			if (!xdr_opaque(xdrs, owner_val, *owner_length)) {
1196 				if (owner_alloc)
1197 					kmem_free(owner_alloc, *owner_length);
1198 				return (FALSE);
1199 			}
1200 
1201 			/* Optimize for matching if called for */
1202 			if (pug &&
1203 			    *owner_length == pug->u_last.utf8string_len &&
1204 			    bcmp(owner_val, pug->u_last.utf8string_val,
1205 			    *owner_length) == 0) {
1206 				vap->va_uid = pug->uid;
1207 				vap->va_mask |= AT_UID;
1208 			} else {
1209 				uid_t uid;
1210 
1211 				ov.utf8string_len = *owner_length;
1212 				ov.utf8string_val = owner_val;
1213 				error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1214 				/*
1215 				 * String was mapped, but to nobody because
1216 				 * we are nfsmapid, indicate it should not
1217 				 * be cached.
1218 				 */
1219 				if (error == ENOTSUP) {
1220 					error = 0;
1221 					garp->n4g_attrwhy =
1222 					    NFS4_GETATTR_NOCACHE_OK;
1223 				}
1224 
1225 				if (error) {
1226 					garp->n4g_attrerr = error;
1227 					garp->n4g_attrwhy =
1228 					    NFS4_GETATTR_ATUID_ERR;
1229 				} else {
1230 					vap->va_uid = uid;
1231 					vap->va_mask |= AT_UID;
1232 					if (pug && ol <= MAX_OG_NAME) {
1233 						pug->uid = uid;
1234 						U_SWAP_CURR_LAST(pug);
1235 					}
1236 				}
1237 				if (owner_alloc)
1238 					kmem_free(owner_alloc, *owner_length);
1239 			}
1240 		}
1241 		if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1242 			uint_t *group_length, gl;
1243 			char *group_val = NULL;
1244 			char *group_alloc = NULL;
1245 			utf8string gv;
1246 			int error;
1247 
1248 			/* get the OWNER_GROUP_LENGTH */
1249 			if (!xdr_u_int(xdrs, &gl))
1250 				return (FALSE);
1251 
1252 			/* Manage the group length location */
1253 			if (pug && gl <= MAX_OG_NAME) {
1254 				group_length = &pug->g_curr.utf8string_len;
1255 				*group_length = gl;
1256 			} else {
1257 				group_length = &gl;
1258 			}
1259 
1260 			/* find memory to store the decode */
1261 			if (*group_length > MAX_OG_NAME || pug == NULL)
1262 				group_val = group_alloc =
1263 				    kmem_alloc(*group_length, KM_SLEEP);
1264 			else
1265 				group_val = pug->g_curr.utf8string_val;
1266 
1267 			/* get the OWNER_GROUP string */
1268 			if (!xdr_opaque(xdrs, group_val, *group_length)) {
1269 				if (group_alloc)
1270 					kmem_free(group_alloc, *group_length);
1271 				return (FALSE);
1272 			}
1273 
1274 			/* Optimize for matching if called for */
1275 			if (pug &&
1276 			    *group_length == pug->g_last.utf8string_len &&
1277 			    bcmp(group_val, pug->g_last.utf8string_val,
1278 			    *group_length) == 0) {
1279 				vap->va_gid = pug->gid;
1280 				vap->va_mask |= AT_GID;
1281 			} else {
1282 				uid_t gid;
1283 
1284 				gv.utf8string_len = *group_length;
1285 				gv.utf8string_val = group_val;
1286 				error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1287 				/*
1288 				 * String was mapped, but to nobody because
1289 				 * we are nfsmapid, indicate it should not
1290 				 * be cached.
1291 				 */
1292 				if (error == ENOTSUP) {
1293 					error = 0;
1294 					garp->n4g_attrwhy =
1295 					    NFS4_GETATTR_NOCACHE_OK;
1296 				}
1297 
1298 				if (error) {
1299 					garp->n4g_attrerr = error;
1300 					garp->n4g_attrwhy =
1301 					    NFS4_GETATTR_ATGID_ERR;
1302 				} else {
1303 					vap->va_gid = gid;
1304 					vap->va_mask |= AT_GID;
1305 					if (pug && gl <= MAX_OG_NAME) {
1306 						pug->gid = gid;
1307 						G_SWAP_CURR_LAST(pug);
1308 					}
1309 				}
1310 				if (group_alloc) {
1311 					kmem_free(group_alloc, *group_length);
1312 				}
1313 			}
1314 		}
1315 		if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1316 			ASSERT(0);
1317 		}
1318 		if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1319 			ASSERT(0);
1320 		}
1321 	}
1322 	if (resbmap &
1323 	    (FATTR4_QUOTA_USED_MASK |
1324 	    FATTR4_SPACE_AVAIL_MASK |
1325 	    FATTR4_SPACE_FREE_MASK |
1326 	    FATTR4_SPACE_TOTAL_MASK |
1327 	    FATTR4_SPACE_USED_MASK |
1328 	    FATTR4_SYSTEM_MASK)) {
1329 
1330 		if (resbmap & FATTR4_QUOTA_USED_MASK) {
1331 			ASSERT(0);
1332 		}
1333 		if (resbmap & FATTR4_RAWDEV_MASK) {
1334 			fattr4_rawdev rawdev;
1335 			if (!xdr_fattr4_rawdev(xdrs, &rawdev))
1336 				return (FALSE);
1337 
1338 			if (vap->va_type == VCHR || vap->va_type == VBLK) {
1339 				vap->va_rdev = makedevice(rawdev.specdata1,
1340 				    rawdev.specdata2);
1341 			} else {
1342 				vap->va_rdev = 0;
1343 			}
1344 			vap->va_mask |= AT_RDEV;
1345 		}
1346 		if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1347 			if (!xdr_u_longlong_t(xdrs,
1348 			    (u_longlong_t *)&gesp->n4g_sb.f_bavail))
1349 				return (FALSE);
1350 			gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1351 		}
1352 		if (resbmap & FATTR4_SPACE_FREE_MASK) {
1353 			if (!xdr_u_longlong_t(xdrs,
1354 			    (u_longlong_t *)&gesp->n4g_sb.f_bfree))
1355 				return (FALSE);
1356 			gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1357 		}
1358 		if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1359 			if (!xdr_u_longlong_t(xdrs,
1360 			    (u_longlong_t *)&gesp->n4g_sb.f_blocks))
1361 				return (FALSE);
1362 			gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1363 		}
1364 		if (resbmap & FATTR4_SPACE_USED_MASK) {
1365 			uint64_t space_used;
1366 			if (!xdr_u_longlong_t(xdrs,
1367 			    (u_longlong_t *)&space_used))
1368 				return (FALSE);
1369 
1370 			/* Compute space depending on device type */
1371 			ASSERT((vap->va_mask & AT_TYPE));
1372 			if (vap->va_type == VREG || vap->va_type == VDIR ||
1373 			    vap->va_type == VLNK) {
1374 				vap->va_nblocks = (u_longlong_t)
1375 				    ((space_used + (offset4)DEV_BSIZE -
1376 				    (offset4)1) / (offset4)DEV_BSIZE);
1377 			} else {
1378 				vap->va_nblocks = 0;
1379 			}
1380 			vap->va_mask |= AT_NBLOCKS;
1381 		}
1382 		if (resbmap & FATTR4_SYSTEM_MASK) {
1383 			ASSERT(0);
1384 		}
1385 	}
1386 	if (resbmap &
1387 	    (FATTR4_TIME_ACCESS_MASK |
1388 	    FATTR4_TIME_ACCESS_SET_MASK |
1389 	    FATTR4_TIME_BACKUP_MASK |
1390 	    FATTR4_TIME_CREATE_MASK |
1391 	    FATTR4_TIME_DELTA_MASK |
1392 	    FATTR4_TIME_METADATA_MASK |
1393 	    FATTR4_TIME_MODIFY_MASK |
1394 	    FATTR4_TIME_MODIFY_SET_MASK |
1395 	    FATTR4_MOUNTED_ON_FILEID_MASK)) {
1396 
1397 		if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1398 			nfstime4 atime;
1399 			int error;
1400 
1401 			if (!xdr_longlong_t(xdrs,
1402 			    (longlong_t *)&atime.seconds))
1403 				return (FALSE);
1404 			if (!XDR_GETINT32(xdrs, (int *)&atime.nseconds))
1405 				return (FALSE);
1406 			error = nfs4_time_ntov(&atime, &vap->va_atime);
1407 			if (error) {
1408 				garp->n4g_attrerr = error;
1409 				garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
1410 			}
1411 			vap->va_mask |= AT_ATIME;
1412 		}
1413 		if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
1414 			ASSERT(0);
1415 		}
1416 		if (resbmap & FATTR4_TIME_BACKUP_MASK) {
1417 			ASSERT(0);
1418 		}
1419 		if (resbmap & FATTR4_TIME_CREATE_MASK) {
1420 			ASSERT(0);
1421 		}
1422 		if (resbmap & FATTR4_TIME_DELTA_MASK) {
1423 			if ((!xdr_u_longlong_t(xdrs,
1424 			    (u_longlong_t *)&gesp->n4g_delta.seconds)) ||
1425 			    (!xdr_u_int(xdrs, &gesp->n4g_delta.nseconds)))
1426 				return (FALSE);
1427 		}
1428 		if (resbmap & FATTR4_TIME_METADATA_MASK) {
1429 			nfstime4 mdt;
1430 			int error;
1431 
1432 			if (!xdr_longlong_t(xdrs, (longlong_t *)&mdt.seconds))
1433 				return (FALSE);
1434 			if (!XDR_GETINT32(xdrs, (int32_t *)&mdt.nseconds))
1435 				return (FALSE);
1436 			error = nfs4_time_ntov(&mdt, &vap->va_ctime);
1437 			if (error) {
1438 				garp->n4g_attrerr = error;
1439 				garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
1440 			}
1441 			vap->va_mask |= AT_CTIME;
1442 		}
1443 		if (resbmap & FATTR4_TIME_MODIFY_MASK) {
1444 			nfstime4 mtime;
1445 			int error;
1446 
1447 			if (!xdr_longlong_t(xdrs,
1448 			    (longlong_t *)&mtime.seconds))
1449 				return (FALSE);
1450 			if (!XDR_GETINT32(xdrs, (int32_t *)&mtime.nseconds))
1451 				return (FALSE);
1452 			error = nfs4_time_ntov(&mtime, &vap->va_mtime);
1453 			if (error) {
1454 				garp->n4g_attrerr = error;
1455 				garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
1456 			}
1457 			vap->va_mask |= AT_MTIME;
1458 		}
1459 		if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
1460 			ASSERT(0);
1461 		}
1462 		if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
1463 			if (!xdr_u_longlong_t(xdrs,
1464 			    (u_longlong_t *)&garp->n4g_mon_fid))
1465 				return (FALSE);
1466 			garp->n4g_mon_fid_valid = 1;
1467 		}
1468 	}
1469 
1470 	if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
1471 		/* copy only if not provided */
1472 		if (garp->n4g_ext_res == NULL) {
1473 			garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
1474 			bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
1475 		}
1476 	}
1477 
1478 	return (TRUE);
1479 }
1480 
1481 /*
1482  * Inlined version of get_bitmap4 processing
1483  */
1484 bitmap4
1485 xdr_get_bitmap4_inline(uint32_t **iptr)
1486 {
1487 	uint32_t resbmaplen;
1488 	bitmap4 bm;
1489 	uint32_t *ptr = *iptr;
1490 
1491 	/* bitmap LENGTH */
1492 	resbmaplen = IXDR_GET_U_INT32(ptr);
1493 
1494 	/* Inline the bitmap and attrlen for common case of two word map */
1495 	if (resbmaplen == 2) {
1496 		IXDR_GET_HYPER(ptr, bm);
1497 		*iptr = ptr;
1498 		return (bm);
1499 	}
1500 
1501 #if defined(_LITTLE_ENDIAN)
1502 	bm = IXDR_GET_U_INT32(ptr);
1503 	if (--resbmaplen == 0) {
1504 		*iptr = ptr;
1505 		return (bm);
1506 	}
1507 	*((uint32_t *)&bm) |= IXDR_GET_U_INT32(ptr);
1508 	if (--resbmaplen == 0) {
1509 		*iptr = ptr;
1510 		return (bm);
1511 	}
1512 	ptr += resbmaplen;
1513 	*iptr = ptr;
1514 	return (bm);
1515 #elif defined(_BIG_ENDIAN)
1516 	*((uint32_t *)&bm) = IXDR_GET_U_INT32(ptr);
1517 	if (--resbmaplen == 0) {
1518 		*iptr = ptr;
1519 		return (bm);
1520 	}
1521 	bm |= IXDR_GET_U_INT32(ptr);
1522 	if (--resbmaplen == 0) {
1523 		*iptr = ptr;
1524 		return (bm);
1525 	}
1526 	ptr += resbmaplen;
1527 	*iptr = ptr;
1528 	return (bm);
1529 #else
1530 	ASSERT(0);
1531 	ptr += resbmaplen;
1532 	*iptr = ptr;
1533 	return (0);
1534 #endif
1535 }
1536 
1537 static bool_t
1538 xdr_ga_fattr_res_inline(uint32_t *ptr, struct nfs4_ga_res *garp,
1539 			bitmap4 resbmap, bitmap4 argbmap, struct mntinfo4 *mi,
1540 			ug_cache_t *pug)
1541 {
1542 	int truefalse;
1543 	struct nfs4_ga_ext_res ges, *gesp;
1544 	vattr_t *vap = &garp->n4g_va;
1545 
1546 	if (garp->n4g_ext_res)
1547 		gesp = garp->n4g_ext_res;
1548 	else
1549 		gesp = &ges;
1550 
1551 	vap->va_mask = 0;
1552 
1553 	/* Check to see if the vattr should be pre-filled */
1554 	if (argbmap & NFS4_VATTR_MASK)
1555 		xdr_ga_prefill_vattr(garp, mi);
1556 
1557 	if (argbmap & NFS4_STATFS_ATTR_MASK)
1558 		xdr_ga_prefill_statvfs(gesp, mi);
1559 
1560 	if (resbmap &
1561 	    (FATTR4_SUPPORTED_ATTRS_MASK |
1562 	    FATTR4_TYPE_MASK |
1563 	    FATTR4_FH_EXPIRE_TYPE_MASK |
1564 	    FATTR4_CHANGE_MASK |
1565 	    FATTR4_SIZE_MASK |
1566 	    FATTR4_LINK_SUPPORT_MASK |
1567 	    FATTR4_SYMLINK_SUPPORT_MASK |
1568 	    FATTR4_NAMED_ATTR_MASK)) {
1569 
1570 		if (resbmap & FATTR4_SUPPORTED_ATTRS_MASK) {
1571 			gesp->n4g_suppattrs = xdr_get_bitmap4_inline(&ptr);
1572 		}
1573 		if (resbmap & FATTR4_TYPE_MASK) {
1574 			vap->va_type = IXDR_GET_U_INT32(ptr);
1575 
1576 			if (vap->va_type < NF4REG ||
1577 			    vap->va_type > NF4NAMEDATTR)
1578 				vap->va_type = VBAD;
1579 			else
1580 				vap->va_type = nf4_to_vt[vap->va_type];
1581 			if (vap->va_type == VBLK)
1582 				vap->va_blksize = DEV_BSIZE;
1583 
1584 			vap->va_mask |= AT_TYPE;
1585 		}
1586 		if (resbmap & FATTR4_FH_EXPIRE_TYPE_MASK) {
1587 			gesp->n4g_fet = IXDR_GET_U_INT32(ptr);
1588 		}
1589 		if (resbmap & FATTR4_CHANGE_MASK) {
1590 			IXDR_GET_U_HYPER(ptr, garp->n4g_change);
1591 			garp->n4g_change_valid = 1;
1592 		}
1593 		if (resbmap & FATTR4_SIZE_MASK) {
1594 			IXDR_GET_U_HYPER(ptr, vap->va_size);
1595 
1596 			if (!NFS4_SIZE_OK(vap->va_size)) {
1597 				garp->n4g_attrerr = EFBIG;
1598 				garp->n4g_attrwhy = NFS4_GETATTR_ATSIZE_ERR;
1599 			} else {
1600 				vap->va_mask |= AT_SIZE;
1601 			}
1602 		}
1603 		if (resbmap & FATTR4_LINK_SUPPORT_MASK) {
1604 			truefalse = IXDR_GET_U_INT32(ptr);
1605 			gesp->n4g_pc4.pc4_link_support =
1606 			    (truefalse ? TRUE : FALSE);
1607 		}
1608 		if (resbmap & FATTR4_SYMLINK_SUPPORT_MASK) {
1609 			truefalse = IXDR_GET_U_INT32(ptr);
1610 			gesp->n4g_pc4.pc4_symlink_support =
1611 			    (truefalse ? TRUE : FALSE);
1612 		}
1613 		if (resbmap & FATTR4_NAMED_ATTR_MASK) {
1614 			truefalse = IXDR_GET_U_INT32(ptr);
1615 			gesp->n4g_pc4.pc4_xattr_exists = TRUE;
1616 			gesp->n4g_pc4.pc4_xattr_exists =
1617 			    (truefalse ? TRUE : FALSE);
1618 		}
1619 	}
1620 	if (resbmap &
1621 	    (FATTR4_FSID_MASK |
1622 	    FATTR4_UNIQUE_HANDLES_MASK |
1623 	    FATTR4_LEASE_TIME_MASK |
1624 	    FATTR4_RDATTR_ERROR_MASK)) {
1625 
1626 		if (resbmap & FATTR4_FSID_MASK) {
1627 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.major);
1628 			IXDR_GET_U_HYPER(ptr, garp->n4g_fsid.minor);
1629 			garp->n4g_fsid_valid = 1;
1630 		}
1631 		if (resbmap & FATTR4_UNIQUE_HANDLES_MASK) {
1632 			truefalse = IXDR_GET_U_INT32(ptr);
1633 			gesp->n4g_pc4.pc4_unique_handles =
1634 			    (truefalse ? TRUE : FALSE);
1635 		}
1636 		if (resbmap & FATTR4_LEASE_TIME_MASK) {
1637 			gesp->n4g_leasetime = IXDR_GET_U_INT32(ptr);
1638 		}
1639 		if (resbmap & FATTR4_RDATTR_ERROR_MASK) {
1640 			gesp->n4g_rdattr_error = IXDR_GET_U_INT32(ptr);
1641 		}
1642 	}
1643 	if (resbmap &
1644 	    (FATTR4_ACL_MASK |
1645 	    FATTR4_ACLSUPPORT_MASK |
1646 	    FATTR4_ARCHIVE_MASK |
1647 	    FATTR4_CANSETTIME_MASK)) {
1648 
1649 		if (resbmap & FATTR4_ACL_MASK) {
1650 			ASSERT(0);
1651 		}
1652 		if (resbmap & FATTR4_ACLSUPPORT_MASK) {
1653 			gesp->n4g_aclsupport = IXDR_GET_U_INT32(ptr);
1654 		}
1655 		if (resbmap & FATTR4_ARCHIVE_MASK) {
1656 			ASSERT(0);
1657 		}
1658 		if (resbmap & FATTR4_CANSETTIME_MASK) {
1659 			truefalse = IXDR_GET_U_INT32(ptr);
1660 			gesp->n4g_pc4.pc4_cansettime =
1661 			    (truefalse ? TRUE : FALSE);
1662 		}
1663 	}
1664 	if (resbmap &
1665 	    (FATTR4_CASE_INSENSITIVE_MASK |
1666 	    FATTR4_CASE_PRESERVING_MASK |
1667 	    FATTR4_CHOWN_RESTRICTED_MASK |
1668 	    FATTR4_FILEHANDLE_MASK |
1669 	    FATTR4_FILEID_MASK |
1670 	    FATTR4_FILES_AVAIL_MASK |
1671 	    FATTR4_FILES_FREE_MASK |
1672 	    FATTR4_FILES_TOTAL_MASK)) {
1673 
1674 		if (resbmap & FATTR4_CASE_INSENSITIVE_MASK) {
1675 			truefalse = IXDR_GET_U_INT32(ptr);
1676 			gesp->n4g_pc4.pc4_case_insensitive =
1677 			    (truefalse ? TRUE : FALSE);
1678 		}
1679 		if (resbmap & FATTR4_CASE_PRESERVING_MASK) {
1680 			truefalse = IXDR_GET_U_INT32(ptr);
1681 			gesp->n4g_pc4.pc4_case_preserving =
1682 			    (truefalse ? TRUE : FALSE);
1683 		}
1684 		if (resbmap & FATTR4_CHOWN_RESTRICTED_MASK) {
1685 			truefalse = IXDR_GET_U_INT32(ptr);
1686 			gesp->n4g_pc4.pc4_chown_restricted =
1687 			    (truefalse ? TRUE : FALSE);
1688 		}
1689 		if (resbmap & FATTR4_FILEHANDLE_MASK) {
1690 			int len = IXDR_GET_U_INT32(ptr);
1691 
1692 			gesp->n4g_fh_u.nfs_fh4_alt.len = 0;
1693 			gesp->n4g_fh_u.nfs_fh4_alt.val =
1694 			    gesp->n4g_fh_u.nfs_fh4_alt.data;
1695 			gesp->n4g_fh_u.n4g_fh.nfs_fh4_len = len;
1696 
1697 			bcopy(ptr, gesp->n4g_fh_u.n4g_fh.nfs_fh4_val, len);
1698 
1699 			ptr += RNDUP(len) / BYTES_PER_XDR_UNIT;
1700 		}
1701 		if (resbmap & FATTR4_FILEID_MASK) {
1702 			IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
1703 			vap->va_mask |= AT_NODEID;
1704 		}
1705 		if (resbmap & FATTR4_FILES_AVAIL_MASK) {
1706 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_favail);
1707 		}
1708 		if (resbmap & FATTR4_FILES_FREE_MASK) {
1709 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_ffree);
1710 		}
1711 		if (resbmap & FATTR4_FILES_TOTAL_MASK) {
1712 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_files);
1713 		}
1714 	}
1715 	if (resbmap &
1716 	    (FATTR4_FS_LOCATIONS_MASK |
1717 	    FATTR4_HIDDEN_MASK |
1718 	    FATTR4_HOMOGENEOUS_MASK)) {
1719 
1720 		if (resbmap & FATTR4_FS_LOCATIONS_MASK) {
1721 			ASSERT(0);
1722 		}
1723 		if (resbmap & FATTR4_HIDDEN_MASK) {
1724 			ASSERT(0);
1725 		}
1726 		if (resbmap & FATTR4_HOMOGENEOUS_MASK) {
1727 			truefalse = IXDR_GET_U_INT32(ptr);
1728 			gesp->n4g_pc4.pc4_homogeneous =
1729 			    (truefalse ? TRUE : FALSE);
1730 		}
1731 	}
1732 	if (resbmap &
1733 	    (FATTR4_MAXFILESIZE_MASK |
1734 	    FATTR4_MAXLINK_MASK |
1735 	    FATTR4_MAXNAME_MASK |
1736 	    FATTR4_MAXREAD_MASK |
1737 	    FATTR4_MAXWRITE_MASK)) {
1738 
1739 		if (resbmap & FATTR4_MAXFILESIZE_MASK) {
1740 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxfilesize);
1741 		}
1742 		if (resbmap & FATTR4_MAXLINK_MASK) {
1743 			gesp->n4g_pc4.pc4_link_max = IXDR_GET_U_INT32(ptr);
1744 		}
1745 		if (resbmap & FATTR4_MAXNAME_MASK) {
1746 			gesp->n4g_pc4.pc4_name_max = IXDR_GET_U_INT32(ptr);
1747 			gesp->n4g_sb.f_namemax = gesp->n4g_pc4.pc4_name_max;
1748 		}
1749 		if (resbmap & FATTR4_MAXREAD_MASK) {
1750 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxread);
1751 		}
1752 		if (resbmap & FATTR4_MAXWRITE_MASK) {
1753 			IXDR_GET_U_HYPER(ptr, gesp->n4g_maxwrite);
1754 		}
1755 	}
1756 	if (resbmap &
1757 	    (FATTR4_MIMETYPE_MASK |
1758 	    FATTR4_MODE_MASK |
1759 	    FATTR4_NO_TRUNC_MASK |
1760 	    FATTR4_NUMLINKS_MASK)) {
1761 
1762 		if (resbmap & FATTR4_MIMETYPE_MASK) {
1763 			ASSERT(0);
1764 		}
1765 		if (resbmap & FATTR4_MODE_MASK) {
1766 			vap->va_mode = IXDR_GET_U_INT32(ptr);
1767 			vap->va_mask |= AT_MODE;
1768 		}
1769 		if (resbmap & FATTR4_NO_TRUNC_MASK) {
1770 			truefalse = IXDR_GET_U_INT32(ptr);
1771 			gesp->n4g_pc4.pc4_no_trunc =
1772 			    (truefalse ? TRUE : FALSE);
1773 		}
1774 		if (resbmap & FATTR4_NUMLINKS_MASK) {
1775 			vap->va_nlink = IXDR_GET_U_INT32(ptr);
1776 			vap->va_mask |= AT_NLINK;
1777 		}
1778 	}
1779 	if (resbmap &
1780 	    (FATTR4_OWNER_MASK |
1781 	    FATTR4_OWNER_GROUP_MASK |
1782 	    FATTR4_QUOTA_AVAIL_HARD_MASK |
1783 	    FATTR4_QUOTA_AVAIL_SOFT_MASK)) {
1784 
1785 		if (resbmap & FATTR4_OWNER_MASK) {
1786 			uint_t *owner_length, ol;
1787 			char *owner_val = NULL;
1788 			utf8string ov;
1789 			int error;
1790 
1791 			/* get the OWNER_LENGTH */
1792 			ol = IXDR_GET_U_INT32(ptr);
1793 
1794 			/* Manage the owner length location */
1795 			if (pug && ol <= MAX_OG_NAME) {
1796 				owner_length = &pug->u_curr.utf8string_len;
1797 				*owner_length = ol;
1798 			} else {
1799 				owner_length = &ol;
1800 			}
1801 
1802 			/* find memory to store the decode */
1803 			if (*owner_length > MAX_OG_NAME || pug == NULL)
1804 				owner_val = (char *)ptr;
1805 			else
1806 				owner_val = (char *)ptr;
1807 
1808 			/* Optimize for matching if called for */
1809 			if (pug &&
1810 			    *owner_length == pug->u_last.utf8string_len &&
1811 			    bcmp(owner_val, pug->u_last.utf8string_val,
1812 			    *owner_length) == 0) {
1813 				vap->va_uid = pug->uid;
1814 				vap->va_mask |= AT_UID;
1815 			} else {
1816 				uid_t uid;
1817 
1818 				ov.utf8string_len = *owner_length;
1819 				ov.utf8string_val = owner_val;
1820 				error = nfs_idmap_str_uid(&ov, &uid, FALSE);
1821 				/*
1822 				 * String was mapped, but to nobody because
1823 				 * we are nfsmapid, indicate it should not
1824 				 * be cached.
1825 				 */
1826 				if (error == ENOTSUP) {
1827 					error = 0;
1828 					garp->n4g_attrwhy =
1829 					    NFS4_GETATTR_NOCACHE_OK;
1830 				}
1831 
1832 				if (error) {
1833 					garp->n4g_attrerr = error;
1834 					garp->n4g_attrwhy =
1835 					    NFS4_GETATTR_ATUID_ERR;
1836 				} else {
1837 					vap->va_uid = uid;
1838 					vap->va_mask |= AT_UID;
1839 					/* save the results for next time */
1840 					if (pug && ol <= MAX_OG_NAME) {
1841 						pug->uid = uid;
1842 						pug->u_curr.utf8string_len =
1843 						    ov.utf8string_len;
1844 						bcopy(owner_val,
1845 						    pug->u_curr.utf8string_val,
1846 						    ol);
1847 						U_SWAP_CURR_LAST(pug);
1848 					}
1849 				}
1850 			}
1851 			ptr += RNDUP(ol) / BYTES_PER_XDR_UNIT;
1852 		}
1853 		if (resbmap & FATTR4_OWNER_GROUP_MASK) {
1854 			uint_t *group_length, gl;
1855 			char *group_val = NULL;
1856 			utf8string gv;
1857 			int error;
1858 
1859 			/* get the OWNER_GROUP_LENGTH */
1860 			gl = IXDR_GET_U_INT32(ptr);
1861 
1862 			/* Manage the group length location */
1863 			if (pug && gl <= MAX_OG_NAME) {
1864 				group_length = &pug->g_curr.utf8string_len;
1865 				*group_length = gl;
1866 			} else {
1867 				group_length = &gl;
1868 			}
1869 
1870 			/* find memory to store the decode */
1871 			if (*group_length > MAX_OG_NAME || pug == NULL)
1872 				group_val = (char *)ptr;
1873 			else
1874 				group_val = (char *)ptr;
1875 
1876 			/* Optimize for matching if called for */
1877 			if (pug &&
1878 			    *group_length == pug->g_last.utf8string_len &&
1879 			    bcmp(group_val, pug->g_last.utf8string_val,
1880 			    *group_length) == 0) {
1881 				vap->va_gid = pug->gid;
1882 				vap->va_mask |= AT_GID;
1883 			} else {
1884 				uid_t gid;
1885 
1886 				gv.utf8string_len = *group_length;
1887 				gv.utf8string_val = group_val;
1888 				error = nfs_idmap_str_gid(&gv, &gid, FALSE);
1889 				/*
1890 				 * String was mapped, but to nobody because
1891 				 * we are nfsmapid, indicate it should not
1892 				 * be cached.
1893 				 */
1894 				if (error == ENOTSUP) {
1895 					error = 0;
1896 					garp->n4g_attrwhy =
1897 					    NFS4_GETATTR_NOCACHE_OK;
1898 				}
1899 
1900 				if (error) {
1901 					garp->n4g_attrerr = error;
1902 					garp->n4g_attrwhy =
1903 					    NFS4_GETATTR_ATGID_ERR;
1904 				} else {
1905 					vap->va_gid = gid;
1906 					vap->va_mask |= AT_GID;
1907 					if (pug && gl <= MAX_OG_NAME) {
1908 						pug->gid = gid;
1909 						pug->g_curr.utf8string_len =
1910 						    gv.utf8string_len;
1911 						bcopy(group_val,
1912 						    pug->g_curr.utf8string_val,
1913 						    gl);
1914 						G_SWAP_CURR_LAST(pug);
1915 					}
1916 				}
1917 			}
1918 			ptr += RNDUP(gl) / BYTES_PER_XDR_UNIT;
1919 		}
1920 		if (resbmap & FATTR4_QUOTA_AVAIL_HARD_MASK) {
1921 			ASSERT(0);
1922 		}
1923 		if (resbmap & FATTR4_QUOTA_AVAIL_SOFT_MASK) {
1924 			ASSERT(0);
1925 		}
1926 	}
1927 	if (resbmap &
1928 	    (FATTR4_QUOTA_USED_MASK |
1929 	    FATTR4_SPACE_AVAIL_MASK |
1930 	    FATTR4_SPACE_FREE_MASK |
1931 	    FATTR4_SPACE_TOTAL_MASK |
1932 	    FATTR4_SPACE_USED_MASK |
1933 	    FATTR4_SYSTEM_MASK)) {
1934 
1935 		if (resbmap & FATTR4_QUOTA_USED_MASK) {
1936 			ASSERT(0);
1937 		}
1938 		if (resbmap & FATTR4_RAWDEV_MASK) {
1939 			fattr4_rawdev rawdev;
1940 
1941 			rawdev.specdata1 = IXDR_GET_U_INT32(ptr);
1942 			rawdev.specdata2 = IXDR_GET_U_INT32(ptr);
1943 
1944 			if (vap->va_type == VCHR || vap->va_type == VBLK) {
1945 				vap->va_rdev = makedevice(rawdev.specdata1,
1946 				    rawdev.specdata2);
1947 			} else {
1948 				vap->va_rdev = 0;
1949 			}
1950 			vap->va_mask |= AT_RDEV;
1951 		}
1952 		if (resbmap & FATTR4_SPACE_AVAIL_MASK) {
1953 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bavail);
1954 			gesp->n4g_sb.f_bavail /= DEV_BSIZE;
1955 		}
1956 		if (resbmap & FATTR4_SPACE_FREE_MASK) {
1957 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_bfree);
1958 			gesp->n4g_sb.f_bfree /= DEV_BSIZE;
1959 		}
1960 		if (resbmap & FATTR4_SPACE_TOTAL_MASK) {
1961 			IXDR_GET_U_HYPER(ptr, gesp->n4g_sb.f_blocks);
1962 			gesp->n4g_sb.f_blocks /= DEV_BSIZE;
1963 		}
1964 		if (resbmap & FATTR4_SPACE_USED_MASK) {
1965 			uint64_t space_used;
1966 			IXDR_GET_U_HYPER(ptr, space_used);
1967 
1968 			/* Compute space depending on device type */
1969 			ASSERT((vap->va_mask & AT_TYPE));
1970 			if (vap->va_type == VREG || vap->va_type == VDIR ||
1971 			    vap->va_type == VLNK) {
1972 				vap->va_nblocks = (u_longlong_t)
1973 				    ((space_used + (offset4)DEV_BSIZE -
1974 				    (offset4)1) / (offset4)DEV_BSIZE);
1975 			} else {
1976 				vap->va_nblocks = 0;
1977 			}
1978 			vap->va_mask |= AT_NBLOCKS;
1979 		}
1980 		if (resbmap & FATTR4_SYSTEM_MASK) {
1981 			ASSERT(0);
1982 		}
1983 	}
1984 	if (resbmap &
1985 	    (FATTR4_TIME_ACCESS_MASK |
1986 	    FATTR4_TIME_ACCESS_SET_MASK |
1987 	    FATTR4_TIME_BACKUP_MASK |
1988 	    FATTR4_TIME_CREATE_MASK |
1989 	    FATTR4_TIME_DELTA_MASK |
1990 	    FATTR4_TIME_METADATA_MASK |
1991 	    FATTR4_TIME_MODIFY_MASK |
1992 	    FATTR4_TIME_MODIFY_SET_MASK |
1993 	    FATTR4_MOUNTED_ON_FILEID_MASK)) {
1994 
1995 		if (resbmap & FATTR4_TIME_ACCESS_MASK) {
1996 			nfstime4 atime;
1997 			int error;
1998 
1999 			IXDR_GET_U_HYPER(ptr, atime.seconds);
2000 			atime.nseconds = IXDR_GET_U_INT32(ptr);
2001 
2002 			error = nfs4_time_ntov(&atime, &vap->va_atime);
2003 			if (error) {
2004 				garp->n4g_attrerr = error;
2005 				garp->n4g_attrwhy = NFS4_GETATTR_ATATIME_ERR;
2006 			}
2007 			vap->va_mask |= AT_ATIME;
2008 		}
2009 		if (resbmap & FATTR4_TIME_ACCESS_SET_MASK) {
2010 			ASSERT(0);
2011 		}
2012 		if (resbmap & FATTR4_TIME_BACKUP_MASK) {
2013 			ASSERT(0);
2014 		}
2015 		if (resbmap & FATTR4_TIME_CREATE_MASK) {
2016 			ASSERT(0);
2017 		}
2018 		if (resbmap & FATTR4_TIME_DELTA_MASK) {
2019 			IXDR_GET_U_HYPER(ptr, gesp->n4g_delta.seconds);
2020 			gesp->n4g_delta.nseconds = IXDR_GET_U_INT32(ptr);
2021 		}
2022 		if (resbmap & FATTR4_TIME_METADATA_MASK) {
2023 			nfstime4 mdt;
2024 			int error;
2025 
2026 			IXDR_GET_U_HYPER(ptr, mdt.seconds);
2027 			mdt.nseconds = IXDR_GET_U_INT32(ptr);
2028 
2029 			error = nfs4_time_ntov(&mdt, &vap->va_ctime);
2030 			if (error) {
2031 				garp->n4g_attrerr = error;
2032 				garp->n4g_attrwhy = NFS4_GETATTR_ATCTIME_ERR;
2033 			}
2034 			vap->va_mask |= AT_CTIME;
2035 		}
2036 		if (resbmap & FATTR4_TIME_MODIFY_MASK) {
2037 			nfstime4 mtime;
2038 			int error;
2039 
2040 			IXDR_GET_U_HYPER(ptr, mtime.seconds);
2041 			mtime.nseconds = IXDR_GET_U_INT32(ptr);
2042 
2043 			error = nfs4_time_ntov(&mtime, &vap->va_mtime);
2044 			if (error) {
2045 				garp->n4g_attrerr = error;
2046 				garp->n4g_attrwhy = NFS4_GETATTR_ATMTIME_ERR;
2047 			}
2048 			vap->va_mask |= AT_MTIME;
2049 		}
2050 		if (resbmap & FATTR4_TIME_MODIFY_SET_MASK) {
2051 			ASSERT(0);
2052 		}
2053 		if (resbmap & FATTR4_MOUNTED_ON_FILEID_MASK) {
2054 			IXDR_GET_U_HYPER(ptr, garp->n4g_mon_fid);
2055 			garp->n4g_mon_fid_valid = 1;
2056 		}
2057 	}
2058 
2059 	/*
2060 	 * FATTR4_ACL_MASK is not yet supported by this function, but
2061 	 * we check against it anyway, in case it ever is.
2062 	 */
2063 	if (resbmap & ~(NFS4_VATTR_MASK | FATTR4_ACL_MASK)) {
2064 		/* copy only if not provided */
2065 		if (garp->n4g_ext_res == NULL) {
2066 			garp->n4g_ext_res = kmem_alloc(sizeof (ges), KM_SLEEP);
2067 			bcopy(&ges, garp->n4g_ext_res, sizeof (ges));
2068 		}
2069 	}
2070 
2071 	return (TRUE);
2072 }
2073 
2074 
2075 /*
2076  * "." and ".." buffers for filling in on read and readdir
2077  * calls. Intialize the first time and fill in on every
2078  * call to to readdir.
2079  */
2080 char	*nfs4_dot_entries;
2081 char	*nfs4_dot_dot_entry;
2082 
2083 /*
2084  * Create the "." or ".." and pad the buffer once so they are
2085  * copied out as required into the user supplied buffer everytime.
2086  * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2087  * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2088  */
2089 void
2090 nfs4_init_dot_entries()
2091 {
2092 	struct dirent64 *odp;
2093 
2094 	/*
2095 	 * zalloc it so it zeros the buffer out. Need
2096 	 * to just do it once.
2097 	 */
2098 	nfs4_dot_entries = kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2099 	    KM_SLEEP);
2100 
2101 	odp = (struct dirent64 *)nfs4_dot_entries;
2102 	odp->d_off = 1; /* magic cookie for "." entry */
2103 	odp->d_reclen = DIRENT64_RECLEN(1);
2104 	odp->d_name[0] = '.';
2105 	odp->d_name[1] = '\0';
2106 
2107 	nfs4_dot_dot_entry = nfs4_dot_entries + DIRENT64_RECLEN(1);
2108 	odp = (struct dirent64 *)nfs4_dot_dot_entry;
2109 
2110 	odp->d_off = 2;
2111 	odp->d_reclen = DIRENT64_RECLEN(2);
2112 	odp->d_name[0] = '.';
2113 	odp->d_name[1] = '.';
2114 	odp->d_name[2] = '\0';
2115 }
2116 
2117 void
2118 nfs4_destroy_dot_entries()
2119 {
2120 	if (nfs4_dot_entries)
2121 		kmem_free(nfs4_dot_entries, DIRENT64_RECLEN(1) +
2122 		    DIRENT64_RECLEN(2));
2123 
2124 	nfs4_dot_entries = nfs4_dot_dot_entry = NULL;
2125 }
2126 
2127 bool_t
2128 xdr_READDIR4res_clnt(XDR *xdrs, READDIR4res_clnt *objp, READDIR4args *aobjp)
2129 {
2130 	bool_t more_data;
2131 	rddir4_cache *rdc = aobjp->rdc;
2132 	dirent64_t *dp = NULL;
2133 	int entry_length = 0;
2134 	int space_left = 0;
2135 	bitmap4 resbmap;
2136 	uint32_t attrlen;
2137 	nfs4_ga_res_t gar;
2138 	struct nfs4_ga_ext_res ges;
2139 	uint64_t last_cookie = 0;
2140 	int skip_to_end;
2141 	ug_cache_t *pug = NULL;
2142 
2143 	ASSERT(xdrs->x_op == XDR_DECODE);
2144 	ASSERT(rdc->entries == NULL);
2145 	ASSERT(aobjp->dircount > 0);
2146 
2147 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2148 		return (FALSE);
2149 	if (objp->status != NFS4_OK)
2150 		return (TRUE);
2151 
2152 	gar.n4g_va.va_mask = 0;
2153 	gar.n4g_change_valid = 0;
2154 	gar.n4g_mon_fid_valid = 0;
2155 	gar.n4g_fsid_valid = 0;
2156 	gar.n4g_vsa.vsa_mask = 0;
2157 	gar.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2158 	ges.n4g_pc4.pc4_cache_valid = 0;
2159 	ges.n4g_pc4.pc4_xattr_valid = 0;
2160 	gar.n4g_ext_res = &ges;
2161 
2162 	/* READDIR4res_clnt_free needs to kmem_free this buffer */
2163 	rdc->entries = kmem_alloc(aobjp->dircount, KM_SLEEP);
2164 
2165 	dp = (dirent64_t *)rdc->entries;
2166 	rdc->entlen = rdc->buflen = space_left = aobjp->dircount;
2167 
2168 	/* Fill in dot and dot-dot if needed */
2169 	if (rdc->nfs4_cookie == (nfs_cookie4) 0 ||
2170 	    rdc->nfs4_cookie == (nfs_cookie4) 1) {
2171 
2172 		if (rdc->nfs4_cookie == (nfs_cookie4)0) {
2173 			bcopy(nfs4_dot_entries, rdc->entries,
2174 			    DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2175 			objp->dotp = dp;
2176 			dp = (struct dirent64 *)(((char *)dp) +
2177 			    DIRENT64_RECLEN(1));
2178 			objp->dotdotp = dp;
2179 			dp = (struct dirent64 *)(((char *)dp) +
2180 			    DIRENT64_RECLEN(2));
2181 			space_left -= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2182 
2183 		} else	{	/* for ".." entry */
2184 			bcopy(nfs4_dot_dot_entry, rdc->entries,
2185 			    DIRENT64_RECLEN(2));
2186 			objp->dotp = NULL;
2187 			objp->dotdotp = dp;
2188 			dp = (struct dirent64 *)(((char *)dp) +
2189 			    DIRENT64_RECLEN(2));
2190 			space_left -= DIRENT64_RECLEN(2);
2191 		}
2192 		/* Magic NFSv4 number for entry after start */
2193 		last_cookie = 2;
2194 	}
2195 
2196 	/* Get the cookie VERIFIER */
2197 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
2198 		goto noentries;
2199 
2200 	/* Get the do-we-have-a-next-entry BOOL */
2201 	if (!xdr_bool(xdrs, &more_data))
2202 		goto noentries;
2203 
2204 	if (aobjp->attr_request & (FATTR4_OWNER_MASK | FATTR4_OWNER_GROUP_MASK))
2205 		pug = alloc_ugcache();
2206 
2207 	skip_to_end = 0;
2208 	while (more_data) {
2209 		uint_t namelen;
2210 		uint64_t cookie;
2211 
2212 		/* Get the COOKIE */
2213 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&cookie))
2214 			goto noentries;
2215 
2216 		/* Get the LENGTH of the entry name */
2217 		if (!xdr_u_int(xdrs, &namelen))
2218 			goto noentries;
2219 
2220 		if (!skip_to_end) {
2221 			/*
2222 			 * With the length of the directory entry name
2223 			 * in hand, figure out if there is room left
2224 			 * to encode it for the requestor.  If not,
2225 			 * that is okay, but the rest of the readdir
2226 			 * operation result must be decoded in the
2227 			 * case there are following operations
2228 			 * in the compound request.  Therefore, mark
2229 			 * the rest of the response as "skip" and
2230 			 * decode or skip the remaining data
2231 			 */
2232 			entry_length = DIRENT64_RECLEN(namelen);
2233 			if (space_left < entry_length)
2234 				skip_to_end = 1;
2235 		}
2236 
2237 		/* Get the NAME of the entry */
2238 		if (!skip_to_end) {
2239 			if (!xdr_opaque(xdrs, dp->d_name, namelen))
2240 				goto noentries;
2241 			bzero(&dp->d_name[namelen],
2242 			    DIRENT64_NAMELEN(entry_length) - namelen);
2243 			dp->d_off = last_cookie = cookie;
2244 			dp->d_reclen = entry_length;
2245 		} else {
2246 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &namelen))
2247 				goto noentries;
2248 		}
2249 
2250 		/* Get the attribute BITMAP */
2251 		if (!xdr_bitmap4(xdrs, &resbmap))
2252 			goto noentries;
2253 		/* Get the LENGTH of the attributes */
2254 		if (!xdr_u_int(xdrs, (uint_t *)&attrlen))
2255 			goto noentries;
2256 
2257 		/* Get the ATTRIBUTES */
2258 		if (!skip_to_end) {
2259 			uint32_t *ptr;
2260 
2261 			if (!(resbmap & FATTR4_ACL_MASK) &&
2262 			    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen))
2263 			    != NULL) {
2264 				if (!xdr_ga_fattr_res_inline(ptr, &gar, resbmap,
2265 				    aobjp->attr_request, aobjp->mi, pug))
2266 					goto noentries;
2267 			} else {
2268 				if (!xdr_ga_fattr_res(xdrs, &gar, resbmap,
2269 				    aobjp->attr_request, aobjp->mi, pug))
2270 					goto noentries;
2271 			}
2272 
2273 			/* Fill in the d_ino per the server's fid values */
2274 			/*
2275 			 * Important to note that the mounted on fileid
2276 			 * is returned in d_ino if supported.  This is
2277 			 * expected, readdir returns the mounted on fileid
2278 			 * while stat() returns the fileid of the object
2279 			 * on "top" of the mount.
2280 			 */
2281 			if (gar.n4g_mon_fid_valid)
2282 				dp->d_ino = gar.n4g_mon_fid;
2283 			else if (gar.n4g_va.va_mask & AT_NODEID)
2284 				dp->d_ino = gar.n4g_va.va_nodeid;
2285 			else
2286 				dp->d_ino = 0;
2287 
2288 			/* See about creating an rnode for this entry */
2289 			if ((resbmap &
2290 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) ==
2291 			    (NFS4_VATTR_MASK | FATTR4_FILEHANDLE_MASK)) {
2292 				nfs4_sharedfh_t *sfhp;
2293 				vnode_t *vp;
2294 
2295 				sfhp = sfh4_put(&ges.n4g_fh_u.n4g_fh,
2296 				    aobjp->mi, NULL);
2297 				vp = makenfs4node(sfhp, &gar,
2298 				    aobjp->dvp->v_vfsp,
2299 				    aobjp->t,
2300 				    aobjp->cr,
2301 				    aobjp->dvp,
2302 				    fn_get(VTOSV(aobjp->dvp)->sv_name,
2303 				    dp->d_name, sfhp));
2304 				sfh4_rele(&sfhp);
2305 				dnlc_update(aobjp->dvp, dp->d_name, vp);
2306 				VN_RELE(vp);
2307 			}
2308 
2309 			dp = (struct dirent64 *)(((caddr_t)dp) + dp->d_reclen);
2310 
2311 			space_left -= entry_length;
2312 
2313 		} else {
2314 			if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &attrlen))
2315 				goto noentries;
2316 		}
2317 
2318 		/* Get the do-we-have-a-next-entry BOOL */
2319 		if (!xdr_bool(xdrs, &more_data))
2320 			goto noentries;
2321 	}
2322 
2323 	if (pug) {
2324 		kmem_free(pug, sizeof (ug_cache_t));
2325 		pug = NULL;
2326 	}
2327 
2328 	/*
2329 	 * Finish up the rddir cache
2330 	 * If no entries were returned, free up buffer &
2331 	 * set ncookie to the starting cookie for this
2332 	 * readdir request so that the direof caching
2333 	 * will work properly.
2334 	 */
2335 	ASSERT(rdc->entries);
2336 	if (last_cookie == 0) {
2337 		kmem_free(rdc->entries, rdc->entlen);
2338 		rdc->entries = NULL;
2339 		last_cookie = rdc->nfs4_cookie;
2340 	}
2341 
2342 	rdc->actlen = rdc->entlen - space_left;
2343 	rdc->nfs4_ncookie = last_cookie;
2344 
2345 	/* Get the EOF marker */
2346 	if (!xdr_bool(xdrs, &objp->eof))
2347 		goto noentries;
2348 
2349 	/*
2350 	 * If the server returns eof and there were no
2351 	 * skipped entries, set eof
2352 	 */
2353 	rdc->eof = (objp->eof && !skip_to_end) ? TRUE : FALSE;
2354 
2355 	/*
2356 	 * If we encoded entries we are done
2357 	 */
2358 	if (rdc->entries) {
2359 		rdc->error = 0;
2360 		return (TRUE);
2361 	}
2362 
2363 	/*
2364 	 * If there were no entries and we skipped because
2365 	 * there was not enough space, return EINVAL
2366 	 */
2367 	if (skip_to_end) {
2368 		rdc->error = EINVAL;
2369 		return (TRUE);
2370 	}
2371 
2372 	/*
2373 	 * No entries, nothing skipped, and EOF, return OK.
2374 	 */
2375 	if (objp->eof == TRUE) {
2376 		rdc->error = 0;
2377 		return (TRUE);
2378 	}
2379 
2380 	/*
2381 	 * No entries, nothing skipped, and not EOF
2382 	 * probably a bad cookie, return ENOENT.
2383 	 */
2384 	rdc->error = ENOENT;
2385 	return (TRUE);
2386 
2387 noentries:
2388 	if (rdc->entries) {
2389 		kmem_free(rdc->entries, rdc->entlen);
2390 		rdc->entries = NULL;
2391 	}
2392 	if (pug)
2393 		kmem_free(pug, sizeof (ug_cache_t));
2394 	rdc->error = EIO;
2395 	return (FALSE);
2396 }
2397 
2398 /*
2399  * xdr_ga_res
2400  *
2401  * Returns: FALSE on raw data processing errors, TRUE otherwise.
2402  *
2403  * This function pre-processes the OP_GETATTR response, and then
2404  * calls common routines to process the GETATTR fattr4 results into
2405  * vnode attributes and other components that the client is interested
2406  * in. If an error other than an RPC error is encountered, the details
2407  * of the error are filled into objp, although the result of the
2408  * processing is set to TRUE.
2409  */
2410 static bool_t
2411 xdr_ga_res(XDR *xdrs, GETATTR4res *objp, GETATTR4args *aobjp)
2412 {
2413 #ifdef INLINE
2414 	uint32_t *ptr;
2415 #endif
2416 	bitmap4 resbmap;
2417 	uint32_t attrlen;
2418 
2419 	ASSERT(xdrs->x_op == XDR_DECODE);
2420 
2421 	/* Initialize objp attribute error values */
2422 	objp->ga_res.n4g_attrerr =
2423 	    objp->ga_res.n4g_attrwhy = NFS4_GETATTR_OP_OK;
2424 
2425 	if (!xdr_bitmap4(xdrs, &resbmap))
2426 		return (FALSE);
2427 
2428 	/* save the response bitmap for the caller */
2429 	objp->ga_res.n4g_resbmap = resbmap;
2430 
2431 	/* attrlen */
2432 	if (!XDR_GETINT32(xdrs, (int32_t *)&attrlen))
2433 		return (FALSE);
2434 
2435 	/*
2436 	 * Handle case where request and response bitmaps don't match.
2437 	 */
2438 	if (aobjp->attr_request && aobjp->attr_request != resbmap) {
2439 		bitmap4 deltabmap;
2440 
2441 		/*
2442 		 * Return error for case where server sent extra attributes
2443 		 * because the "unknown" attributes may be anywhere in the
2444 		 * xdr stream and can't be properly processed.
2445 		 */
2446 		deltabmap = ((aobjp->attr_request ^ resbmap) & resbmap);
2447 		if (deltabmap) {
2448 			objp->ga_res.n4g_attrerr = EINVAL;
2449 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_BITMAP_ERR;
2450 			return (TRUE);
2451 		}
2452 
2453 		/*
2454 		 * Return error for case where there is a mandatory
2455 		 * attribute missing in the server response. Note that
2456 		 * missing recommended attributes are evaluated in the
2457 		 * specific routines that decode the server response.
2458 		 */
2459 		deltabmap = ((aobjp->attr_request ^ resbmap)
2460 		    & aobjp->attr_request);
2461 		if ((deltabmap & FATTR4_MANDATTR_MASK)) {
2462 			objp->ga_res.n4g_attrerr = EINVAL;
2463 			objp->ga_res.n4g_attrwhy = NFS4_GETATTR_MANDATTR_ERR;
2464 			return (TRUE);
2465 		}
2466 	}
2467 
2468 	/* Check to see if the attrs can be inlined and go for it if so */
2469 #ifdef INLINE
2470 	if (!(resbmap & FATTR4_ACL_MASK) &&
2471 	    (ptr = (uint32_t *)XDR_INLINE(xdrs, attrlen)) != NULL)
2472 		return (xdr_ga_fattr_res_inline(ptr, &objp->ga_res,
2473 		    resbmap, aobjp->attr_request, aobjp->mi, NULL));
2474 	else
2475 #endif
2476 		return (xdr_ga_fattr_res(xdrs, &objp->ga_res,
2477 		    resbmap, aobjp->attr_request, aobjp->mi, NULL));
2478 }
2479 
2480 #if defined(DEBUG) && !defined(lint)
2481 /*
2482  * We assume that an enum is a 32-bit value, check it once
2483  */
2484 static enum szchk { SZVAL } szchkvar;
2485 #endif
2486 
2487 bool_t
2488 xdr_settime4(XDR *xdrs, settime4 *objp)
2489 {
2490 #if defined(DEBUG) && !defined(lint)
2491 	ASSERT(sizeof (szchkvar) == sizeof (int32_t));
2492 #endif
2493 	if (xdrs->x_op == XDR_FREE)
2494 		return (TRUE);
2495 
2496 	if (!xdr_int(xdrs, (int *)&objp->set_it))
2497 		return (FALSE);
2498 	if (objp->set_it != SET_TO_CLIENT_TIME4)
2499 		return (TRUE);
2500 	/* xdr_nfstime4 */
2501 	if (!xdr_longlong_t(xdrs, (longlong_t *)&objp->time.seconds))
2502 		return (FALSE);
2503 	return (xdr_u_int(xdrs, &objp->time.nseconds));
2504 }
2505 
2506 static bool_t
2507 xdr_fattr4(XDR *xdrs, fattr4 *objp)
2508 {
2509 	if (xdrs->x_op != XDR_FREE) {
2510 		if (!xdr_bitmap4(xdrs, &objp->attrmask))
2511 			return (FALSE);
2512 		return (xdr_bytes(xdrs, (char **)&objp->attrlist4,
2513 		    (uint_t *)&objp->attrlist4_len, NFS4_FATTR4_LIMIT));
2514 	}
2515 
2516 	/*
2517 	 * Optimized free case
2518 	 */
2519 	if (objp->attrlist4 != NULL)
2520 		kmem_free(objp->attrlist4, objp->attrlist4_len);
2521 	return (TRUE);
2522 }
2523 
2524 static bool_t
2525 xdr_ACCESS4res(XDR *xdrs, ACCESS4res *objp)
2526 {
2527 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2528 		return (FALSE);
2529 	if (objp->status != NFS4_OK)
2530 		return (TRUE);
2531 	if (!xdr_u_int(xdrs, &objp->supported))
2532 		return (FALSE);
2533 	return (xdr_u_int(xdrs, &objp->access));
2534 }
2535 
2536 static bool_t
2537 xdr_CLOSE4args(XDR *xdrs, CLOSE4args *objp)
2538 {
2539 	if (!xdr_u_int(xdrs, &objp->seqid))
2540 		return (FALSE);
2541 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2542 		return (FALSE);
2543 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
2544 }
2545 
2546 static bool_t
2547 xdr_CLOSE4res(XDR *xdrs, CLOSE4res *objp)
2548 {
2549 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2550 		return (FALSE);
2551 	if (objp->status != NFS4_OK)
2552 		return (TRUE);
2553 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
2554 		return (FALSE);
2555 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
2556 }
2557 
2558 static bool_t
2559 xdr_CREATE4args(XDR *xdrs, CREATE4args *objp)
2560 {
2561 	if (xdrs->x_op != XDR_FREE) {
2562 		if (!xdr_int(xdrs, (int32_t *)&objp->type))
2563 			return (FALSE);
2564 		switch (objp->type) {
2565 		case NF4LNK:
2566 			if (!xdr_bytes(xdrs,
2567 			    (char **)&objp->ftype4_u.linkdata.utf8string_val,
2568 			    (uint_t *)&objp->ftype4_u.linkdata.utf8string_len,
2569 			    NFS4_MAX_UTF8STRING))
2570 				return (FALSE);
2571 			break;
2572 		case NF4BLK:
2573 		case NF4CHR:
2574 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata1))
2575 				return (FALSE);
2576 			if (!xdr_u_int(xdrs, &objp->ftype4_u.devdata.specdata2))
2577 				return (FALSE);
2578 			break;
2579 		case NF4SOCK:
2580 		case NF4FIFO:
2581 		case NF4DIR:
2582 		default:
2583 			break;	/* server should return NFS4ERR_BADTYPE */
2584 		}
2585 		if (!xdr_bytes(xdrs, (char **)&objp->objname.utf8string_val,
2586 		    (uint_t *)&objp->objname.utf8string_len,
2587 		    NFS4_MAX_UTF8STRING))
2588 			return (FALSE);
2589 		return (xdr_fattr4(xdrs, &objp->createattrs));
2590 	}
2591 
2592 	/*
2593 	 * Optimized free case
2594 	 */
2595 	if (objp->type == NF4LNK) {
2596 		if (objp->ftype4_u.linkdata.utf8string_val != NULL)
2597 			kmem_free(objp->ftype4_u.linkdata.utf8string_val,
2598 			    objp->ftype4_u.linkdata.utf8string_len);
2599 	}
2600 	if (objp->objname.utf8string_val != NULL)
2601 		kmem_free(objp->objname.utf8string_val,
2602 		    objp->objname.utf8string_len);
2603 	return (xdr_fattr4(xdrs, &objp->createattrs));
2604 }
2605 
2606 static bool_t
2607 xdr_CREATE4cargs(XDR *xdrs, CREATE4cargs *objp)
2608 {
2609 	int len;
2610 
2611 	ASSERT(xdrs->x_op == XDR_ENCODE);
2612 
2613 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->type))
2614 		return (FALSE);
2615 	switch (objp->type) {
2616 	case NF4LNK:
2617 		len = strlen(objp->ftype4_u.clinkdata);
2618 		if (len > NFS4_MAX_UTF8STRING)
2619 			return (FALSE);
2620 		if (!XDR_PUTINT32(xdrs, &len))
2621 			return (FALSE);
2622 		if (!xdr_opaque(xdrs, objp->ftype4_u.clinkdata, len))
2623 			return (FALSE);
2624 		break;
2625 	case NF4BLK:
2626 	case NF4CHR:
2627 		if (!XDR_PUTINT32(xdrs,
2628 		    (int32_t *)&objp->ftype4_u.devdata.specdata1))
2629 			return (FALSE);
2630 		if (!XDR_PUTINT32(xdrs,
2631 		    (int32_t *)&objp->ftype4_u.devdata.specdata2))
2632 			return (FALSE);
2633 		break;
2634 	case NF4SOCK:
2635 	case NF4FIFO:
2636 	case NF4DIR:
2637 	default:
2638 		break;	/* server should return NFS4ERR_BADTYPE */
2639 	}
2640 
2641 	len = strlen(objp->cname);
2642 	if (len > NFS4_MAX_UTF8STRING)
2643 		return (FALSE);
2644 	if (!XDR_PUTINT32(xdrs, &len))
2645 		return (FALSE);
2646 	if (!xdr_opaque(xdrs, objp->cname, len))
2647 		return (FALSE);
2648 
2649 	return (xdr_fattr4(xdrs, &objp->createattrs));
2650 }
2651 
2652 static bool_t
2653 xdr_CREATE4res(XDR *xdrs, CREATE4res *objp)
2654 {
2655 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2656 		return (FALSE);
2657 	if (objp->status != NFS4_OK)
2658 		return (TRUE);
2659 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2660 		return (FALSE);
2661 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2662 		return (FALSE);
2663 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
2664 		return (FALSE);
2665 	return (xdr_bitmap4(xdrs, &objp->attrset));
2666 }
2667 
2668 static bool_t
2669 xdr_LINK4res(XDR *xdrs, LINK4res *objp)
2670 {
2671 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
2672 		return (FALSE);
2673 	if (objp->status != NFS4_OK)
2674 		return (TRUE);
2675 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
2676 		return (FALSE);
2677 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
2678 		return (FALSE);
2679 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after));
2680 }
2681 
2682 static bool_t
2683 xdr_LOCK4args(XDR *xdrs, LOCK4args *objp)
2684 {
2685 	if (xdrs->x_op != XDR_FREE) {
2686 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2687 			return (FALSE);
2688 		if (!xdr_bool(xdrs, &objp->reclaim))
2689 			return (FALSE);
2690 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2691 			return (FALSE);
2692 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2693 			return (FALSE);
2694 		if (!xdr_bool(xdrs, &objp->locker.new_lock_owner))
2695 			return (FALSE);
2696 		if (objp->locker.new_lock_owner == TRUE) {
2697 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2698 			    open_seqid))
2699 				return (FALSE);
2700 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2701 			    open_stateid.seqid))
2702 				return (FALSE);
2703 			if (!xdr_opaque(xdrs, objp->locker.locker4_u.open_owner.
2704 			    open_stateid.other, 12))
2705 				return (FALSE);
2706 			if (!xdr_u_int(xdrs, &objp->locker.locker4_u.open_owner.
2707 			    lock_seqid))
2708 				return (FALSE);
2709 			if (!xdr_u_longlong_t(xdrs,
2710 			    (u_longlong_t *)&objp->locker.locker4_u.
2711 			    open_owner.lock_owner.clientid))
2712 				return (FALSE);
2713 			return (xdr_bytes(xdrs,
2714 			    (char **)&objp->locker.locker4_u.open_owner.
2715 			    lock_owner.owner_val,
2716 			    (uint_t *)&objp->locker.locker4_u.open_owner.
2717 			    lock_owner.owner_len,
2718 			    NFS4_OPAQUE_LIMIT));
2719 		}
2720 
2721 		if (objp->locker.new_lock_owner != FALSE)
2722 			return (FALSE);
2723 
2724 		if (!xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2725 		    lock_stateid.seqid))
2726 			return (FALSE);
2727 		if (!xdr_opaque(xdrs, objp->locker.locker4_u.lock_owner.
2728 		    lock_stateid.other, 12))
2729 			return (FALSE);
2730 		return (xdr_u_int(xdrs, &objp->locker.locker4_u.lock_owner.
2731 		    lock_seqid));
2732 	}
2733 
2734 	/*
2735 	 * Optimized free case
2736 	 */
2737 	if (objp->locker.new_lock_owner == TRUE) {
2738 		if (objp->locker.locker4_u.open_owner.lock_owner.owner_val !=
2739 		    NULL) {
2740 			kmem_free(objp->locker.locker4_u.open_owner.lock_owner.
2741 			    owner_val,
2742 			    objp->locker.locker4_u.open_owner.lock_owner.
2743 			    owner_len);
2744 		}
2745 	}
2746 
2747 	return (TRUE);
2748 }
2749 
2750 static bool_t
2751 xdr_LOCK4res(XDR *xdrs, LOCK4res *objp)
2752 {
2753 	if (xdrs->x_op != XDR_FREE) {
2754 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2755 			return (FALSE);
2756 		if (objp->status == NFS4_OK) {
2757 			if (!xdr_u_int(xdrs,
2758 			    &objp->LOCK4res_u.lock_stateid.seqid))
2759 				return (FALSE);
2760 			return (xdr_opaque(xdrs,
2761 			    objp->LOCK4res_u.lock_stateid.other, 12));
2762 		}
2763 		if (objp->status != NFS4ERR_DENIED)
2764 			return (TRUE);
2765 
2766 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2767 		    denied.offset))
2768 			return (FALSE);
2769 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2770 		    denied.length))
2771 			return (FALSE);
2772 		if (!xdr_int(xdrs, (int *)&objp->LOCK4res_u.denied.locktype))
2773 			return (FALSE);
2774 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->LOCK4res_u.
2775 		    denied.owner.clientid))
2776 			return (FALSE);
2777 		return (xdr_bytes(xdrs,
2778 		    (char **)&objp->LOCK4res_u.denied.owner.owner_val,
2779 		    (uint_t *)&objp->LOCK4res_u.denied.owner.owner_len,
2780 		    NFS4_OPAQUE_LIMIT));
2781 	}
2782 
2783 	/*
2784 	 * Optimized free case
2785 	 */
2786 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2787 		return (TRUE);
2788 
2789 	if (objp->LOCK4res_u.denied.owner.owner_val != NULL)
2790 		kmem_free(objp->LOCK4res_u.denied.owner.owner_val,
2791 		    objp->LOCK4res_u.denied.owner.owner_len);
2792 	return (TRUE);
2793 }
2794 
2795 static bool_t
2796 xdr_LOCKT4args(XDR *xdrs, LOCKT4args *objp)
2797 {
2798 	if (xdrs->x_op != XDR_FREE) {
2799 		if (!xdr_int(xdrs, (int *)&objp->locktype))
2800 			return (FALSE);
2801 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2802 			return (FALSE);
2803 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length))
2804 			return (FALSE);
2805 		if (!xdr_u_longlong_t(xdrs,
2806 		    (u_longlong_t *)&objp->owner.clientid))
2807 			return (FALSE);
2808 		return (xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2809 		    (uint_t *)&objp->owner.owner_len,
2810 		    NFS4_OPAQUE_LIMIT));
2811 	}
2812 
2813 	/*
2814 	 * Optimized free case
2815 	 */
2816 	if (objp->owner.owner_val != NULL)
2817 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2818 	return (TRUE);
2819 }
2820 
2821 static bool_t
2822 xdr_LOCKT4res(XDR *xdrs, LOCKT4res *objp)
2823 {
2824 	if (xdrs->x_op != XDR_FREE) {
2825 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
2826 			return (FALSE);
2827 		if (objp->status == NFS4_OK)
2828 			return (TRUE);
2829 		if (objp->status != NFS4ERR_DENIED)
2830 			return (TRUE);
2831 		/* xdr_LOCK4denied */
2832 		if (!xdr_u_longlong_t(xdrs,
2833 		    (u_longlong_t *)&objp->denied.offset))
2834 			return (FALSE);
2835 		if (!xdr_u_longlong_t(xdrs,
2836 		    (u_longlong_t *)&objp->denied.length))
2837 			return (FALSE);
2838 		if (!xdr_int(xdrs, (int *)&objp->denied.locktype))
2839 			return (FALSE);
2840 		if (!xdr_u_longlong_t(xdrs,
2841 		    (u_longlong_t *)&objp->denied.owner.clientid))
2842 			return (FALSE);
2843 		return (xdr_bytes(xdrs,
2844 		    (char **)&objp->denied.owner.owner_val,
2845 		    (uint_t *)&objp->denied.owner.owner_len,
2846 		    NFS4_OPAQUE_LIMIT));
2847 	}
2848 
2849 	/*
2850 	 * Optimized free case
2851 	 */
2852 	if (objp->status == NFS4_OK || objp->status != NFS4ERR_DENIED)
2853 		return (TRUE);
2854 	if (objp->denied.owner.owner_val != NULL)
2855 		kmem_free(objp->denied.owner.owner_val,
2856 		    objp->denied.owner.owner_len);
2857 	return (TRUE);
2858 }
2859 
2860 static bool_t
2861 xdr_LOCKU4args(XDR *xdrs, LOCKU4args *objp)
2862 {
2863 	if (!xdr_int(xdrs, (int *)&objp->locktype))
2864 		return (FALSE);
2865 	if (!xdr_u_int(xdrs, &objp->seqid))
2866 		return (FALSE);
2867 	if (!xdr_u_int(xdrs, &objp->lock_stateid.seqid))
2868 		return (FALSE);
2869 	if (!xdr_opaque(xdrs, objp->lock_stateid.other, 12))
2870 		return (FALSE);
2871 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
2872 		return (FALSE);
2873 	return (xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->length));
2874 }
2875 
2876 static bool_t
2877 xdr_OPEN4args(XDR *xdrs, OPEN4args *objp)
2878 {
2879 	if (xdrs->x_op != XDR_FREE) {
2880 		if (!xdr_u_int(xdrs, &objp->seqid))
2881 			return (FALSE);
2882 		if (!xdr_u_int(xdrs, &objp->share_access))
2883 			return (FALSE);
2884 		if (!xdr_u_int(xdrs, &objp->share_deny))
2885 			return (FALSE);
2886 
2887 		/* xdr_open_owner4 */
2888 		if (!xdr_u_longlong_t(xdrs,
2889 		    (u_longlong_t *)&objp->owner.clientid))
2890 			return (FALSE);
2891 		if (!xdr_bytes(xdrs, (char **)&objp->owner.owner_val,
2892 		    (uint_t *)&objp->owner.owner_len,
2893 		    NFS4_OPAQUE_LIMIT))
2894 			return (FALSE);
2895 
2896 		/* xdr_openflag4 */
2897 		if (!xdr_int(xdrs, (int *)&objp->opentype))
2898 			return (FALSE);
2899 		if (objp->opentype == OPEN4_CREATE) {
2900 
2901 			/* xdr_createhow4 */
2902 			if (!xdr_int(xdrs, (int *)&objp->mode))
2903 				return (FALSE);
2904 			switch (objp->mode) {
2905 			case UNCHECKED4:
2906 			case GUARDED4:
2907 				if (!xdr_fattr4(xdrs,
2908 				    &objp->createhow4_u.createattrs))
2909 					return (FALSE);
2910 				break;
2911 			case EXCLUSIVE4:
2912 				if (!xdr_u_longlong_t(xdrs,
2913 				    (u_longlong_t *)&objp->createhow4_u.
2914 				    createverf))
2915 					return (FALSE);
2916 				break;
2917 			default:
2918 				return (FALSE);
2919 			}
2920 		}
2921 
2922 		/* xdr_open_claim4 */
2923 		if (!xdr_int(xdrs, (int *)&objp->claim))
2924 			return (FALSE);
2925 
2926 		switch (objp->claim) {
2927 		case CLAIM_NULL:
2928 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2929 			    file.utf8string_val,
2930 			    (uint_t *)&objp->open_claim4_u.file.
2931 			    utf8string_len,
2932 			    NFS4_MAX_UTF8STRING));
2933 		case CLAIM_PREVIOUS:
2934 			return (xdr_int(xdrs,
2935 			    (int *)&objp->open_claim4_u.delegate_type));
2936 		case CLAIM_DELEGATE_CUR:
2937 			if (!xdr_u_int(xdrs, (uint_t *)&objp->open_claim4_u.
2938 			    delegate_cur_info.delegate_stateid.seqid))
2939 				return (FALSE);
2940 			if (!xdr_opaque(xdrs, objp->open_claim4_u.
2941 			    delegate_cur_info.delegate_stateid.other,
2942 			    12))
2943 				return (FALSE);
2944 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2945 			    delegate_cur_info.file.utf8string_val,
2946 			    (uint_t *)&objp->open_claim4_u.
2947 			    delegate_cur_info.file.utf8string_len,
2948 			    NFS4_MAX_UTF8STRING));
2949 		case CLAIM_DELEGATE_PREV:
2950 			return (xdr_bytes(xdrs, (char **)&objp->open_claim4_u.
2951 			    file_delegate_prev.utf8string_val,
2952 			    (uint_t *)&objp->open_claim4_u.
2953 			    file_delegate_prev.utf8string_len,
2954 			    NFS4_MAX_UTF8STRING));
2955 		default:
2956 			return (FALSE);
2957 		}
2958 	}
2959 
2960 	/*
2961 	 * Optimized free case
2962 	 */
2963 	if (objp->owner.owner_val != NULL)
2964 		kmem_free(objp->owner.owner_val, objp->owner.owner_len);
2965 
2966 	if (objp->opentype == OPEN4_CREATE) {
2967 		switch (objp->mode) {
2968 		case UNCHECKED4:
2969 		case GUARDED4:
2970 			(void) xdr_fattr4(xdrs,
2971 			    &objp->createhow4_u.createattrs);
2972 			break;
2973 		case EXCLUSIVE4:
2974 		default:
2975 			break;
2976 		}
2977 	}
2978 
2979 	switch (objp->claim) {
2980 	case CLAIM_NULL:
2981 		if (objp->open_claim4_u.file.utf8string_val != NULL)
2982 			kmem_free(objp->open_claim4_u.file.utf8string_val,
2983 			    objp->open_claim4_u.file.utf8string_len);
2984 		return (TRUE);
2985 	case CLAIM_PREVIOUS:
2986 		return (TRUE);
2987 	case CLAIM_DELEGATE_CUR:
2988 		if (objp->open_claim4_u.delegate_cur_info.file.utf8string_val !=
2989 		    NULL) {
2990 			kmem_free(objp->open_claim4_u.delegate_cur_info.file.
2991 			    utf8string_val,
2992 			    objp->open_claim4_u.delegate_cur_info.file.
2993 			    utf8string_len);
2994 		}
2995 		return (TRUE);
2996 	case CLAIM_DELEGATE_PREV:
2997 		if (objp->open_claim4_u.file_delegate_prev.utf8string_val !=
2998 		    NULL) {
2999 			kmem_free(objp->open_claim4_u.file_delegate_prev.
3000 			    utf8string_val,
3001 			    objp->open_claim4_u.file_delegate_prev.
3002 			    utf8string_len);
3003 		}
3004 		return (TRUE);
3005 	default:
3006 		return (TRUE);
3007 	}
3008 }
3009 
3010 static bool_t
3011 xdr_OPEN4cargs(XDR *xdrs, OPEN4cargs *objp)
3012 {
3013 	int op;
3014 	int len;
3015 	rpc_inline_t *ptr;
3016 
3017 	ASSERT(xdrs->x_op == XDR_ENCODE);
3018 
3019 	/*
3020 	 * We must always define the client's open_owner to be
3021 	 * 4 byte aligned and sized.
3022 	 */
3023 	ASSERT(objp->owner.owner_len <= NFS4_OPAQUE_LIMIT);
3024 	ASSERT(!(objp->owner.owner_len % BYTES_PER_XDR_UNIT));
3025 
3026 	len = objp->owner.owner_len;
3027 	if ((ptr = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + len)) != NULL) {
3028 		int i;
3029 		int32_t *ip;
3030 
3031 		IXDR_PUT_U_INT32(ptr, OP_OPEN);
3032 		IXDR_PUT_U_INT32(ptr, objp->seqid);
3033 		IXDR_PUT_U_INT32(ptr, objp->share_access);
3034 		IXDR_PUT_U_INT32(ptr, objp->share_deny);
3035 
3036 		/* xdr_open_owner4 */
3037 		IXDR_PUT_HYPER(ptr, objp->owner.clientid);
3038 		IXDR_PUT_U_INT32(ptr, objp->owner.owner_len);
3039 		/* We know this is very short so don't bcopy */
3040 		ip = (int32_t *)objp->owner.owner_val;
3041 		len /= BYTES_PER_XDR_UNIT;
3042 		for (i = 0; i < len; i++)
3043 			*ptr++ = *ip++;
3044 
3045 		/* xdr_openflag4 */
3046 		IXDR_PUT_U_INT32(ptr, objp->opentype);
3047 	} else {
3048 		op = OP_OPEN;
3049 		if (!XDR_PUTINT32(xdrs, (int32_t *)&op))
3050 			return (FALSE);
3051 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->seqid))
3052 			return (FALSE);
3053 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_access))
3054 			return (FALSE);
3055 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->share_deny))
3056 			return (FALSE);
3057 
3058 		/* xdr_open_owner4 */
3059 		if (!xdr_u_longlong_t(xdrs,
3060 		    (u_longlong_t *)&objp->owner.clientid))
3061 			return (FALSE);
3062 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->owner.owner_len))
3063 			return (FALSE);
3064 		if (!xdr_opaque(xdrs, objp->owner.owner_val,
3065 		    objp->owner.owner_len))
3066 			return (FALSE);
3067 
3068 		/* xdr_openflag4 */
3069 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->opentype))
3070 			return (FALSE);
3071 	}
3072 
3073 	if (objp->opentype == OPEN4_CREATE) {
3074 		/* xdr_createhow4 */
3075 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->mode))
3076 			return (FALSE);
3077 		switch (objp->mode) {
3078 		case UNCHECKED4:
3079 		case GUARDED4:
3080 			if (!xdr_fattr4(xdrs,
3081 			    &objp->createhow4_u.createattrs))
3082 				return (FALSE);
3083 			break;
3084 		case EXCLUSIVE4:
3085 			if (!xdr_u_longlong_t(xdrs,
3086 			    (u_longlong_t *)&objp->createhow4_u.
3087 			    createverf))
3088 				return (FALSE);
3089 			break;
3090 		default:
3091 			return (FALSE);
3092 		}
3093 	}
3094 
3095 	/* xdr_open_claim4 */
3096 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->claim))
3097 		return (FALSE);
3098 
3099 	switch (objp->claim) {
3100 	case CLAIM_NULL:
3101 		len = strlen(objp->open_claim4_u.cfile);
3102 		if (len > NFS4_MAX_UTF8STRING)
3103 			return (FALSE);
3104 		if (XDR_PUTINT32(xdrs, &len)) {
3105 			return (xdr_opaque(xdrs,
3106 			    objp->open_claim4_u.cfile, len));
3107 		}
3108 		return (FALSE);
3109 	case CLAIM_PREVIOUS:
3110 		return (XDR_PUTINT32(xdrs,
3111 		    (int32_t *)&objp->open_claim4_u.delegate_type));
3112 	case CLAIM_DELEGATE_CUR:
3113 		if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->open_claim4_u.
3114 		    delegate_cur_info.delegate_stateid.seqid))
3115 			return (FALSE);
3116 		if (!xdr_opaque(xdrs, objp->open_claim4_u.
3117 		    delegate_cur_info.delegate_stateid.other,
3118 		    12))
3119 			return (FALSE);
3120 		len = strlen(objp->open_claim4_u.delegate_cur_info.cfile);
3121 		if (len > NFS4_MAX_UTF8STRING)
3122 			return (FALSE);
3123 		if (XDR_PUTINT32(xdrs, &len)) {
3124 			return (xdr_opaque(xdrs,
3125 			    objp->open_claim4_u.delegate_cur_info.cfile,
3126 			    len));
3127 		}
3128 		return (FALSE);
3129 	case CLAIM_DELEGATE_PREV:
3130 		len = strlen(objp->open_claim4_u.cfile_delegate_prev);
3131 		if (len > NFS4_MAX_UTF8STRING)
3132 			return (FALSE);
3133 		if (XDR_PUTINT32(xdrs, &len)) {
3134 			return (xdr_opaque(xdrs,
3135 			    objp->open_claim4_u.cfile_delegate_prev, len));
3136 		}
3137 		return (FALSE);
3138 	default:
3139 		return (FALSE);
3140 	}
3141 }
3142 
3143 static bool_t
3144 xdr_OPEN4res(XDR *xdrs, OPEN4res *objp)
3145 {
3146 	if (xdrs->x_op != XDR_FREE) {
3147 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3148 			return (FALSE);
3149 		if (objp->status != NFS4_OK)
3150 			return (TRUE);
3151 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3152 			return (FALSE);
3153 		if (!xdr_opaque(xdrs, objp->stateid.other, 12))
3154 			return (FALSE);
3155 		if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3156 			return (FALSE);
3157 		if (!xdr_u_longlong_t(xdrs,
3158 		    (u_longlong_t *)&objp->cinfo.before))
3159 			return (FALSE);
3160 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.after))
3161 			return (FALSE);
3162 		if (!xdr_u_int(xdrs, &objp->rflags))
3163 			return (FALSE);
3164 		if (!xdr_bitmap4(xdrs, &objp->attrset))
3165 			return (FALSE);
3166 		if (!xdr_int(xdrs,
3167 		    (int *)&objp->delegation.delegation_type))
3168 			return (FALSE);
3169 		switch (objp->delegation.delegation_type) {
3170 		case OPEN_DELEGATE_NONE:
3171 			return (TRUE);
3172 		case OPEN_DELEGATE_READ:
3173 			if (!xdr_u_int(xdrs, &objp->delegation.
3174 			    open_delegation4_u.read.stateid.seqid))
3175 				return (FALSE);
3176 			if (!xdr_opaque(xdrs, objp->delegation.
3177 			    open_delegation4_u.read.stateid.other,
3178 			    12))
3179 				return (FALSE);
3180 			if (!xdr_bool(xdrs, &objp->delegation.
3181 			    open_delegation4_u.read.recall))
3182 				return (FALSE);
3183 			return (xdr_nfsace4(xdrs, &objp->delegation.
3184 			    open_delegation4_u.read.permissions));
3185 		case OPEN_DELEGATE_WRITE:
3186 			if (!xdr_u_int(xdrs, &objp->delegation.
3187 			    open_delegation4_u.write.stateid.seqid))
3188 				return (FALSE);
3189 			if (!xdr_opaque(xdrs, objp->delegation.
3190 			    open_delegation4_u.write.stateid.other,
3191 			    12))
3192 				return (FALSE);
3193 			if (!xdr_bool(xdrs, &objp->delegation.
3194 			    open_delegation4_u.write.recall))
3195 				return (FALSE);
3196 			if (!xdr_int(xdrs, (int *)&objp->delegation.
3197 			    open_delegation4_u.write.space_limit.
3198 			    limitby))
3199 				return (FALSE);
3200 			switch (objp->delegation.
3201 			    open_delegation4_u.write.space_limit.
3202 			    limitby) {
3203 			case NFS_LIMIT_SIZE:
3204 				if (!xdr_u_longlong_t(xdrs,
3205 				    (u_longlong_t *)&objp->delegation.
3206 				    open_delegation4_u.write.space_limit.
3207 				    nfs_space_limit4_u.filesize))
3208 					return (FALSE);
3209 				break;
3210 			case NFS_LIMIT_BLOCKS:
3211 				if (!xdr_u_int(xdrs,
3212 				    &objp->delegation.open_delegation4_u.write.
3213 				    space_limit.nfs_space_limit4_u.
3214 				    mod_blocks.num_blocks))
3215 					return (FALSE);
3216 				if (!xdr_u_int(xdrs, &objp->delegation.
3217 				    open_delegation4_u.write.space_limit.
3218 				    nfs_space_limit4_u.mod_blocks.
3219 				    bytes_per_block))
3220 					return (FALSE);
3221 				break;
3222 			default:
3223 				return (FALSE);
3224 			}
3225 			return (xdr_nfsace4(xdrs, &objp->delegation.
3226 			    open_delegation4_u.write.permissions));
3227 		}
3228 		return (FALSE);
3229 	}
3230 
3231 	/*
3232 	 * Optimized free case
3233 	 */
3234 	if (objp->status != NFS4_OK)
3235 		return (TRUE);
3236 
3237 	switch (objp->delegation.delegation_type) {
3238 	case OPEN_DELEGATE_NONE:
3239 		return (TRUE);
3240 	case OPEN_DELEGATE_READ:
3241 		return (xdr_nfsace4(xdrs, &objp->delegation.
3242 		    open_delegation4_u.read.permissions));
3243 	case OPEN_DELEGATE_WRITE:
3244 		switch (objp->delegation.
3245 		    open_delegation4_u.write.space_limit.limitby) {
3246 		case NFS_LIMIT_SIZE:
3247 		case NFS_LIMIT_BLOCKS:
3248 			break;
3249 		default:
3250 			return (FALSE);
3251 		}
3252 		return (xdr_nfsace4(xdrs, &objp->delegation.
3253 		    open_delegation4_u.write.permissions));
3254 	}
3255 	return (FALSE);
3256 }
3257 
3258 static bool_t
3259 xdr_OPEN_CONFIRM4res(XDR *xdrs, OPEN_CONFIRM4res *objp)
3260 {
3261 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3262 		return (FALSE);
3263 	if (objp->status != NFS4_OK)
3264 		return (TRUE);
3265 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3266 		return (FALSE);
3267 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
3268 }
3269 
3270 static bool_t
3271 xdr_OPEN_DOWNGRADE4args(XDR *xdrs, OPEN_DOWNGRADE4args *objp)
3272 {
3273 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3274 		return (FALSE);
3275 	if (!xdr_opaque(xdrs, objp->open_stateid.other, 12))
3276 		return (FALSE);
3277 	if (!xdr_u_int(xdrs, &objp->seqid))
3278 		return (FALSE);
3279 	if (!xdr_u_int(xdrs, &objp->share_access))
3280 		return (FALSE);
3281 	return (xdr_u_int(xdrs, &objp->share_deny));
3282 }
3283 
3284 static bool_t
3285 xdr_OPEN_DOWNGRADE4res(XDR *xdrs, OPEN_DOWNGRADE4res *objp)
3286 {
3287 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3288 		return (FALSE);
3289 	if (objp->status != NFS4_OK)
3290 		return (TRUE);
3291 	if (!xdr_u_int(xdrs, &objp->open_stateid.seqid))
3292 		return (FALSE);
3293 	return (xdr_opaque(xdrs, objp->open_stateid.other, 12));
3294 }
3295 
3296 static bool_t
3297 xdr_READ4args(XDR *xdrs, READ4args *objp)
3298 {
3299 	rdma_chunkinfo_t rci;
3300 	rdma_wlist_conn_info_t rwci;
3301 	struct xdr_ops *xops = xdrrdma_xops();
3302 
3303 	if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3304 		return (FALSE);
3305 	if (!xdr_opaque(xdrs, objp->stateid.other, 12))
3306 		return (FALSE);
3307 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3308 		return (FALSE);
3309 	if (!xdr_u_int(xdrs, &objp->count))
3310 		return (FALSE);
3311 
3312 	DTRACE_PROBE1(xdr__i__read4args_buf_len,
3313 	    int, objp->count);
3314 
3315 	objp->wlist = NULL;
3316 
3317 	if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
3318 		rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3319 		rci.rci_len = objp->count;
3320 		(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3321 	}
3322 
3323 	if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
3324 		return (TRUE);
3325 
3326 	if (xdrs->x_op == XDR_ENCODE) {
3327 		if (objp->res_uiop != NULL) {
3328 			rci.rci_type = RCI_WRITE_UIO_CHUNK;
3329 			rci.rci_a.rci_uiop = objp->res_uiop;
3330 			rci.rci_len = objp->count;
3331 			rci.rci_clpp = &objp->wlist;
3332 		} else {
3333 			rci.rci_type = RCI_WRITE_ADDR_CHUNK;
3334 			rci.rci_a.rci_addr = objp->res_data_val_alt;
3335 			rci.rci_len = objp->count;
3336 			rci.rci_clpp = &objp->wlist;
3337 		}
3338 
3339 		return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
3340 	}
3341 
3342 	/* XDR_DECODE case */
3343 	(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
3344 	objp->wlist = rwci.rwci_wlist;
3345 	objp->conn = rwci.rwci_conn;
3346 
3347 	return (TRUE);
3348 }
3349 
3350 static bool_t
3351 xdr_READ4res(XDR *xdrs, READ4res *objp)
3352 {
3353 	mblk_t *mp;
3354 
3355 	if (xdrs->x_op == XDR_DECODE)
3356 		return (FALSE);
3357 
3358 	if (xdrs->x_op == XDR_FREE) {
3359 		/*
3360 		 * Optimized free case
3361 		 */
3362 		if (objp->status != NFS4_OK)
3363 			return (TRUE);
3364 		if (objp->data_val != NULL)
3365 			kmem_free(objp->data_val, objp->data_len);
3366 		return (TRUE);
3367 	}
3368 
3369 	/* on with ENCODE paths */
3370 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->status))
3371 		return (FALSE);
3372 	if (objp->status != NFS4_OK)
3373 		return (TRUE);
3374 
3375 	if (!XDR_PUTINT32(xdrs, &objp->eof))
3376 		return (FALSE);
3377 
3378 	mp = objp->mblk;
3379 	if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
3380 		if (xdrmblk_putmblk(xdrs, mp, objp->data_len) == TRUE) {
3381 			objp->mblk = NULL;
3382 			return (TRUE);
3383 		}
3384 	} else if (mp == NULL) {
3385 		if (xdr_u_int(xdrs, &objp->data_len) == FALSE) {
3386 			return (FALSE);
3387 		}
3388 		/*
3389 		 * If read data sent by wlist (RDMA_WRITE), don't do
3390 		 * xdr_bytes() below.   RDMA_WRITE transfers the data.
3391 		 * Note: this is encode-only because the client code
3392 		 * uses xdr_READ4res_clnt to decode results.
3393 		 */
3394 		if (objp->wlist) {
3395 			if (objp->data_len != 0) {
3396 				return (xdrrdma_send_read_data(
3397 				    xdrs, objp->data_len, objp->wlist));
3398 			}
3399 			return (TRUE);
3400 		}
3401 	}
3402 
3403 	return (xdr_bytes(xdrs, (char **)&objp->data_val,
3404 	    (uint_t *)&objp->data_len,
3405 	    objp->data_len));
3406 }
3407 
3408 static bool_t
3409 xdr_READ4res_clnt(XDR *xdrs, READ4res *objp, READ4args *aobjp)
3410 {
3411 	mblk_t *mp;
3412 	size_t n;
3413 	int error;
3414 	uint_t size = aobjp->res_maxsize;
3415 	count4 ocount;
3416 
3417 	if (xdrs->x_op == XDR_ENCODE)
3418 		return (FALSE);
3419 
3420 	if (xdrs->x_op == XDR_FREE) {
3421 		/*
3422 		 * Optimized free case
3423 		 */
3424 		if (objp->status != NFS4_OK)
3425 			return (TRUE);
3426 		if (objp->data_val != NULL)
3427 			kmem_free(objp->data_val, objp->data_len);
3428 		return (TRUE);
3429 	}
3430 
3431 	if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
3432 		return (FALSE);
3433 	if (objp->status != NFS4_OK)
3434 		return (TRUE);
3435 
3436 	if (!XDR_GETINT32(xdrs, &objp->eof))
3437 		return (FALSE);
3438 
3439 
3440 	/*
3441 	 * This is a special case such that the caller is providing a
3442 	 * uio as a guide to eventual data location; this is used for
3443 	 * handling DIRECTIO reads.
3444 	 */
3445 	if (aobjp->res_uiop != NULL) {
3446 		struct uio *uiop = aobjp->res_uiop;
3447 		int32_t *ptr;
3448 
3449 		if (xdrs->x_ops == &xdrmblk_ops) {
3450 			if (!xdrmblk_getmblk(xdrs, &mp, &objp->data_len))
3451 				return (FALSE);
3452 
3453 			if (objp->data_len == 0)
3454 				return (TRUE);
3455 
3456 			if (objp->data_len > size)
3457 				return (FALSE);
3458 
3459 			size = objp->data_len;
3460 			do {
3461 				n = MIN(size, mp->b_wptr - mp->b_rptr);
3462 				if ((n = MIN(uiop->uio_resid, n)) != 0) {
3463 
3464 					error =	uiomove((char *)mp->b_rptr, n,
3465 					    UIO_READ, uiop);
3466 					if (error)
3467 						return (FALSE);
3468 					mp->b_rptr += n;
3469 					size -= n;
3470 				}
3471 
3472 				while (mp && (mp->b_rptr >= mp->b_wptr))
3473 					mp = mp->b_cont;
3474 			} while (mp && size > 0 && uiop->uio_resid > 0);
3475 
3476 			return (TRUE);
3477 		}
3478 
3479 		if (xdrs->x_ops == &xdrrdma_ops) {
3480 			struct clist *cl;
3481 
3482 			XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3483 
3484 			objp->wlist = cl;
3485 
3486 			if (objp->wlist) {
3487 				/* opaque count */
3488 				if (!xdr_u_int(xdrs, &ocount)) {
3489 					objp->wlist = NULL;
3490 					return (FALSE);
3491 				}
3492 
3493 				objp->wlist_len = clist_len(cl);
3494 				objp->data_len = ocount;
3495 
3496 				if (objp->wlist_len !=
3497 				    roundup(
3498 				    objp->data_len, BYTES_PER_XDR_UNIT)) {
3499 					DTRACE_PROBE2(
3500 					    xdr__e__read4resuio_clnt_fail,
3501 					    int, ocount,
3502 					    int, objp->data_len);
3503 					objp->wlist = NULL;
3504 					return (FALSE);
3505 				}
3506 
3507 				uiop->uio_resid -= objp->data_len;
3508 				uiop->uio_iov->iov_len -= objp->data_len;
3509 				uiop->uio_iov->iov_base += objp->data_len;
3510 				uiop->uio_loffset += objp->data_len;
3511 
3512 				objp->wlist = NULL;
3513 				return (TRUE);
3514 			}
3515 		}
3516 
3517 		/*
3518 		 * This isn't an xdrmblk stream nor RDMA.
3519 		 * Handle the likely case that it can be
3520 		 * inlined (ex. xdrmem).
3521 		 */
3522 		if (!XDR_GETINT32(xdrs, (int32_t *)&objp->data_len))
3523 			return (FALSE);
3524 
3525 		if (objp->data_len == 0)
3526 			return (TRUE);
3527 
3528 		if (objp->data_len > size)
3529 			return (FALSE);
3530 
3531 		size = (int)objp->data_len;
3532 		if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
3533 			return (uiomove(ptr, size, UIO_READ, uiop) ?
3534 			    FALSE : TRUE);
3535 
3536 		/*
3537 		 * Handle some other (unlikely) stream type that will
3538 		 * need a copy.
3539 		 */
3540 		if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
3541 			return (FALSE);
3542 
3543 		if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
3544 			kmem_free(ptr, size);
3545 			return (FALSE);
3546 		}
3547 		error = uiomove(ptr, size, UIO_READ, uiop);
3548 		kmem_free(ptr, size);
3549 
3550 		return (error ? FALSE : TRUE);
3551 	}
3552 
3553 	/*
3554 	 * Check for the other special case of the caller providing
3555 	 * the target area for the data.
3556 	 */
3557 	if (aobjp->res_data_val_alt == NULL)
3558 		return (FALSE);
3559 
3560 	/*
3561 	 * If read data received via RDMA_WRITE, don't do xdr_bytes().
3562 	 * RDMA_WRITE already moved the data so decode length of
3563 	 * RDMA_WRITE.
3564 	 */
3565 	if (xdrs->x_ops == &xdrrdma_ops) {
3566 		struct clist *cl;
3567 
3568 		XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
3569 
3570 		objp->wlist = cl;
3571 
3572 		/*
3573 		 * Data transferred through inline if
3574 		 * objp->wlist == NULL
3575 		 */
3576 		if (objp->wlist) {
3577 			/* opaque count */
3578 			if (!xdr_u_int(xdrs, &ocount)) {
3579 				objp->wlist = NULL;
3580 				return (FALSE);
3581 			}
3582 
3583 			objp->wlist_len = clist_len(cl);
3584 			objp->data_len = ocount;
3585 
3586 			if (objp->wlist_len !=
3587 			    roundup(
3588 			    objp->data_len, BYTES_PER_XDR_UNIT)) {
3589 				DTRACE_PROBE2(
3590 				    xdr__e__read4res_clnt_fail,
3591 				    int, ocount,
3592 				    int, objp->data_len);
3593 				objp->wlist = NULL;
3594 				return (FALSE);
3595 			}
3596 
3597 			objp->wlist = NULL;
3598 			return (TRUE);
3599 		}
3600 	}
3601 
3602 	return (xdr_bytes(xdrs, (char **)&aobjp->res_data_val_alt,
3603 	    (uint_t *)&objp->data_len,
3604 	    aobjp->res_maxsize));
3605 }
3606 
3607 static bool_t
3608 xdr_READDIR4args(XDR *xdrs, READDIR4args *objp)
3609 {
3610 	rdma_chunkinfo_t rci;
3611 	struct xdr_ops *xops = xdrrdma_xops();
3612 
3613 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
3614 	    xdrs->x_op == XDR_ENCODE) {
3615 		rci.rci_type = RCI_REPLY_CHUNK;
3616 		rci.rci_len = objp->maxcount;
3617 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
3618 	}
3619 
3620 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookie))
3621 		return (FALSE);
3622 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cookieverf))
3623 		return (FALSE);
3624 	if (!xdr_u_int(xdrs, &objp->dircount))
3625 		return (FALSE);
3626 	if (!xdr_u_int(xdrs, &objp->maxcount))
3627 		return (FALSE);
3628 	return (xdr_bitmap4(xdrs, &objp->attr_request));
3629 }
3630 
3631 /* ARGSUSED */
3632 static bool_t
3633 xdrmblk_putmblk_rd(XDR *xdrs, mblk_t *m)
3634 {
3635 	if (((m->b_wptr - m->b_rptr) % BYTES_PER_XDR_UNIT) != 0)
3636 		return (FALSE);
3637 
3638 	/* LINTED pointer alignment */
3639 	((mblk_t *)xdrs->x_base)->b_cont = m;
3640 	xdrs->x_base = (caddr_t)m;
3641 	xdrs->x_handy = 0;
3642 	return (TRUE);
3643 }
3644 
3645 bool_t
3646 xdr_READDIR4res(XDR *xdrs, READDIR4res *objp)
3647 {
3648 	mblk_t *mp = objp->mblk;
3649 	bool_t ret_val;
3650 	uint_t flags = 0;
3651 
3652 	ASSERT(xdrs->x_op == XDR_ENCODE);
3653 
3654 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3655 		return (FALSE);
3656 	if (objp->status != NFS4_OK)
3657 		return (TRUE);
3658 	if (mp == NULL)
3659 		return (FALSE);
3660 
3661 	if (xdrs->x_ops == &xdrmblk_ops) {
3662 		if (xdrmblk_putmblk_rd(xdrs, mp)
3663 		    == TRUE) {
3664 			/* mblk successfully inserted into outgoing chain */
3665 			objp->mblk = NULL;
3666 			return (TRUE);
3667 		}
3668 	}
3669 
3670 	ASSERT(mp->b_cont == NULL);
3671 
3672 	/*
3673 	 * If transport is RDMA, the pre-encoded m_blk needs to be moved
3674 	 * without being chunked.
3675 	 * Check if chunking is enabled for the xdr stream.
3676 	 * If it is enabled, disable it temporarily for this op,
3677 	 * then re-enable.
3678 	 */
3679 	XDR_CONTROL(xdrs, XDR_RDMA_GET_FLAGS, &flags);
3680 
3681 	if (!(flags & XDR_RDMA_CHUNK))
3682 		return (xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len));
3683 
3684 	flags &= ~XDR_RDMA_CHUNK;
3685 
3686 	(void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3687 
3688 	ret_val = xdr_opaque(xdrs, (char *)mp->b_rptr, objp->data_len);
3689 
3690 	flags |= XDR_RDMA_CHUNK;
3691 
3692 	(void) XDR_CONTROL(xdrs, XDR_RDMA_SET_FLAGS, &flags);
3693 
3694 	return (ret_val);
3695 }
3696 
3697 static bool_t
3698 xdr_READLINK4res(XDR *xdrs, READLINK4res *objp)
3699 {
3700 	if (xdrs->x_op != XDR_FREE) {
3701 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3702 			return (FALSE);
3703 		if (objp->status != NFS4_OK)
3704 			return (TRUE);
3705 		return (xdr_bytes(xdrs, (char **)&objp->link.utf8string_val,
3706 		    (uint_t *)&objp->link.utf8string_len,
3707 		    NFS4_MAX_UTF8STRING));
3708 	}
3709 
3710 	/*
3711 	 * Optimized free case
3712 	 */
3713 	if (objp->status != NFS4_OK)
3714 		return (TRUE);
3715 	if (objp->link.utf8string_val != NULL)
3716 		kmem_free(objp->link.utf8string_val, objp->link.utf8string_len);
3717 	return (TRUE);
3718 }
3719 
3720 static bool_t
3721 xdr_REMOVE4res(XDR *xdrs, REMOVE4res *objp)
3722 {
3723 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3724 		return (FALSE);
3725 	if (objp->status != NFS4_OK)
3726 		return (TRUE);
3727 	if (!xdr_bool(xdrs, &objp->cinfo.atomic))
3728 		return (FALSE);
3729 	if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->cinfo.before))
3730 		return (FALSE);
3731 	return (xdr_u_longlong_t(xdrs,
3732 	    (u_longlong_t *)&objp->cinfo.after));
3733 }
3734 
3735 static bool_t
3736 xdr_RENAME4res(XDR *xdrs, RENAME4res *objp)
3737 {
3738 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3739 		return (FALSE);
3740 	if (objp->status != NFS4_OK)
3741 		return (TRUE);
3742 	if (!xdr_bool(xdrs, &objp->source_cinfo.atomic))
3743 		return (FALSE);
3744 	if (!xdr_u_longlong_t(xdrs,
3745 	    (u_longlong_t *)&objp->source_cinfo.before))
3746 		return (FALSE);
3747 	if (!xdr_u_longlong_t(xdrs,
3748 	    (u_longlong_t *)&objp->source_cinfo.after))
3749 		return (FALSE);
3750 	if (!xdr_bool(xdrs, &objp->target_cinfo.atomic))
3751 		return (FALSE);
3752 	if (!xdr_u_longlong_t(xdrs,
3753 	    (u_longlong_t *)&objp->target_cinfo.before))
3754 		return (FALSE);
3755 	return (xdr_u_longlong_t(xdrs,
3756 	    (u_longlong_t *)&objp->target_cinfo.after));
3757 }
3758 
3759 static bool_t
3760 xdr_secinfo4(XDR *xdrs, secinfo4 *objp)
3761 {
3762 	if (xdrs->x_op != XDR_FREE) {
3763 		if (!xdr_u_int(xdrs, &objp->flavor))
3764 			return (FALSE);
3765 		if (objp->flavor != RPCSEC_GSS)
3766 			return (TRUE);
3767 		if (!xdr_bytes(xdrs,
3768 		    (char **)&objp->flavor_info.oid.sec_oid4_val,
3769 		    (uint_t *)&objp->flavor_info.oid.sec_oid4_len,
3770 		    NFS4_MAX_SECOID4))
3771 			return (FALSE);
3772 		if (!xdr_u_int(xdrs, &objp->flavor_info.qop))
3773 			return (FALSE);
3774 		return (xdr_int(xdrs, (int *)&objp->flavor_info.service));
3775 	}
3776 
3777 	/*
3778 	 * Optimized free path
3779 	 */
3780 	if (objp->flavor != RPCSEC_GSS)
3781 		return (TRUE);
3782 
3783 	if (objp->flavor_info.oid.sec_oid4_val != NULL)
3784 		kmem_free(objp->flavor_info.oid.sec_oid4_val,
3785 		    objp->flavor_info.oid.sec_oid4_len);
3786 	return (TRUE);
3787 }
3788 
3789 static bool_t
3790 xdr_SETCLIENTID4args(XDR *xdrs, SETCLIENTID4args *objp)
3791 {
3792 	if (xdrs->x_op != XDR_FREE) {
3793 		if (!xdr_u_longlong_t(xdrs,
3794 		    (u_longlong_t *)&objp->client.verifier))
3795 			return (FALSE);
3796 		if (!xdr_bytes(xdrs, (char **)&objp->client.id_val,
3797 		    (uint_t *)&objp->client.id_len, NFS4_OPAQUE_LIMIT))
3798 			return (FALSE);
3799 		if (!xdr_u_int(xdrs, &objp->callback.cb_program))
3800 			return (FALSE);
3801 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3802 		    NFS4_OPAQUE_LIMIT))
3803 			return (FALSE);
3804 		if (!xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3805 		    NFS4_OPAQUE_LIMIT))
3806 			return (FALSE);
3807 		return (xdr_u_int(xdrs, &objp->callback_ident));
3808 	}
3809 
3810 	/*
3811 	 * Optimized free case
3812 	 */
3813 	if (objp->client.id_val != NULL)
3814 		kmem_free(objp->client.id_val, objp->client.id_len);
3815 	(void) xdr_string(xdrs, &objp->callback.cb_location.r_netid,
3816 	    NFS4_OPAQUE_LIMIT);
3817 	return (xdr_string(xdrs, &objp->callback.cb_location.r_addr,
3818 	    NFS4_OPAQUE_LIMIT));
3819 }
3820 
3821 static bool_t
3822 xdr_SETCLIENTID4res(XDR *xdrs, SETCLIENTID4res *objp)
3823 {
3824 	if (xdrs->x_op != XDR_FREE) {
3825 		if (!xdr_int(xdrs, (int32_t *)&objp->status))
3826 			return (FALSE);
3827 		switch (objp->status) {
3828 		case NFS4_OK:
3829 			if (!xdr_u_longlong_t(xdrs,
3830 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.resok4.
3831 			    clientid))
3832 				return (FALSE);
3833 			return (xdr_u_longlong_t(xdrs,
3834 			    (u_longlong_t *)&objp->SETCLIENTID4res_u.
3835 			    resok4.setclientid_confirm));
3836 		case NFS4ERR_CLID_INUSE:
3837 			if (!xdr_string(xdrs,
3838 			    &objp->SETCLIENTID4res_u.client_using.
3839 			    r_netid, NFS4_OPAQUE_LIMIT))
3840 				return (FALSE);
3841 			return (xdr_string(xdrs,
3842 			    &objp->SETCLIENTID4res_u.client_using.
3843 			    r_addr, NFS4_OPAQUE_LIMIT));
3844 		}
3845 		return (TRUE);
3846 	}
3847 
3848 	/*
3849 	 * Optimized free case
3850 	 */
3851 	if (objp->status != NFS4ERR_CLID_INUSE)
3852 		return (TRUE);
3853 
3854 	if (!xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_netid,
3855 	    NFS4_OPAQUE_LIMIT))
3856 		return (FALSE);
3857 	return (xdr_string(xdrs, &objp->SETCLIENTID4res_u.client_using.r_addr,
3858 	    NFS4_OPAQUE_LIMIT));
3859 }
3860 
3861 static bool_t
3862 xdr_WRITE4args(XDR *xdrs, WRITE4args *objp)
3863 {
3864 	if (xdrs->x_op != XDR_FREE) {
3865 		if (!xdr_u_int(xdrs, &objp->stateid.seqid))
3866 			return (FALSE);
3867 		if (!xdr_opaque(xdrs, objp->stateid.other, 12))
3868 			return (FALSE);
3869 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->offset))
3870 			return (FALSE);
3871 		if (!xdr_int(xdrs, (int *)&objp->stable))
3872 			return (FALSE);
3873 		if (xdrs->x_op == XDR_DECODE) {
3874 			if (xdrs->x_ops == &xdrmblk_ops) {
3875 				objp->data_val = NULL;
3876 				return (xdrmblk_getmblk(xdrs, &objp->mblk,
3877 				    &objp->data_len));
3878 			}
3879 			objp->mblk = NULL;
3880 			if (xdrs->x_ops == &xdrrdmablk_ops) {
3881 				int retval;
3882 				retval = xdrrdma_getrdmablk(xdrs,
3883 				    &objp->rlist,
3884 				    &objp->data_len,
3885 				    &objp->conn, NFS4_DATA_LIMIT);
3886 				if (retval == FALSE)
3887 					return (FALSE);
3888 				return (xdrrdma_read_from_client(objp->rlist,
3889 				    &objp->conn, objp->data_len));
3890 			}
3891 		}
3892 		/* Else fall thru for the xdr_bytes(). */
3893 		return (xdr_bytes(xdrs, (char **)&objp->data_val,
3894 		    (uint_t *)&objp->data_len, NFS4_DATA_LIMIT));
3895 	}
3896 	if (objp->rlist != NULL) {
3897 		(void) xdrrdma_free_clist(objp->conn, objp->rlist);
3898 		objp->rlist = NULL;
3899 		objp->data_val = NULL;
3900 
3901 		return (TRUE);
3902 	}
3903 
3904 	/*
3905 	 * Optimized free case
3906 	 */
3907 	if (objp->data_val != NULL)
3908 		kmem_free(objp->data_val, objp->data_len);
3909 	return (TRUE);
3910 }
3911 
3912 static bool_t
3913 xdr_WRITE4res(XDR *xdrs, WRITE4res *objp)
3914 {
3915 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
3916 		return (FALSE);
3917 	if (objp->status != NFS4_OK)
3918 		return (TRUE);
3919 	if (!xdr_u_int(xdrs, &objp->count))
3920 		return (FALSE);
3921 	if (!xdr_int(xdrs, (int *)&objp->committed))
3922 		return (FALSE);
3923 	return (xdr_u_longlong_t(xdrs,
3924 	    (u_longlong_t *)&objp->writeverf));
3925 }
3926 
3927 static bool_t
3928 xdr_snfs_argop4_free(XDR *xdrs, nfs_argop4 **arrayp, int len)
3929 {
3930 	int i;
3931 	nfs_argop4 *array = *arrayp;
3932 
3933 	/*
3934 	 * Optimized XDR_FREE only args array
3935 	 */
3936 	ASSERT(xdrs->x_op == XDR_FREE);
3937 
3938 	/*
3939 	 * Nothing to do?
3940 	 */
3941 	if (array == NULL)
3942 		return (TRUE);
3943 
3944 	for (i = 0; i < len; i++) {
3945 		/*
3946 		 * These should be ordered by frequency of use
3947 		 */
3948 		switch (array[i].argop) {
3949 		case OP_PUTFH:
3950 			if (array[i].nfs_argop4_u.opputfh.object.nfs_fh4_val !=
3951 			    NULL) {
3952 				kmem_free(array[i].nfs_argop4_u.opputfh.object.
3953 				    nfs_fh4_val,
3954 				    array[i].nfs_argop4_u.opputfh.object.
3955 				    nfs_fh4_len);
3956 			}
3957 			continue;
3958 		case OP_GETATTR:
3959 		case OP_GETFH:
3960 			continue;
3961 		case OP_LOOKUP:
3962 			if (array[i].nfs_argop4_u.oplookup.objname.
3963 			    utf8string_val != NULL) {
3964 				kmem_free(array[i].nfs_argop4_u.oplookup.
3965 				    objname.utf8string_val,
3966 				    array[i].nfs_argop4_u.oplookup.
3967 				    objname.utf8string_len);
3968 			}
3969 			continue;
3970 		case OP_OPEN:
3971 			(void) xdr_OPEN4args(xdrs,
3972 			    &array[i].nfs_argop4_u.opopen);
3973 			continue;
3974 		case OP_CLOSE:
3975 		case OP_ACCESS:
3976 		case OP_READ:
3977 			continue;
3978 		case OP_WRITE:
3979 			(void) xdr_WRITE4args(xdrs,
3980 			    &array[i].nfs_argop4_u.opwrite);
3981 			continue;
3982 		case OP_DELEGRETURN:
3983 		case OP_LOOKUPP:
3984 		case OP_READDIR:
3985 			continue;
3986 		case OP_REMOVE:
3987 			if (array[i].nfs_argop4_u.opremove.target.
3988 			    utf8string_val != NULL) {
3989 				kmem_free(array[i].nfs_argop4_u.opremove.target.
3990 				    utf8string_val,
3991 				    array[i].nfs_argop4_u.opremove.target.
3992 				    utf8string_len);
3993 			}
3994 			continue;
3995 		case OP_COMMIT:
3996 			continue;
3997 		case OP_CREATE:
3998 			(void) xdr_CREATE4args(xdrs,
3999 			    &array[i].nfs_argop4_u.opcreate);
4000 			continue;
4001 		case OP_DELEGPURGE:
4002 			continue;
4003 		case OP_LINK:
4004 			if (array[i].nfs_argop4_u.oplink.newname.
4005 			    utf8string_val != NULL) {
4006 				kmem_free(array[i].nfs_argop4_u.oplink.newname.
4007 				    utf8string_val,
4008 				    array[i].nfs_argop4_u.oplink.newname.
4009 				    utf8string_len);
4010 			}
4011 			continue;
4012 		case OP_LOCK:
4013 			(void) xdr_LOCK4args(xdrs,
4014 			    &array[i].nfs_argop4_u.oplock);
4015 			continue;
4016 		case OP_LOCKT:
4017 			(void) xdr_LOCKT4args(xdrs,
4018 			    &array[i].nfs_argop4_u.oplockt);
4019 			continue;
4020 		case OP_LOCKU:
4021 			continue;
4022 		case OP_NVERIFY:
4023 			(void) xdr_fattr4(xdrs,
4024 			    &array[i].nfs_argop4_u.opnverify.obj_attributes);
4025 			continue;
4026 		case OP_OPENATTR:
4027 		case OP_OPEN_CONFIRM:
4028 		case OP_OPEN_DOWNGRADE:
4029 		case OP_PUTPUBFH:
4030 		case OP_PUTROOTFH:
4031 		case OP_READLINK:
4032 			continue;
4033 		case OP_RENAME:
4034 			if (array[i].nfs_argop4_u.oprename.oldname.
4035 			    utf8string_val != NULL) {
4036 				kmem_free(array[i].nfs_argop4_u.oprename.
4037 				    oldname.utf8string_val,
4038 				    array[i].nfs_argop4_u.oprename.
4039 				    oldname.utf8string_len);
4040 			}
4041 			if (array[i].nfs_argop4_u.oprename.newname.
4042 			    utf8string_val != NULL) {
4043 				kmem_free(array[i].nfs_argop4_u.oprename.
4044 				    newname.utf8string_val,
4045 				    array[i].nfs_argop4_u.oprename.
4046 				    newname.utf8string_len);
4047 			}
4048 			continue;
4049 		case OP_RENEW:
4050 		case OP_RESTOREFH:
4051 		case OP_SAVEFH:
4052 			continue;
4053 		case OP_SECINFO:
4054 			if (array[i].nfs_argop4_u.opsecinfo.name.
4055 			    utf8string_val != NULL) {
4056 				kmem_free(array[i].nfs_argop4_u.opsecinfo.name.
4057 				    utf8string_val,
4058 				    array[i].nfs_argop4_u.opsecinfo.name.
4059 				    utf8string_len);
4060 			}
4061 			continue;
4062 		case OP_SETATTR:
4063 			(void) xdr_fattr4(xdrs,
4064 			    &array[i].nfs_argop4_u.opsetattr.obj_attributes);
4065 			continue;
4066 		case OP_SETCLIENTID:
4067 			(void) xdr_SETCLIENTID4args(xdrs,
4068 			    &array[i].nfs_argop4_u.opsetclientid);
4069 			continue;
4070 		case OP_SETCLIENTID_CONFIRM:
4071 			continue;
4072 		case OP_VERIFY:
4073 			(void) xdr_fattr4(xdrs,
4074 			    &array[i].nfs_argop4_u.opverify.obj_attributes);
4075 			continue;
4076 		case OP_RELEASE_LOCKOWNER:
4077 			if (array[i].nfs_argop4_u.oprelease_lockowner.
4078 			    lock_owner.owner_val != NULL) {
4079 				kmem_free(array[i].nfs_argop4_u.
4080 				    oprelease_lockowner.lock_owner.owner_val,
4081 				    array[i].nfs_argop4_u.
4082 				    oprelease_lockowner.lock_owner.owner_len);
4083 			}
4084 			continue;
4085 		case OP_ILLEGAL:
4086 			continue;
4087 		default:
4088 			/*
4089 			 * An invalid op is a coding error, it should never
4090 			 * have been decoded.
4091 			 * Don't error because the caller cannot finish
4092 			 * freeing the residual memory of the array.
4093 			 */
4094 			continue;
4095 		}
4096 	}
4097 
4098 	kmem_free(*arrayp, len * sizeof (nfs_argop4));
4099 	*arrayp = NULL;
4100 	return (TRUE);
4101 }
4102 
4103 static bool_t
4104 xdr_nfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4105 {
4106 	rdma_chunkinfo_t rci;
4107 	struct xdr_ops *xops = xdrrdma_xops();
4108 
4109 	/*
4110 	 * These should be ordered by frequency of use
4111 	 */
4112 	switch (objp->argop) {
4113 	case OP_PUTFH:
4114 		return (xdr_bytes(xdrs,
4115 		    (char **)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_val,
4116 		    (uint_t *)&objp->nfs_argop4_u.opputfh.object.nfs_fh4_len,
4117 		    NFS4_FHSIZE));
4118 	case OP_GETATTR:
4119 		/*
4120 		 * ACLs can become relatively large ( > 8K) and the default
4121 		 * 8K reply chunk of RDMA may not suffice. Check for
4122 		 * get ACL bit and if it's RDMA, add a chunk equal the size
4123 		 * of the transfer size to the reply chunk list.
4124 		 */
4125 		if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4126 		    (xdrs->x_op == XDR_ENCODE) &&
4127 		    (objp->nfs_argop4_u.opgetattr.attr_request &
4128 		    FATTR4_ACL_MASK)) {
4129 			rci.rci_type = RCI_REPLY_CHUNK;
4130 			rci.rci_len = objp->nfs_argop4_u.opgetattr.mi->mi_tsize;
4131 			XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4132 
4133 			DTRACE_PROBE1(xdr__i__argop4__getattr, int,
4134 			    rci.rci_len);
4135 		}
4136 		return (xdr_bitmap4(xdrs,
4137 		    &objp->nfs_argop4_u.opgetattr.attr_request));
4138 	case OP_GETFH:
4139 		return (TRUE);
4140 	case OP_LOOKUP:
4141 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oplookup.
4142 		    objname.utf8string_val,
4143 		    (uint_t *)&objp->nfs_argop4_u.oplookup.
4144 		    objname.utf8string_len,
4145 		    NFS4_MAX_UTF8STRING));
4146 	case OP_OPEN:
4147 		return (xdr_OPEN4args(xdrs, &objp->nfs_argop4_u.opopen));
4148 	case OP_CLOSE:
4149 		return (xdr_CLOSE4args(xdrs, &objp->nfs_argop4_u.opclose));
4150 	case OP_ACCESS:
4151 		return (xdr_u_int(xdrs,
4152 		    &objp->nfs_argop4_u.opaccess.access));
4153 	case OP_READ:
4154 		return (xdr_READ4args(xdrs, &objp->nfs_argop4_u.opread));
4155 	case OP_WRITE:
4156 		return (xdr_WRITE4args(xdrs, &objp->nfs_argop4_u.opwrite));
4157 	case OP_DELEGRETURN:
4158 		if (!xdr_u_int(xdrs,
4159 		    &objp->nfs_argop4_u.opdelegreturn.deleg_stateid.seqid))
4160 			return (FALSE);
4161 		return (xdr_opaque(xdrs,
4162 		    objp->nfs_argop4_u.opdelegreturn.deleg_stateid.other, 12));
4163 	case OP_LOOKUPP:
4164 		return (TRUE);
4165 	case OP_READDIR:
4166 		return (xdr_READDIR4args(xdrs, &objp->nfs_argop4_u.opreaddir));
4167 	case OP_REMOVE:
4168 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.opremove.
4169 		    target.utf8string_val,
4170 		    (uint_t *)&objp->nfs_argop4_u.opremove.
4171 		    target.utf8string_len,
4172 		    NFS4_MAX_UTF8STRING));
4173 	case OP_COMMIT:
4174 		if (!xdr_u_longlong_t(xdrs,
4175 		    (u_longlong_t *)&objp->nfs_argop4_u.opcommit.offset))
4176 			return (FALSE);
4177 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opcommit.count));
4178 	case OP_CREATE:
4179 		return (xdr_CREATE4args(xdrs, &objp->nfs_argop4_u.opcreate));
4180 	case OP_DELEGPURGE:
4181 		return (xdr_u_longlong_t(xdrs,
4182 		    (u_longlong_t *)&objp->nfs_argop4_u.opdelegpurge.clientid));
4183 	case OP_LINK:
4184 		return (xdr_bytes(xdrs,
4185 		    (char **)&objp->nfs_argop4_u.oplink.newname.utf8string_val,
4186 		    (uint_t *)&objp->nfs_argop4_u.oplink.newname.utf8string_len,
4187 		    NFS4_MAX_UTF8STRING));
4188 	case OP_LOCK:
4189 		return (xdr_LOCK4args(xdrs, &objp->nfs_argop4_u.oplock));
4190 	case OP_LOCKT:
4191 		return (xdr_LOCKT4args(xdrs, &objp->nfs_argop4_u.oplockt));
4192 	case OP_LOCKU:
4193 		return (xdr_LOCKU4args(xdrs, &objp->nfs_argop4_u.oplocku));
4194 	case OP_NVERIFY:
4195 		return (xdr_fattr4(xdrs,
4196 		    &objp->nfs_argop4_u.opnverify.obj_attributes));
4197 	case OP_OPENATTR:
4198 		return (xdr_bool(xdrs,
4199 		    &objp->nfs_argop4_u.opopenattr.createdir));
4200 	case OP_OPEN_CONFIRM:
4201 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4202 		    open_stateid.seqid))
4203 			return (FALSE);
4204 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opopen_confirm.
4205 		    open_stateid.other, 12))
4206 			return (FALSE);
4207 		return (xdr_u_int(xdrs, &objp->nfs_argop4_u.opopen_confirm.
4208 		    seqid));
4209 	case OP_OPEN_DOWNGRADE:
4210 		return (xdr_OPEN_DOWNGRADE4args(xdrs,
4211 		    &objp->nfs_argop4_u.opopen_downgrade));
4212 	case OP_PUTPUBFH:
4213 		return (TRUE);
4214 	case OP_PUTROOTFH:
4215 		return (TRUE);
4216 	case OP_READLINK:
4217 		if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
4218 		    xdrs->x_op == XDR_ENCODE) {
4219 			rci.rci_type = RCI_REPLY_CHUNK;
4220 			rci.rci_len = MAXPATHLEN;
4221 			XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4222 		}
4223 		return (TRUE);
4224 	case OP_RENAME:
4225 		if (!xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4226 		    oldname.utf8string_val,
4227 		    (uint_t *)&objp->nfs_argop4_u.oprename.
4228 		    oldname.utf8string_len,
4229 		    NFS4_MAX_UTF8STRING))
4230 			return (FALSE);
4231 		return (xdr_bytes(xdrs, (char **)&objp->nfs_argop4_u.oprename.
4232 		    newname.utf8string_val,
4233 		    (uint_t *)&objp->nfs_argop4_u.oprename.
4234 		    newname.utf8string_len,
4235 		    NFS4_MAX_UTF8STRING));
4236 	case OP_RENEW:
4237 		return (xdr_u_longlong_t(xdrs,
4238 		    (u_longlong_t *)&objp->nfs_argop4_u.oprenew.clientid));
4239 	case OP_RESTOREFH:
4240 		return (TRUE);
4241 	case OP_SAVEFH:
4242 		return (TRUE);
4243 	case OP_SECINFO:
4244 		return (xdr_bytes(xdrs,
4245 		    (char **)&objp->nfs_argop4_u.opsecinfo.name.utf8string_val,
4246 		    (uint_t *)&objp->nfs_argop4_u.opsecinfo.name.utf8string_len,
4247 		    NFS4_MAX_UTF8STRING));
4248 	case OP_SETATTR:
4249 		if (!xdr_u_int(xdrs, &objp->nfs_argop4_u.opsetattr.
4250 		    stateid.seqid))
4251 			return (FALSE);
4252 		if (!xdr_opaque(xdrs, objp->nfs_argop4_u.opsetattr.
4253 		    stateid.other, 12))
4254 			return (FALSE);
4255 		return (xdr_fattr4(xdrs, &objp->nfs_argop4_u.opsetattr.
4256 		    obj_attributes));
4257 	case OP_SETCLIENTID:
4258 		return (xdr_SETCLIENTID4args(xdrs,
4259 		    &objp->nfs_argop4_u.opsetclientid));
4260 	case OP_SETCLIENTID_CONFIRM:
4261 		if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&objp->nfs_argop4_u.
4262 		    opsetclientid_confirm.clientid))
4263 			return (FALSE);
4264 		return (xdr_u_longlong_t(xdrs,
4265 		    (u_longlong_t *)&objp->nfs_argop4_u.
4266 		    opsetclientid_confirm.setclientid_confirm));
4267 	case OP_VERIFY:
4268 		return (xdr_fattr4(xdrs,
4269 		    &objp->nfs_argop4_u.opverify.obj_attributes));
4270 	case OP_RELEASE_LOCKOWNER:
4271 		if (!xdr_u_longlong_t(xdrs,
4272 		    (u_longlong_t *)&objp->nfs_argop4_u.
4273 		    oprelease_lockowner.lock_owner.clientid))
4274 			return (FALSE);
4275 		return (xdr_bytes(xdrs,
4276 		    (char **)&objp->nfs_argop4_u.oprelease_lockowner.
4277 		    lock_owner.owner_val,
4278 		    (uint_t *)&objp->nfs_argop4_u.oprelease_lockowner.
4279 		    lock_owner.owner_len, NFS4_OPAQUE_LIMIT));
4280 	case OP_ILLEGAL:
4281 		return (TRUE);
4282 	}
4283 	return (FALSE);
4284 }
4285 
4286 static bool_t
4287 xdr_cnfs_argop4_wrap(XDR *xdrs, nfs_argop4 *objp)
4288 {
4289 	if (!xdr_int(xdrs, (int *)&objp->argop))
4290 		return (FALSE);
4291 
4292 	return (xdr_nfs_argop4(xdrs, objp));
4293 }
4294 
4295 static bool_t
4296 xdr_snfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4297 {
4298 	if (!xdr_int(xdrs, (int *)&objp->argop))
4299 		return (FALSE);
4300 
4301 	switch (objp->argop) {
4302 	case OP_PUTFH:
4303 		return (xdr_decode_nfs_fh4(xdrs,
4304 		    &objp->nfs_argop4_u.opputfh.object));
4305 	default:
4306 		return (xdr_nfs_argop4(xdrs, objp));
4307 	}
4308 }
4309 
4310 /*
4311  * Client side encode only arg op processing
4312  */
4313 static bool_t
4314 xdr_cnfs_argop4(XDR *xdrs, nfs_argop4 *objp)
4315 {
4316 	int len;
4317 	int op;
4318 	nfs4_sharedfh_t *sfh;
4319 	mntinfo4_t *mi;
4320 	rpc_inline_t *ptr;
4321 
4322 	ASSERT(xdrs->x_op == XDR_ENCODE);
4323 
4324 	/*
4325 	 * Special case the private pseudo ops
4326 	 */
4327 	if (!(objp->argop & SUNW_PRIVATE_OP))
4328 		return (xdr_cnfs_argop4_wrap(xdrs, objp));
4329 
4330 	/*
4331 	 * These should be ordered by frequency of use
4332 	 */
4333 	switch (objp->argop) {
4334 	case OP_CPUTFH:
4335 		/*
4336 		 * We are passed in the file handle as a nfs4_sharedfh_t *
4337 		 * We need to acquire the correct locks so we can copy it out.
4338 		 */
4339 		sfh = (nfs4_sharedfh_t *)objp->nfs_argop4_u.opcputfh.sfh;
4340 		mi = sfh->sfh_mi;
4341 		(void) nfs_rw_enter_sig(&mi->mi_fh_lock, RW_READER, 0);
4342 
4343 		len = sfh->sfh_fh.nfs_fh4_len;
4344 		ASSERT(len <= NFS4_FHSIZE);
4345 
4346 		/*
4347 		 * First try and inline the copy
4348 		 * Must first be a multiple of BYTES_PER_XDR_UNIT
4349 		 */
4350 		if (!(len % BYTES_PER_XDR_UNIT) &&
4351 		    (ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + len)) !=
4352 		    NULL) {
4353 			IXDR_PUT_U_INT32(ptr, OP_PUTFH);
4354 			IXDR_PUT_U_INT32(ptr, len);
4355 			bcopy(sfh->sfh_fh.nfs_fh4_val, ptr, len);
4356 			nfs_rw_exit(&mi->mi_fh_lock);
4357 			return (TRUE);
4358 		}
4359 
4360 		op = OP_PUTFH;
4361 		if (!XDR_PUTINT32(xdrs, &op)) {
4362 			nfs_rw_exit(&mi->mi_fh_lock);
4363 			return (FALSE);
4364 		}
4365 		if (!XDR_PUTINT32(xdrs, &len)) {
4366 			nfs_rw_exit(&mi->mi_fh_lock);
4367 			return (FALSE);
4368 		}
4369 		if (!(len % BYTES_PER_XDR_UNIT)) {
4370 			if (XDR_PUTBYTES(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4371 				nfs_rw_exit(&mi->mi_fh_lock);
4372 				return (TRUE);
4373 			}
4374 		} else if (xdr_opaque(xdrs, sfh->sfh_fh.nfs_fh4_val, len)) {
4375 			nfs_rw_exit(&mi->mi_fh_lock);
4376 			return (TRUE);
4377 		}
4378 		nfs_rw_exit(&mi->mi_fh_lock);
4379 		return (FALSE);
4380 	case OP_CLOOKUP:
4381 		len = strlen(objp->nfs_argop4_u.opclookup.cname);
4382 		if (len > NFS4_MAX_UTF8STRING)
4383 			return (FALSE);
4384 		op = OP_LOOKUP;
4385 		if (XDR_PUTINT32(xdrs, &op)) {
4386 			if (XDR_PUTINT32(xdrs, &len)) {
4387 				return (xdr_opaque(xdrs,
4388 				    objp->nfs_argop4_u.opclookup.cname,
4389 				    len));
4390 			}
4391 		}
4392 		return (FALSE);
4393 	case OP_COPEN:
4394 		/* op processing inlined in xdr_OPEN4cargs */
4395 		return (xdr_OPEN4cargs(xdrs, &objp->nfs_argop4_u.opcopen));
4396 	case OP_CREMOVE:
4397 		len = strlen(objp->nfs_argop4_u.opcremove.ctarget);
4398 		if (len > NFS4_MAX_UTF8STRING)
4399 			return (FALSE);
4400 		op = OP_REMOVE;
4401 		if (XDR_PUTINT32(xdrs, &op)) {
4402 			if (XDR_PUTINT32(xdrs, &len)) {
4403 				return (xdr_opaque(xdrs,
4404 				    objp->nfs_argop4_u.opcremove.ctarget,
4405 				    len));
4406 			}
4407 		}
4408 		return (FALSE);
4409 	case OP_CCREATE:
4410 		op = OP_CREATE;
4411 		if (!XDR_PUTINT32(xdrs, &op))
4412 			return (FALSE);
4413 		return (xdr_CREATE4cargs(xdrs, &objp->nfs_argop4_u.opccreate));
4414 	case OP_CLINK:
4415 		len = strlen(objp->nfs_argop4_u.opclink.cnewname);
4416 		if (len > NFS4_MAX_UTF8STRING)
4417 			return (FALSE);
4418 		op = OP_LINK;
4419 		if (XDR_PUTINT32(xdrs, &op)) {
4420 			if (XDR_PUTINT32(xdrs, &len)) {
4421 				return (xdr_opaque(xdrs,
4422 				    objp->nfs_argop4_u.opclink.cnewname,
4423 				    len));
4424 			}
4425 		}
4426 		return (FALSE);
4427 	case OP_CRENAME:
4428 		len = strlen(objp->nfs_argop4_u.opcrename.coldname);
4429 		if (len > NFS4_MAX_UTF8STRING)
4430 			return (FALSE);
4431 		op = OP_RENAME;
4432 		if (!XDR_PUTINT32(xdrs, &op))
4433 			return (FALSE);
4434 		if (!XDR_PUTINT32(xdrs, &len))
4435 			return (FALSE);
4436 		if (!xdr_opaque(xdrs,
4437 		    objp->nfs_argop4_u.opcrename.coldname, len))
4438 			return (FALSE);
4439 		len = strlen(objp->nfs_argop4_u.opcrename.cnewname);
4440 		if (len > NFS4_MAX_UTF8STRING)
4441 			return (FALSE);
4442 		if (XDR_PUTINT32(xdrs, &len)) {
4443 			return (xdr_opaque(xdrs,
4444 			    objp->nfs_argop4_u.opcrename.cnewname, len));
4445 		}
4446 		return (FALSE);
4447 	case OP_CSECINFO:
4448 		len = strlen(objp->nfs_argop4_u.opcsecinfo.cname);
4449 		if (len > NFS4_MAX_UTF8STRING)
4450 			return (FALSE);
4451 		op = OP_SECINFO;
4452 		if (XDR_PUTINT32(xdrs, &op)) {
4453 			if (XDR_PUTINT32(xdrs, &len)) {
4454 				return (xdr_opaque(xdrs,
4455 				    objp->nfs_argop4_u.opcsecinfo.cname,
4456 				    len));
4457 			}
4458 		}
4459 		return (FALSE);
4460 	}
4461 	return (FALSE);
4462 }
4463 
4464 /*
4465  * Note that the len and decode_len will only be different in the case
4466  * of the client's use of this free function.  If the server is
4467  * freeing results, then the len/decode_len will always match.
4468  */
4469 static bool_t
4470 xdr_nfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4471 {
4472 	int i;
4473 	nfs_resop4 *array = *arrayp;
4474 	nfs4_ga_res_t *gr;
4475 
4476 	/*
4477 	 * Optimized XDR_FREE only results array
4478 	 */
4479 	ASSERT(xdrs->x_op == XDR_FREE);
4480 
4481 	if (array == NULL)
4482 		return (TRUE);
4483 
4484 	for (i = 0; i < decode_len; i++) {
4485 		/*
4486 		 * These should be ordered by frequency of use
4487 		 */
4488 		switch (array[i].resop) {
4489 		case OP_PUTFH:
4490 			continue;
4491 		case OP_GETATTR:
4492 			if (array[i].nfs_resop4_u.opgetattr.status != NFS4_OK)
4493 				continue;
4494 
4495 			gr = &array[i].nfs_resop4_u.opgetattr.ga_res;
4496 			if (gr->n4g_ext_res) {
4497 				if (gr->n4g_resbmap & FATTR4_FS_LOCATIONS_MASK)
4498 					(void) xdr_fattr4_fs_locations(xdrs,
4499 					    &gr->n4g_ext_res->n4g_fslocations);
4500 				kmem_free(gr->n4g_ext_res,
4501 				    sizeof (struct nfs4_ga_ext_res));
4502 			}
4503 			continue;
4504 		case OP_GETFH:
4505 			if (array[i].nfs_resop4_u.opgetfh.status != NFS4_OK)
4506 				continue;
4507 			if (array[i].nfs_resop4_u.opgetfh.object.nfs_fh4_val !=
4508 			    NULL) {
4509 				kmem_free(array[i].nfs_resop4_u.opgetfh.object.
4510 				    nfs_fh4_val,
4511 				    array[i].nfs_resop4_u.opgetfh.object.
4512 				    nfs_fh4_len);
4513 			}
4514 			continue;
4515 		case OP_LOOKUP:
4516 			continue;
4517 		case OP_OPEN:
4518 			(void) xdr_OPEN4res(xdrs, &array[i].nfs_resop4_u.
4519 			    opopen);
4520 			continue;
4521 		case OP_CLOSE:
4522 		case OP_ACCESS:
4523 			continue;
4524 		case OP_READ:
4525 			(void) xdr_READ4res(xdrs,
4526 			    &array[i].nfs_resop4_u.opread);
4527 			continue;
4528 		case OP_WRITE:
4529 		case OP_DELEGRETURN:
4530 		case OP_LOOKUPP:
4531 		case OP_READDIR:
4532 		case OP_REMOVE:
4533 		case OP_COMMIT:
4534 		case OP_CREATE:
4535 		case OP_DELEGPURGE:
4536 		case OP_LINK:
4537 			continue;
4538 		case OP_LOCK:
4539 			(void) xdr_LOCK4res(xdrs, &array[i].nfs_resop4_u.
4540 			    oplock);
4541 			continue;
4542 		case OP_LOCKT:
4543 			(void) xdr_LOCKT4res(xdrs, &array[i].nfs_resop4_u.
4544 			    oplockt);
4545 			continue;
4546 		case OP_LOCKU:
4547 		case OP_NVERIFY:
4548 		case OP_OPENATTR:
4549 		case OP_OPEN_CONFIRM:
4550 		case OP_OPEN_DOWNGRADE:
4551 		case OP_PUTPUBFH:
4552 		case OP_PUTROOTFH:
4553 		case OP_RENAME:
4554 		case OP_RENEW:
4555 		case OP_RESTOREFH:
4556 		case OP_SAVEFH:
4557 			continue;
4558 		case OP_READLINK:
4559 			(void) xdr_READLINK4res(xdrs, &array[i].nfs_resop4_u.
4560 			    opreadlink);
4561 			continue;
4562 		case OP_SECINFO:
4563 			(void) xdr_array(xdrs,
4564 			    (char **)&array[i].nfs_resop4_u.opsecinfo.
4565 			    SECINFO4resok_val,
4566 			    (uint_t *)&array[i].nfs_resop4_u.opsecinfo.
4567 			    SECINFO4resok_len,
4568 			    NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4569 			    (xdrproc_t)xdr_secinfo4);
4570 			continue;
4571 		case OP_SETCLIENTID:
4572 			(void) xdr_SETCLIENTID4res(xdrs,
4573 			    &array[i].nfs_resop4_u.opsetclientid);
4574 			continue;
4575 		case OP_SETATTR:
4576 		case OP_SETCLIENTID_CONFIRM:
4577 		case OP_VERIFY:
4578 		case OP_RELEASE_LOCKOWNER:
4579 		case OP_ILLEGAL:
4580 			continue;
4581 		default:
4582 			/*
4583 			 * An invalid op is a coding error, it should never
4584 			 * have been decoded.
4585 			 * Don't error because the caller cannot finish
4586 			 * freeing the residual memory of the array.
4587 			 */
4588 			continue;
4589 		}
4590 	}
4591 
4592 	kmem_free(*arrayp, len * sizeof (nfs_resop4));
4593 	*arrayp = NULL;
4594 	return (TRUE);
4595 }
4596 
4597 static bool_t
4598 xdr_snfs_resop4_free(XDR *xdrs, nfs_resop4 **arrayp, int len, int decode_len)
4599 {
4600 	return (xdr_nfs_resop4_free(xdrs, arrayp, len, decode_len));
4601 }
4602 
4603 static bool_t
4604 xdr_nfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4605 {
4606 	/*
4607 	 * These should be ordered by frequency of use
4608 	 */
4609 	switch (objp->resop) {
4610 	case OP_PUTFH:
4611 		return (xdr_int(xdrs,
4612 		    (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4613 	case OP_GETATTR:
4614 		if (!xdr_int(xdrs,
4615 		    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4616 			return (FALSE);
4617 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4618 			return (TRUE);
4619 		return (xdr_fattr4(xdrs,
4620 		    &objp->nfs_resop4_u.opgetattr.obj_attributes));
4621 	case OP_GETFH:
4622 		if (!xdr_int(xdrs,
4623 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4624 			return (FALSE);
4625 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4626 			return (TRUE);
4627 		return (xdr_bytes(xdrs,
4628 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4629 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4630 		    NFS4_FHSIZE));
4631 	case OP_LOOKUP:
4632 		return (xdr_int(xdrs,
4633 		    (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4634 	case OP_OPEN:
4635 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4636 	case OP_CLOSE:
4637 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4638 	case OP_ACCESS:
4639 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4640 	case OP_READ:
4641 		return (xdr_READ4res(xdrs, &objp->nfs_resop4_u.opread));
4642 	case OP_WRITE:
4643 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4644 	case OP_DELEGRETURN:
4645 		return (xdr_int(xdrs,
4646 		    (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4647 	case OP_LOOKUPP:
4648 		return (xdr_int(xdrs,
4649 		    (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4650 	case OP_READDIR:
4651 		return (xdr_READDIR4res(xdrs, &objp->nfs_resop4_u.opreaddir));
4652 	case OP_REMOVE:
4653 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4654 
4655 	case OP_COMMIT:
4656 		if (!xdr_int(xdrs,
4657 		    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4658 			return (FALSE);
4659 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4660 			return (TRUE);
4661 		return (xdr_u_longlong_t(xdrs,
4662 		    (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4663 		    writeverf));
4664 	case OP_CREATE:
4665 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4666 	case OP_DELEGPURGE:
4667 		return (xdr_int(xdrs,
4668 		    (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4669 	case OP_LINK:
4670 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4671 	case OP_LOCK:
4672 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4673 	case OP_LOCKT:
4674 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4675 	case OP_LOCKU:
4676 		if (!xdr_int(xdrs,
4677 		    (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4678 			return (FALSE);
4679 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4680 			return (TRUE);
4681 		if (!xdr_u_int(xdrs,
4682 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4683 			return (FALSE);
4684 		return (xdr_opaque(xdrs,
4685 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4686 		    12));
4687 	case OP_NVERIFY:
4688 		return (xdr_int(xdrs,
4689 		    (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4690 	case OP_OPENATTR:
4691 		return (xdr_int(xdrs,
4692 		    (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4693 	case OP_OPEN_CONFIRM:
4694 		return (xdr_OPEN_CONFIRM4res(xdrs,
4695 		    &objp->nfs_resop4_u.opopen_confirm));
4696 	case OP_OPEN_DOWNGRADE:
4697 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4698 		    &objp->nfs_resop4_u.opopen_downgrade));
4699 	case OP_PUTPUBFH:
4700 		return (xdr_int(xdrs,
4701 		    (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4702 	case OP_PUTROOTFH:
4703 		return (xdr_int(xdrs,
4704 		    (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4705 	case OP_READLINK:
4706 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4707 	case OP_RENAME:
4708 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4709 	case OP_RENEW:
4710 		return (xdr_int(xdrs,
4711 		    (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4712 	case OP_RESTOREFH:
4713 		return (xdr_int(xdrs,
4714 		    (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4715 	case OP_SAVEFH:
4716 		return (xdr_int(xdrs,
4717 		    (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4718 	case OP_SECINFO:
4719 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4720 		    status))
4721 			return (FALSE);
4722 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4723 			return (TRUE);
4724 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4725 		    SECINFO4resok_val,
4726 		    (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4727 		    SECINFO4resok_len,
4728 		    NFS4_SECINFO_LIMIT, sizeof (secinfo4),
4729 		    (xdrproc_t)xdr_secinfo4));
4730 	case OP_SETATTR:
4731 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4732 		    status))
4733 			return (FALSE);
4734 		return (xdr_bitmap4(xdrs,
4735 		    &objp->nfs_resop4_u.opsetattr.attrsset));
4736 	case OP_SETCLIENTID:
4737 		return (xdr_SETCLIENTID4res(xdrs,
4738 		    &objp->nfs_resop4_u.opsetclientid));
4739 	case OP_SETCLIENTID_CONFIRM:
4740 		return (xdr_int(xdrs,
4741 		    (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4742 		    status));
4743 	case OP_VERIFY:
4744 		return (xdr_int(xdrs,
4745 		    (int32_t *)&objp->nfs_resop4_u.opverify.status));
4746 	case OP_RELEASE_LOCKOWNER:
4747 		return (xdr_int(xdrs,
4748 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4749 	case OP_ILLEGAL:
4750 		return (xdr_int(xdrs,
4751 		    (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4752 	}
4753 	return (FALSE);
4754 }
4755 
4756 static bool_t
4757 xdr_snfs_resop4(XDR *xdrs, nfs_resop4 *objp)
4758 {
4759 	if (!xdr_int(xdrs, (int *)&objp->resop))
4760 		return (FALSE);
4761 
4762 	switch (objp->resop) {
4763 	case OP_GETFH:
4764 		if (!XDR_PUTINT32(xdrs,
4765 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4766 			return (FALSE);
4767 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4768 			return (TRUE);
4769 		return (xdr_encode_nfs_fh4(xdrs,
4770 		    &objp->nfs_resop4_u.opgetfh.object));
4771 	default:
4772 		return (xdr_nfs_resop4(xdrs, objp));
4773 	}
4774 }
4775 
4776 static bool_t
4777 xdr_nfs_resop4_clnt(XDR *xdrs, nfs_resop4 *objp, nfs_argop4 *aobjp)
4778 {
4779 	if (!xdr_int(xdrs, (int *)&objp->resop))
4780 		return (FALSE);
4781 	/*
4782 	 * These should be ordered by frequency of use
4783 	 */
4784 	switch (objp->resop) {
4785 	case OP_PUTFH:
4786 		return (xdr_int(xdrs,
4787 		    (int32_t *)&objp->nfs_resop4_u.opputfh.status));
4788 	case OP_GETATTR:
4789 		if (!xdr_int(xdrs,
4790 		    (int32_t *)&objp->nfs_resop4_u.opgetattr.status))
4791 			return (FALSE);
4792 		if (objp->nfs_resop4_u.opgetattr.status != NFS4_OK)
4793 			return (TRUE);
4794 		return (xdr_ga_res(xdrs,
4795 		    (GETATTR4res *)&objp->nfs_resop4_u.opgetattr,
4796 		    &aobjp->nfs_argop4_u.opgetattr));
4797 	case OP_GETFH:
4798 		if (!xdr_int(xdrs,
4799 		    (int32_t *)&objp->nfs_resop4_u.opgetfh.status))
4800 			return (FALSE);
4801 		if (objp->nfs_resop4_u.opgetfh.status != NFS4_OK)
4802 			return (TRUE);
4803 		return (xdr_bytes(xdrs,
4804 		    (char **)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_val,
4805 		    (uint_t *)&objp->nfs_resop4_u.opgetfh.object.nfs_fh4_len,
4806 		    NFS4_FHSIZE));
4807 	case OP_LOOKUP:
4808 		return (xdr_int(xdrs,
4809 		    (int32_t *)&objp->nfs_resop4_u.oplookup.status));
4810 	case OP_NVERIFY:
4811 		return (xdr_int(xdrs,
4812 		    (int32_t *)&objp->nfs_resop4_u.opnverify.status));
4813 	case OP_OPEN:
4814 		return (xdr_OPEN4res(xdrs, &objp->nfs_resop4_u.opopen));
4815 	case OP_CLOSE:
4816 		return (xdr_CLOSE4res(xdrs, &objp->nfs_resop4_u.opclose));
4817 	case OP_ACCESS:
4818 		return (xdr_ACCESS4res(xdrs, &objp->nfs_resop4_u.opaccess));
4819 	case OP_READ:
4820 		return (xdr_READ4res_clnt(xdrs, &objp->nfs_resop4_u.opread,
4821 		    &aobjp->nfs_argop4_u.opread));
4822 	case OP_WRITE:
4823 		return (xdr_WRITE4res(xdrs, &objp->nfs_resop4_u.opwrite));
4824 	case OP_DELEGRETURN:
4825 		return (xdr_int(xdrs,
4826 		    (int32_t *)&objp->nfs_resop4_u.opdelegreturn.status));
4827 	case OP_LOOKUPP:
4828 		return (xdr_int(xdrs,
4829 		    (int32_t *)&objp->nfs_resop4_u.oplookupp.status));
4830 	case OP_READDIR:
4831 		return (xdr_READDIR4res_clnt(xdrs,
4832 		    &objp->nfs_resop4_u.opreaddirclnt,
4833 		    &aobjp->nfs_argop4_u.opreaddir));
4834 	case OP_REMOVE:
4835 		return (xdr_REMOVE4res(xdrs, &objp->nfs_resop4_u.opremove));
4836 
4837 	case OP_COMMIT:
4838 		if (!xdr_int(xdrs,
4839 		    (int32_t *)&objp->nfs_resop4_u.opcommit.status))
4840 			return (FALSE);
4841 		if (objp->nfs_resop4_u.opcommit.status != NFS4_OK)
4842 			return (TRUE);
4843 		return (xdr_u_longlong_t(xdrs,
4844 		    (u_longlong_t *)&objp->nfs_resop4_u.opcommit.
4845 		    writeverf));
4846 	case OP_CREATE:
4847 		return (xdr_CREATE4res(xdrs, &objp->nfs_resop4_u.opcreate));
4848 	case OP_DELEGPURGE:
4849 		return (xdr_int(xdrs,
4850 		    (int32_t *)&objp->nfs_resop4_u.opdelegpurge.status));
4851 	case OP_LINK:
4852 		return (xdr_LINK4res(xdrs, &objp->nfs_resop4_u.oplink));
4853 	case OP_LOCK:
4854 		return (xdr_LOCK4res(xdrs, &objp->nfs_resop4_u.oplock));
4855 	case OP_LOCKT:
4856 		return (xdr_LOCKT4res(xdrs, &objp->nfs_resop4_u.oplockt));
4857 	case OP_LOCKU:
4858 		if (!xdr_int(xdrs,
4859 		    (int32_t *)&objp->nfs_resop4_u.oplocku.status))
4860 			return (FALSE);
4861 		if (objp->nfs_resop4_u.oplocku.status != NFS4_OK)
4862 			return (TRUE);
4863 		if (!xdr_u_int(xdrs,
4864 		    &objp->nfs_resop4_u.oplocku.lock_stateid.seqid))
4865 			return (FALSE);
4866 		return (xdr_opaque(xdrs,
4867 		    objp->nfs_resop4_u.oplocku.lock_stateid.other,
4868 		    12));
4869 	case OP_OPENATTR:
4870 		return (xdr_int(xdrs,
4871 		    (int32_t *)&objp->nfs_resop4_u.opopenattr.status));
4872 	case OP_OPEN_CONFIRM:
4873 		return (xdr_OPEN_CONFIRM4res(xdrs,
4874 		    &objp->nfs_resop4_u.opopen_confirm));
4875 	case OP_OPEN_DOWNGRADE:
4876 		return (xdr_OPEN_DOWNGRADE4res(xdrs,
4877 		    &objp->nfs_resop4_u.opopen_downgrade));
4878 	case OP_PUTPUBFH:
4879 		return (xdr_int(xdrs,
4880 		    (int32_t *)&objp->nfs_resop4_u.opputpubfh.status));
4881 	case OP_PUTROOTFH:
4882 		return (xdr_int(xdrs,
4883 		    (int32_t *)&objp->nfs_resop4_u.opputrootfh.status));
4884 	case OP_READLINK:
4885 		return (xdr_READLINK4res(xdrs, &objp->nfs_resop4_u.opreadlink));
4886 	case OP_RENAME:
4887 		return (xdr_RENAME4res(xdrs, &objp->nfs_resop4_u.oprename));
4888 	case OP_RENEW:
4889 		return (xdr_int(xdrs,
4890 		    (int32_t *)&objp->nfs_resop4_u.oprenew.status));
4891 	case OP_RESTOREFH:
4892 		return (xdr_int(xdrs,
4893 		    (int32_t *)&objp->nfs_resop4_u.oprestorefh.status));
4894 	case OP_SAVEFH:
4895 		return (xdr_int(xdrs,
4896 		    (int32_t *)&objp->nfs_resop4_u.opsavefh.status));
4897 	case OP_SECINFO:
4898 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsecinfo.
4899 		    status))
4900 			return (FALSE);
4901 		if (objp->nfs_resop4_u.opsecinfo.status != NFS4_OK)
4902 			return (TRUE);
4903 		return (xdr_array(xdrs, (char **)&objp->nfs_resop4_u.opsecinfo.
4904 		    SECINFO4resok_val,
4905 		    (uint_t *)&objp->nfs_resop4_u.opsecinfo.
4906 		    SECINFO4resok_len,
4907 		    ~0, sizeof (secinfo4), (xdrproc_t)xdr_secinfo4));
4908 	case OP_SETATTR:
4909 		if (!xdr_int(xdrs, (int32_t *)&objp->nfs_resop4_u.opsetattr.
4910 		    status))
4911 			return (FALSE);
4912 		return (xdr_bitmap4(xdrs,
4913 		    &objp->nfs_resop4_u.opsetattr.attrsset));
4914 	case OP_SETCLIENTID:
4915 		return (xdr_SETCLIENTID4res(xdrs,
4916 		    &objp->nfs_resop4_u.opsetclientid));
4917 	case OP_SETCLIENTID_CONFIRM:
4918 		return (xdr_int(xdrs,
4919 		    (int32_t *)&objp->nfs_resop4_u.opsetclientid_confirm.
4920 		    status));
4921 	case OP_VERIFY:
4922 		return (xdr_int(xdrs,
4923 		    (int32_t *)&objp->nfs_resop4_u.opverify.status));
4924 	case OP_RELEASE_LOCKOWNER:
4925 		return (xdr_int(xdrs,
4926 		    (int32_t *)&objp->nfs_resop4_u.oprelease_lockowner.status));
4927 	case OP_ILLEGAL:
4928 		return (xdr_int(xdrs,
4929 		    (int32_t *)&objp->nfs_resop4_u.opillegal.status));
4930 	}
4931 	return (FALSE);
4932 }
4933 
4934 bool_t
4935 xdr_COMPOUND4args_clnt(XDR *xdrs, COMPOUND4args_clnt *objp)
4936 {
4937 	static int32_t twelve = 12;
4938 	static int32_t minorversion = NFS4_MINORVERSION;
4939 	uint32_t *ctagp;
4940 	rpc_inline_t *ptr;
4941 	rdma_chunkinfo_t rci;
4942 	struct xdr_ops *xops = xdrrdma_xops();
4943 
4944 	/*
4945 	 * XDR_ENCODE only
4946 	 */
4947 	if (xdrs->x_op == XDR_FREE)
4948 		return (TRUE);
4949 	if (xdrs->x_op == XDR_DECODE)
4950 		return (FALSE);
4951 
4952 	ctagp = (uint32_t *)&nfs4_ctags[objp->ctag].ct_tag;
4953 
4954 	if ((ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT)) != NULL) {
4955 		/*
4956 		 * Efficiently encode fixed length tags, could be longlongs
4957 		 * but 8 byte XDR alignment not assured
4958 		 */
4959 		IXDR_PUT_U_INT32(ptr, 12);
4960 		IXDR_PUT_U_INT32(ptr, ctagp[0]);
4961 		IXDR_PUT_U_INT32(ptr, ctagp[1]);
4962 		IXDR_PUT_U_INT32(ptr, ctagp[2]);
4963 
4964 		/*
4965 		 * Fixed minor version for now
4966 		 */
4967 		IXDR_PUT_U_INT32(ptr, NFS4_MINORVERSION);
4968 	} else {
4969 		if (!XDR_PUTINT32(xdrs, &twelve))
4970 			return (FALSE);
4971 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[0]))
4972 			return (FALSE);
4973 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[1]))
4974 			return (FALSE);
4975 		if (!XDR_PUTINT32(xdrs, (int32_t *)&ctagp[2]))
4976 			return (FALSE);
4977 		if (!XDR_PUTINT32(xdrs, (int32_t *)&minorversion))
4978 			return (FALSE);
4979 	}
4980 	if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
4981 		rci.rci_type = RCI_REPLY_CHUNK;
4982 		rci.rci_len = MAXPATHLEN * 2;
4983 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
4984 	}
4985 
4986 	return (xdr_array(xdrs, (char **)&objp->array,
4987 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
4988 	    sizeof (nfs_argop4), (xdrproc_t)xdr_cnfs_argop4));
4989 }
4990 
4991 bool_t
4992 xdr_COMPOUND4args_srv(XDR *xdrs, COMPOUND4args *objp)
4993 {
4994 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
4995 	    (uint_t *)&objp->tag.utf8string_len,
4996 	    NFS4_MAX_UTF8STRING))
4997 		return (FALSE);
4998 	if (!xdr_u_int(xdrs, &objp->minorversion))
4999 		return (FALSE);
5000 	if (xdrs->x_op != XDR_FREE)
5001 		return (xdr_array(xdrs, (char **)&objp->array,
5002 		    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5003 		    sizeof (nfs_argop4), (xdrproc_t)xdr_snfs_argop4));
5004 
5005 	return (xdr_snfs_argop4_free(xdrs, &objp->array, objp->array_len));
5006 }
5007 
5008 bool_t
5009 xdr_COMPOUND4res_clnt(XDR *xdrs, COMPOUND4res_clnt *objp)
5010 {
5011 	uint32_t len;
5012 	int32_t *ptr;
5013 	nfs_argop4 *argop;
5014 	nfs_resop4 *resop;
5015 
5016 	/*
5017 	 * No XDR_ENCODE
5018 	 */
5019 	if (xdrs->x_op == XDR_ENCODE)
5020 		return (FALSE);
5021 
5022 	if (xdrs->x_op != XDR_FREE) {
5023 		if ((ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) {
5024 			objp->status = IXDR_GET_U_INT32(ptr);
5025 			len = IXDR_GET_U_INT32(ptr);
5026 		} else {
5027 			if (!xdr_int(xdrs, (int32_t *)&objp->status))
5028 				return (FALSE);
5029 			if (!xdr_u_int(xdrs, (uint32_t *)&len))
5030 				return (FALSE);
5031 		}
5032 		if (len > NFS4_MAX_UTF8STRING)
5033 			return (FALSE);
5034 		/*
5035 		 * Ignore the tag
5036 		 */
5037 		if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &len))
5038 			return (FALSE);
5039 
5040 		if (!xdr_int(xdrs, (int32_t *)&objp->array_len))
5041 			return (FALSE);
5042 
5043 		if (objp->array_len > objp->argsp->array_len)
5044 			return (FALSE);
5045 
5046 		if (objp->status == NFS_OK &&
5047 		    objp->array_len != objp->argsp->array_len)
5048 			return (FALSE);
5049 
5050 		/* Alloc the results array */
5051 		argop = objp->argsp->array;
5052 		len = objp->array_len * sizeof (nfs_resop4);
5053 		objp->decode_len = 0;
5054 		objp->array = resop = kmem_zalloc(len, KM_SLEEP);
5055 
5056 		for (len = 0; len < objp->array_len;
5057 		    len++, resop++, argop++, objp->decode_len++) {
5058 			if (!xdr_nfs_resop4_clnt(xdrs, resop, argop)) {
5059 				/*
5060 				 * Make sure to free anything that may
5061 				 * have been allocated along the way.
5062 				 */
5063 				xdrs->x_op = XDR_FREE;
5064 				(void) xdr_nfs_resop4_free(xdrs, &objp->array,
5065 				    objp->array_len,
5066 				    objp->decode_len);
5067 				return (FALSE);
5068 			}
5069 		}
5070 		return (TRUE);
5071 	}
5072 	return (xdr_nfs_resop4_free(xdrs, &objp->array,
5073 	    objp->array_len, objp->decode_len));
5074 }
5075 
5076 bool_t
5077 xdr_COMPOUND4res_srv(XDR *xdrs, COMPOUND4res *objp)
5078 {
5079 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
5080 		return (FALSE);
5081 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5082 	    (uint_t *)&objp->tag.utf8string_len,
5083 	    NFS4_MAX_UTF8STRING))
5084 		return (FALSE);
5085 
5086 	if (xdrs->x_op != XDR_FREE)
5087 		return (xdr_array(xdrs, (char **)&objp->array,
5088 		    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5089 		    sizeof (nfs_resop4), (xdrproc_t)xdr_snfs_resop4));
5090 
5091 	return (xdr_snfs_resop4_free(xdrs, &objp->array,
5092 	    objp->array_len, objp->array_len));
5093 }
5094 
5095 /*
5096  * NFS server side callback, initiating the callback request so it
5097  * is the RPC client. Must convert from server's internal filehandle
5098  * format to wire format.
5099  */
5100 static bool_t
5101 xdr_snfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5102 {
5103 	CB_GETATTR4args *gargs;
5104 	CB_RECALL4args *rargs;
5105 
5106 	ASSERT(xdrs->x_op == XDR_ENCODE);
5107 
5108 	if (!XDR_PUTINT32(xdrs, (int32_t *)&objp->argop))
5109 		return (FALSE);
5110 
5111 	switch (objp->argop) {
5112 	case OP_CB_GETATTR:
5113 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5114 
5115 		if (!xdr_encode_nfs_fh4(xdrs, &gargs->fh))
5116 			return (FALSE);
5117 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
5118 	case OP_CB_RECALL:
5119 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5120 
5121 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->stateid.seqid))
5122 			return (FALSE);
5123 		if (!xdr_opaque(xdrs, rargs->stateid.other, 12))
5124 			return (FALSE);
5125 		if (!XDR_PUTINT32(xdrs, (int32_t *)&rargs->truncate))
5126 			return (FALSE);
5127 		return (xdr_encode_nfs_fh4(xdrs, &rargs->fh));
5128 	case OP_CB_ILLEGAL:
5129 		return (TRUE);
5130 	}
5131 	return (FALSE);
5132 }
5133 
5134 /*
5135  * NFS client side callback, receiving the callback request so it
5136  * is the RPC server. Must treat the file handles as opaque.
5137  */
5138 static bool_t
5139 xdr_cnfs_cb_argop4(XDR *xdrs, nfs_cb_argop4 *objp)
5140 {
5141 	CB_GETATTR4args *gargs;
5142 	CB_RECALL4args *rargs;
5143 
5144 	ASSERT(xdrs->x_op != XDR_ENCODE);
5145 
5146 	if (!xdr_u_int(xdrs, &objp->argop))
5147 		return (FALSE);
5148 	switch (objp->argop) {
5149 	case OP_CB_GETATTR:
5150 		gargs = &objp->nfs_cb_argop4_u.opcbgetattr;
5151 
5152 		if (!xdr_bytes(xdrs, (char **)&gargs->fh.nfs_fh4_val,
5153 		    (uint_t *)&gargs->fh.nfs_fh4_len, NFS4_FHSIZE))
5154 			return (FALSE);
5155 		return (xdr_bitmap4(xdrs, &gargs->attr_request));
5156 	case OP_CB_RECALL:
5157 		rargs = &objp->nfs_cb_argop4_u.opcbrecall;
5158 
5159 		if (!xdr_u_int(xdrs, &rargs->stateid.seqid))
5160 			return (FALSE);
5161 		if (!xdr_opaque(xdrs, rargs->stateid.other, 12))
5162 			return (FALSE);
5163 		if (!xdr_bool(xdrs, &rargs->truncate))
5164 			return (FALSE);
5165 		return (xdr_bytes(xdrs, (char **)&rargs->fh.nfs_fh4_val,
5166 		    (uint_t *)&rargs->fh.nfs_fh4_len, NFS4_FHSIZE));
5167 	case OP_CB_ILLEGAL:
5168 		return (TRUE);
5169 	}
5170 	return (FALSE);
5171 }
5172 
5173 static bool_t
5174 xdr_nfs_cb_resop4(XDR *xdrs, nfs_cb_resop4 *objp)
5175 {
5176 	if (!xdr_u_int(xdrs, &objp->resop))
5177 		return (FALSE);
5178 	switch (objp->resop) {
5179 	case OP_CB_GETATTR:
5180 		if (!xdr_int(xdrs,
5181 		    (int32_t *)&objp->nfs_cb_resop4_u.opcbgetattr.
5182 		    status))
5183 			return (FALSE);
5184 		if (objp->nfs_cb_resop4_u.opcbgetattr.status != NFS4_OK)
5185 			return (TRUE);
5186 		return (xdr_fattr4(xdrs,
5187 		    &objp->nfs_cb_resop4_u.opcbgetattr.
5188 		    obj_attributes));
5189 	case OP_CB_RECALL:
5190 		return (xdr_int(xdrs,
5191 		    (int32_t *)&objp->nfs_cb_resop4_u.opcbrecall.status));
5192 	case OP_CB_ILLEGAL:
5193 		return (xdr_int(xdrs,
5194 		    (int32_t *)&objp->nfs_cb_resop4_u.opcbillegal.status));
5195 	}
5196 	return (FALSE);
5197 }
5198 
5199 /*
5200  * The NFS client side callback, RPC server
5201  */
5202 bool_t
5203 xdr_CB_COMPOUND4args_clnt(XDR *xdrs, CB_COMPOUND4args *objp)
5204 {
5205 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5206 	    (uint_t *)&objp->tag.utf8string_len,
5207 	    NFS4_MAX_UTF8STRING))
5208 		return (FALSE);
5209 	if (!xdr_u_int(xdrs, &objp->minorversion))
5210 		return (FALSE);
5211 	if (!xdr_u_int(xdrs, &objp->callback_ident))
5212 		return (FALSE);
5213 	return (xdr_array(xdrs, (char **)&objp->array,
5214 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5215 	    sizeof (nfs_cb_argop4), (xdrproc_t)xdr_cnfs_cb_argop4));
5216 }
5217 
5218 /*
5219  * The NFS server side callback, RPC client
5220  */
5221 bool_t
5222 xdr_CB_COMPOUND4args_srv(XDR *xdrs, CB_COMPOUND4args *objp)
5223 {
5224 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5225 	    (uint_t *)&objp->tag.utf8string_len,
5226 	    NFS4_MAX_UTF8STRING))
5227 		return (FALSE);
5228 	if (!xdr_u_int(xdrs, &objp->minorversion))
5229 		return (FALSE);
5230 	if (!xdr_u_int(xdrs, &objp->callback_ident))
5231 		return (FALSE);
5232 	return (xdr_array(xdrs, (char **)&objp->array,
5233 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5234 	    sizeof (nfs_cb_argop4), (xdrproc_t)xdr_snfs_cb_argop4));
5235 }
5236 
5237 bool_t
5238 xdr_CB_COMPOUND4res(XDR *xdrs, CB_COMPOUND4res *objp)
5239 {
5240 	if (!xdr_int(xdrs, (int32_t *)&objp->status))
5241 		return (FALSE);
5242 	if (!xdr_bytes(xdrs, (char **)&objp->tag.utf8string_val,
5243 	    (uint_t *)&objp->tag.utf8string_len,
5244 	    NFS4_MAX_UTF8STRING))
5245 		return (FALSE);
5246 	return (xdr_array(xdrs, (char **)&objp->array,
5247 	    (uint_t *)&objp->array_len, NFS4_COMPOUND_LIMIT,
5248 	    sizeof (nfs_cb_resop4), (xdrproc_t)xdr_nfs_cb_resop4));
5249 }
5250