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