Home | History | Annotate | Download | only in nfs
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
     27 /* All Rights Reserved */
     28 
     29 #include <sys/param.h>
     30 #include <sys/types.h>
     31 #include <sys/systm.h>
     32 #include <sys/user.h>
     33 #include <sys/vnode.h>
     34 #include <sys/file.h>
     35 #include <sys/dirent.h>
     36 #include <sys/vfs.h>
     37 #include <sys/stream.h>
     38 #include <sys/strsubr.h>
     39 #include <sys/debug.h>
     40 #include <sys/t_lock.h>
     41 #include <sys/sdt.h>
     42 
     43 #include <rpc/types.h>
     44 #include <rpc/xdr.h>
     45 
     46 #include <nfs/nfs.h>
     47 
     48 #include <vm/hat.h>
     49 #include <vm/as.h>
     50 #include <vm/seg.h>
     51 #include <vm/seg_map.h>
     52 #include <vm/seg_kmem.h>
     53 
     54 static bool_t xdr_fastshorten(XDR *, uint_t);
     55 
     56 /*
     57  * These are the XDR routines used to serialize and deserialize
     58  * the various structures passed as parameters accross the network
     59  * between NFS clients and servers.
     60  */
     61 
     62 /*
     63  * File access handle
     64  * The fhandle struct is treated a opaque data on the wire
     65  */
     66 bool_t
     67 xdr_fhandle(XDR *xdrs, fhandle_t *fh)
     68 {
     69 	int32_t *ptr;
     70 	int32_t *fhp;
     71 
     72 	if (xdrs->x_op == XDR_FREE)
     73 		return (TRUE);
     74 
     75 	ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
     76 	if (ptr != NULL) {
     77 		fhp = (int32_t *)fh;
     78 		if (xdrs->x_op == XDR_DECODE) {
     79 			*fhp++ = *ptr++;
     80 			*fhp++ = *ptr++;
     81 			*fhp++ = *ptr++;
     82 			*fhp++ = *ptr++;
     83 			*fhp++ = *ptr++;
     84 			*fhp++ = *ptr++;
     85 			*fhp++ = *ptr++;
     86 			*fhp = *ptr;
     87 		} else {
     88 			*ptr++ = *fhp++;
     89 			*ptr++ = *fhp++;
     90 			*ptr++ = *fhp++;
     91 			*ptr++ = *fhp++;
     92 			*ptr++ = *fhp++;
     93 			*ptr++ = *fhp++;
     94 			*ptr++ = *fhp++;
     95 			*ptr = *fhp;
     96 		}
     97 		return (TRUE);
     98 	}
     99 
    100 	return (xdr_opaque(xdrs, (caddr_t)fh, NFS_FHSIZE));
    101 }
    102 
    103 bool_t
    104 xdr_fastfhandle(XDR *xdrs, fhandle_t **fh)
    105 {
    106 	int32_t *ptr;
    107 
    108 	if (xdrs->x_op != XDR_DECODE)
    109 		return (FALSE);
    110 
    111 	ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)));
    112 	if (ptr != NULL) {
    113 		*fh = (fhandle_t *)ptr;
    114 		return (TRUE);
    115 	}
    116 
    117 	return (FALSE);
    118 }
    119 
    120 /*
    121  * Arguments to remote write and writecache
    122  */
    123 bool_t
    124 xdr_writeargs(XDR *xdrs, struct nfswriteargs *wa)
    125 {
    126 	int32_t *ptr;
    127 	int32_t *fhp;
    128 
    129 	switch (xdrs->x_op) {
    130 	case XDR_DECODE:
    131 		wa->wa_args = &wa->wa_args_buf;
    132 		ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
    133 		    3 * BYTES_PER_XDR_UNIT);
    134 		if (ptr != NULL) {
    135 			fhp = (int32_t *)&wa->wa_fhandle;
    136 			*fhp++ = *ptr++;
    137 			*fhp++ = *ptr++;
    138 			*fhp++ = *ptr++;
    139 			*fhp++ = *ptr++;
    140 			*fhp++ = *ptr++;
    141 			*fhp++ = *ptr++;
    142 			*fhp++ = *ptr++;
    143 			*fhp = *ptr++;
    144 			wa->wa_begoff = IXDR_GET_U_INT32(ptr);
    145 			wa->wa_offset = IXDR_GET_U_INT32(ptr);
    146 			wa->wa_totcount = IXDR_GET_U_INT32(ptr);
    147 			wa->wa_mblk = NULL;
    148 			wa->wa_data = NULL;
    149 			wa->wa_rlist = NULL;
    150 			wa->wa_conn = NULL;
    151 			if (xdrs->x_ops == &xdrmblk_ops) {
    152 				return (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
    153 				    &wa->wa_count));
    154 			} else {
    155 				if (xdrs->x_ops == &xdrrdmablk_ops) {
    156 					if (xdrrdma_getrdmablk(xdrs,
    157 					    &wa->wa_rlist,
    158 					    &wa->wa_count,
    159 					    &wa->wa_conn,
    160 					    NFS_MAXDATA) == TRUE)
    161 					return (xdrrdma_read_from_client(
    162 					    wa->wa_rlist,
    163 					    &wa->wa_conn,
    164 					    wa->wa_count));
    165 
    166 					wa->wa_rlist = NULL;
    167 					wa->wa_conn = NULL;
    168 				}
    169 			}
    170 
    171 			/*
    172 			 * It is just as efficient to xdr_bytes
    173 			 * an array of unknown length as to inline copy it.
    174 			 */
    175 			return (xdr_bytes(xdrs, &wa->wa_data,
    176 			    &wa->wa_count, NFS_MAXDATA));
    177 		}
    178 		if (xdr_fhandle(xdrs, &wa->wa_fhandle) &&
    179 		    xdr_u_int(xdrs, &wa->wa_begoff) &&
    180 		    xdr_u_int(xdrs, &wa->wa_offset) &&
    181 		    xdr_u_int(xdrs, &wa->wa_totcount)) {
    182 			/* deal with the variety of data transfer types */
    183 
    184 			wa->wa_mblk = NULL;
    185 			wa->wa_data = NULL;
    186 			wa->wa_rlist = NULL;
    187 			wa->wa_conn = NULL;
    188 
    189 			if (xdrs->x_ops == &xdrmblk_ops) {
    190 				if (xdrmblk_getmblk(xdrs, &wa->wa_mblk,
    191 				    &wa->wa_count) == TRUE)
    192 					return (TRUE);
    193 			} else {
    194 				if (xdrs->x_ops == &xdrrdmablk_ops) {
    195 					if (xdrrdma_getrdmablk(xdrs,
    196 					    &wa->wa_rlist,
    197 					    &wa->wa_count,
    198 					    &wa->wa_conn,
    199 					    NFS_MAXDATA) == TRUE)
    200 					return (xdrrdma_read_from_client(
    201 					    wa->wa_rlist,
    202 					    &wa->wa_conn,
    203 					    wa->wa_count));
    204 
    205 					wa->wa_rlist = NULL;
    206 					wa->wa_conn = NULL;
    207 				}
    208 			}
    209 			return (xdr_bytes(xdrs, &wa->wa_data,
    210 			    &wa->wa_count, NFS_MAXDATA));
    211 		}
    212 		return (FALSE);
    213 	case XDR_ENCODE:
    214 		ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
    215 		    3 * BYTES_PER_XDR_UNIT);
    216 		if (ptr != NULL) {
    217 			fhp = (int32_t *)&wa->wa_fhandle;
    218 			*ptr++ = *fhp++;
    219 			*ptr++ = *fhp++;
    220 			*ptr++ = *fhp++;
    221 			*ptr++ = *fhp++;
    222 			*ptr++ = *fhp++;
    223 			*ptr++ = *fhp++;
    224 			*ptr++ = *fhp++;
    225 			*ptr++ = *fhp;
    226 			IXDR_PUT_U_INT32(ptr, wa->wa_begoff);
    227 			IXDR_PUT_U_INT32(ptr, wa->wa_offset);
    228 			IXDR_PUT_U_INT32(ptr, wa->wa_totcount);
    229 		} else {
    230 			if (!(xdr_fhandle(xdrs, &wa->wa_fhandle) &&
    231 			    xdr_u_int(xdrs, &wa->wa_begoff) &&
    232 			    xdr_u_int(xdrs, &wa->wa_offset) &&
    233 			    xdr_u_int(xdrs, &wa->wa_totcount)))
    234 				return (FALSE);
    235 		}
    236 
    237 		return (xdr_bytes(xdrs, &wa->wa_data, &wa->wa_count,
    238 		    NFS_MAXDATA));
    239 	case XDR_FREE:
    240 		if (wa->wa_rlist) {
    241 			(void) xdrrdma_free_clist(wa->wa_conn, wa->wa_rlist);
    242 			wa->wa_rlist = NULL;
    243 		}
    244 
    245 		if (wa->wa_data != NULL) {
    246 			kmem_free(wa->wa_data, wa->wa_count);
    247 			wa->wa_data = NULL;
    248 		}
    249 		return (TRUE);
    250 	}
    251 	return (FALSE);
    252 }
    253 
    254 
    255 /*
    256  * File attributes
    257  */
    258 bool_t
    259 xdr_fattr(XDR *xdrs, struct nfsfattr *na)
    260 {
    261 	int32_t *ptr;
    262 
    263 	if (xdrs->x_op == XDR_FREE)
    264 		return (TRUE);
    265 
    266 	ptr = XDR_INLINE(xdrs, 17 * BYTES_PER_XDR_UNIT);
    267 	if (ptr != NULL) {
    268 		if (xdrs->x_op == XDR_DECODE) {
    269 			na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
    270 			na->na_mode = IXDR_GET_U_INT32(ptr);
    271 			na->na_nlink = IXDR_GET_U_INT32(ptr);
    272 			na->na_uid = IXDR_GET_U_INT32(ptr);
    273 			na->na_gid = IXDR_GET_U_INT32(ptr);
    274 			na->na_size = IXDR_GET_U_INT32(ptr);
    275 			na->na_blocksize = IXDR_GET_U_INT32(ptr);
    276 			na->na_rdev = IXDR_GET_U_INT32(ptr);
    277 			na->na_blocks = IXDR_GET_U_INT32(ptr);
    278 			na->na_fsid = IXDR_GET_U_INT32(ptr);
    279 			na->na_nodeid = IXDR_GET_U_INT32(ptr);
    280 			na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
    281 			na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
    282 			na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
    283 			na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
    284 			na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
    285 			na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
    286 		} else {
    287 			IXDR_PUT_ENUM(ptr, na->na_type);
    288 			IXDR_PUT_U_INT32(ptr, na->na_mode);
    289 			IXDR_PUT_U_INT32(ptr, na->na_nlink);
    290 			IXDR_PUT_U_INT32(ptr, na->na_uid);
    291 			IXDR_PUT_U_INT32(ptr, na->na_gid);
    292 			IXDR_PUT_U_INT32(ptr, na->na_size);
    293 			IXDR_PUT_U_INT32(ptr, na->na_blocksize);
    294 			IXDR_PUT_U_INT32(ptr, na->na_rdev);
    295 			IXDR_PUT_U_INT32(ptr, na->na_blocks);
    296 			IXDR_PUT_U_INT32(ptr, na->na_fsid);
    297 			IXDR_PUT_U_INT32(ptr, na->na_nodeid);
    298 			IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
    299 			IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
    300 			IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
    301 			IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
    302 			IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
    303 			IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
    304 		}
    305 		return (TRUE);
    306 	}
    307 
    308 	if (xdr_enum(xdrs, (enum_t *)&na->na_type) &&
    309 	    xdr_u_int(xdrs, &na->na_mode) &&
    310 	    xdr_u_int(xdrs, &na->na_nlink) &&
    311 	    xdr_u_int(xdrs, &na->na_uid) &&
    312 	    xdr_u_int(xdrs, &na->na_gid) &&
    313 	    xdr_u_int(xdrs, &na->na_size) &&
    314 	    xdr_u_int(xdrs, &na->na_blocksize) &&
    315 	    xdr_u_int(xdrs, &na->na_rdev) &&
    316 	    xdr_u_int(xdrs, &na->na_blocks) &&
    317 	    xdr_u_int(xdrs, &na->na_fsid) &&
    318 	    xdr_u_int(xdrs, &na->na_nodeid) &&
    319 	    xdr_nfs2_timeval(xdrs, &na->na_atime) &&
    320 	    xdr_nfs2_timeval(xdrs, &na->na_mtime) &&
    321 	    xdr_nfs2_timeval(xdrs, &na->na_ctime)) {
    322 		return (TRUE);
    323 	}
    324 	return (FALSE);
    325 }
    326 
    327 #ifdef _LITTLE_ENDIAN
    328 bool_t
    329 xdr_fastfattr(XDR *xdrs, struct nfsfattr *na)
    330 {
    331 	if (xdrs->x_op == XDR_FREE)
    332 		return (TRUE);
    333 	if (xdrs->x_op == XDR_DECODE)
    334 		return (FALSE);
    335 
    336 	na->na_type = htonl(na->na_type);
    337 	na->na_mode = htonl(na->na_mode);
    338 	na->na_nlink = htonl(na->na_nlink);
    339 	na->na_uid = htonl(na->na_uid);
    340 	na->na_gid = htonl(na->na_gid);
    341 	na->na_size = htonl(na->na_size);
    342 	na->na_blocksize = htonl(na->na_blocksize);
    343 	na->na_rdev = htonl(na->na_rdev);
    344 	na->na_blocks = htonl(na->na_blocks);
    345 	na->na_fsid = htonl(na->na_fsid);
    346 	na->na_nodeid = htonl(na->na_nodeid);
    347 	na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
    348 	na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
    349 	na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
    350 	na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
    351 	na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
    352 	na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
    353 	return (TRUE);
    354 }
    355 #endif
    356 
    357 bool_t
    358 xdr_readlink(XDR *xdrs, fhandle_t *fh)
    359 {
    360 	rdma_chunkinfo_t rci;
    361 	struct xdr_ops *xops = xdrrdma_xops();
    362 
    363 	if (xdr_fhandle(xdrs, fh)) {
    364 		if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
    365 		    xdrs->x_op == XDR_ENCODE) {
    366 			rci.rci_type = RCI_REPLY_CHUNK;
    367 			rci.rci_len = MAXPATHLEN;
    368 			XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
    369 		}
    370 
    371 		return (TRUE);
    372 	}
    373 	return (FALSE);
    374 }
    375 
    376 /*
    377  * Arguments to remote read
    378  */
    379 bool_t
    380 xdr_readargs(XDR *xdrs, struct nfsreadargs *ra)
    381 {
    382 	int32_t *ptr;
    383 	int32_t *fhp;
    384 	rdma_chunkinfo_t rci;
    385 	rdma_wlist_conn_info_t rwci;
    386 	struct xdr_ops *xops = xdrrdma_xops();
    387 
    388 	if (xdrs->x_op == XDR_FREE)
    389 		return (TRUE);
    390 
    391 	ptr = XDR_INLINE(xdrs,
    392 	    RNDUP(sizeof (fhandle_t)) + 3 * BYTES_PER_XDR_UNIT);
    393 	if (ptr != NULL) {
    394 		if (xdrs->x_op == XDR_DECODE) {
    395 			fhp = (int32_t *)&ra->ra_fhandle;
    396 			*fhp++ = *ptr++;
    397 			*fhp++ = *ptr++;
    398 			*fhp++ = *ptr++;
    399 			*fhp++ = *ptr++;
    400 			*fhp++ = *ptr++;
    401 			*fhp++ = *ptr++;
    402 			*fhp++ = *ptr++;
    403 			*fhp = *ptr++;
    404 			ra->ra_offset = IXDR_GET_INT32(ptr);
    405 			ra->ra_count = IXDR_GET_INT32(ptr);
    406 			ra->ra_totcount = IXDR_GET_INT32(ptr);
    407 		} else {
    408 			fhp = (int32_t *)&ra->ra_fhandle;
    409 			*ptr++ = *fhp++;
    410 			*ptr++ = *fhp++;
    411 			*ptr++ = *fhp++;
    412 			*ptr++ = *fhp++;
    413 			*ptr++ = *fhp++;
    414 			*ptr++ = *fhp++;
    415 			*ptr++ = *fhp++;
    416 			*ptr++ = *fhp;
    417 			IXDR_PUT_INT32(ptr, ra->ra_offset);
    418 			IXDR_PUT_INT32(ptr, ra->ra_count);
    419 			IXDR_PUT_INT32(ptr, ra->ra_totcount);
    420 		}
    421 	} else {
    422 		if (!xdr_fhandle(xdrs, &ra->ra_fhandle) ||
    423 		    !xdr_u_int(xdrs, &ra->ra_offset) ||
    424 		    !xdr_u_int(xdrs, &ra->ra_count) ||
    425 		    !xdr_u_int(xdrs, &ra->ra_totcount)) {
    426 			return (FALSE);
    427 		}
    428 	}
    429 
    430 	if (ra->ra_count > NFS_MAXDATA)
    431 		return (FALSE);
    432 
    433 	ra->ra_wlist = NULL;
    434 	ra->ra_conn = NULL;
    435 
    436 	/* If this is xdrrdma_sizeof, record the expect response size */
    437 	if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
    438 		rci.rci_type = RCI_WRITE_ADDR_CHUNK;
    439 		rci.rci_len = ra->ra_count;
    440 		(void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
    441 	}
    442 	/* Nothing special to do, return */
    443 	if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
    444 		return (TRUE);
    445 
    446 	if (xdrs->x_op == XDR_ENCODE) {
    447 		/* Place the target data location into the RDMA header */
    448 		rci.rci_type = RCI_WRITE_ADDR_CHUNK;
    449 		rci.rci_a.rci_addr = ra->ra_data;
    450 		rci.rci_len = ra->ra_count;
    451 		rci.rci_clpp = &ra->ra_wlist;
    452 
    453 		return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
    454 	}
    455 
    456 	/* XDR_DECODE case */
    457 	(void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
    458 	ra->ra_wlist = rwci.rwci_wlist;
    459 	ra->ra_conn = rwci.rwci_conn;
    460 
    461 	return (TRUE);
    462 }
    463 
    464 
    465 /*
    466  * Status OK portion of remote read reply
    467  */
    468 bool_t
    469 xdr_rrok(XDR *xdrs, struct nfsrrok *rrok)
    470 {
    471 	bool_t ret;
    472 	mblk_t *mp;
    473 	struct xdr_ops *xops = xdrrdma_xops();
    474 
    475 	if (xdr_fattr(xdrs, &rrok->rrok_attr) == FALSE)
    476 		return (FALSE);
    477 
    478 	/* deal with RDMA separately */
    479 	if (xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) {
    480 		if (xdrs->x_op == XDR_ENCODE &&
    481 		    rrok->rrok_mp != NULL) {
    482 			ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
    483 			    &rrok->rrok_count, NFS_MAXDATA);
    484 			return (ret);
    485 		}
    486 
    487 		if (xdrs->x_op == XDR_ENCODE) {
    488 			if (xdr_u_int(xdrs, &rrok->rrok_count) == FALSE) {
    489 				return (FALSE);
    490 			}
    491 			/*
    492 			 * If read data sent by wlist (RDMA_WRITE), don't do
    493 			 * xdr_bytes() below.   RDMA_WRITE transfers the data.
    494 			 */
    495 			if (rrok->rrok_wlist) {
    496 				if (rrok->rrok_count != 0) {
    497 					return (xdrrdma_send_read_data(
    498 					    xdrs, rrok->rrok_count,
    499 					    rrok->rrok_wlist));
    500 				}
    501 				return (TRUE);
    502 			}
    503 			if (rrok->rrok_count == 0) {
    504 				return (TRUE);
    505 			}
    506 		} else {
    507 			struct clist *cl;
    508 			uint32_t count;
    509 
    510 			XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
    511 
    512 			if (cl) {
    513 				if (!xdr_u_int(xdrs, &count))
    514 					return (FALSE);
    515 				if (count == 0) {
    516 					rrok->rrok_wlist_len = 0;
    517 					rrok->rrok_count = 0;
    518 				} else {
    519 					rrok->rrok_wlist_len = clist_len(cl);
    520 					if (rrok->rrok_wlist_len !=
    521 					    roundup(count,
    522 					    BYTES_PER_XDR_UNIT)) {
    523 						rrok->rrok_wlist_len = 0;
    524 						rrok->rrok_count = 0;
    525 						return (FALSE);
    526 					}
    527 					rrok->rrok_count = count;
    528 				}
    529 				return (TRUE);
    530 			}
    531 		}
    532 		ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
    533 		    &rrok->rrok_count, NFS_MAXDATA);
    534 
    535 		return (ret);
    536 	}
    537 
    538 	if (xdrs->x_op == XDR_ENCODE) {
    539 		int i, rndup;
    540 
    541 		mp = rrok->rrok_mp;
    542 		if (mp != NULL && xdrs->x_ops == &xdrmblk_ops) {
    543 			mp->b_wptr += rrok->rrok_count;
    544 			rndup = BYTES_PER_XDR_UNIT -
    545 			    (rrok->rrok_count % BYTES_PER_XDR_UNIT);
    546 			if (rndup != BYTES_PER_XDR_UNIT)
    547 				for (i = 0; i < rndup; i++)
    548 					*mp->b_wptr++ = '\0';
    549 			if (xdrmblk_putmblk(xdrs, mp,
    550 			    rrok->rrok_count) == TRUE) {
    551 				rrok->rrok_mp = NULL;
    552 				return (TRUE);
    553 			}
    554 		}
    555 
    556 		/*
    557 		 * Fall thru for the xdr_bytes()
    558 		 *
    559 		 * Note: the mblk mp will be freed in rfs_rdfree
    560 		 */
    561 	}
    562 
    563 	ret = xdr_bytes(xdrs, (char **)&rrok->rrok_data,
    564 	    &rrok->rrok_count, NFS_MAXDATA);
    565 
    566 	return (ret);
    567 }
    568 
    569 static struct xdr_discrim rdres_discrim[2] = {
    570 	{ NFS_OK, xdr_rrok },
    571 	{ __dontcare__, NULL_xdrproc_t }
    572 };
    573 
    574 /*
    575  * Reply from remote read
    576  */
    577 bool_t
    578 xdr_rdresult(XDR *xdrs, struct nfsrdresult *rr)
    579 {
    580 	return (xdr_union(xdrs, (enum_t *)&(rr->rr_status),
    581 	    (caddr_t)&(rr->rr_ok), rdres_discrim, xdr_void));
    582 }
    583 
    584 /*
    585  * File attributes which can be set
    586  */
    587 bool_t
    588 xdr_sattr(XDR *xdrs, struct nfssattr *sa)
    589 {
    590 	if (xdr_u_int(xdrs, &sa->sa_mode) &&
    591 	    xdr_u_int(xdrs, &sa->sa_uid) &&
    592 	    xdr_u_int(xdrs, &sa->sa_gid) &&
    593 	    xdr_u_int(xdrs, &sa->sa_size) &&
    594 	    xdr_nfs2_timeval(xdrs, &sa->sa_atime) &&
    595 	    xdr_nfs2_timeval(xdrs, &sa->sa_mtime)) {
    596 		return (TRUE);
    597 	}
    598 	return (FALSE);
    599 }
    600 
    601 static struct xdr_discrim attrstat_discrim[2] = {
    602 	{ (int)NFS_OK, xdr_fattr },
    603 	{ __dontcare__, NULL_xdrproc_t }
    604 };
    605 
    606 /*
    607  * Reply status with file attributes
    608  */
    609 bool_t
    610 xdr_attrstat(XDR *xdrs, struct nfsattrstat *ns)
    611 {
    612 	return (xdr_union(xdrs, (enum_t *)&(ns->ns_status),
    613 	    (caddr_t)&(ns->ns_attr), attrstat_discrim, xdr_void));
    614 }
    615 
    616 /*
    617  * Fast reply status with file attributes
    618  */
    619 bool_t
    620 xdr_fastattrstat(XDR *xdrs, struct nfsattrstat *ns)
    621 {
    622 #if defined(_LITTLE_ENDIAN)
    623 	/*
    624 	 * we deal with the discriminator;  it's an enum
    625 	 */
    626 	if (!xdr_fastenum(xdrs, (enum_t *)&ns->ns_status))
    627 		return (FALSE);
    628 
    629 	if (ns->ns_status == NFS_OK)
    630 		return (xdr_fastfattr(xdrs, &ns->ns_attr));
    631 #elif defined(_BIG_ENDIAN)
    632 	if (ns->ns_status == NFS_OK)
    633 		return (TRUE);
    634 #endif
    635 	return (xdr_fastshorten(xdrs, sizeof (*ns)));
    636 }
    637 
    638 /*
    639  * NFS_OK part of read sym link reply union
    640  */
    641 bool_t
    642 xdr_srok(XDR *xdrs, struct nfssrok *srok)
    643 {
    644 	/*
    645 	 * It is just as efficient to xdr_bytes
    646 	 * an array of unknown length as to inline copy it.
    647 	 */
    648 	return (xdr_bytes(xdrs, &srok->srok_data, &srok->srok_count,
    649 	    NFS_MAXPATHLEN));
    650 }
    651 
    652 static struct xdr_discrim rdlnres_discrim[2] = {
    653 	{ (int)NFS_OK, xdr_srok },
    654 	{ __dontcare__, NULL_xdrproc_t }
    655 };
    656 
    657 /*
    658  * Result of reading symbolic link
    659  */
    660 bool_t
    661 xdr_rdlnres(XDR *xdrs, struct nfsrdlnres *rl)
    662 {
    663 	return (xdr_union(xdrs, (enum_t *)&(rl->rl_status),
    664 	    (caddr_t)&(rl->rl_srok), rdlnres_discrim, xdr_void));
    665 }
    666 
    667 /*
    668  * Arguments to readdir
    669  */
    670 bool_t
    671 xdr_rddirargs(XDR *xdrs, struct nfsrddirargs *rda)
    672 {
    673 	int32_t *ptr;
    674 	int32_t *fhp;
    675 	rdma_chunkinfo_t rci;
    676 	struct xdr_ops *xops = xdrrdma_xops();
    677 
    678 	if (xdrs->x_op == XDR_FREE)
    679 		return (TRUE);
    680 
    681 	ptr = XDR_INLINE(xdrs,
    682 	    RNDUP(sizeof (fhandle_t)) + 2 * BYTES_PER_XDR_UNIT);
    683 
    684 	if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
    685 	    xdrs->x_op == XDR_ENCODE) {
    686 		rci.rci_type = RCI_REPLY_CHUNK;
    687 		rci.rci_len = rda->rda_count;
    688 		XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
    689 	}
    690 
    691 	if (ptr != NULL) {
    692 		if (xdrs->x_op == XDR_DECODE) {
    693 			fhp = (int32_t *)&rda->rda_fh;
    694 			*fhp++ = *ptr++;
    695 			*fhp++ = *ptr++;
    696 			*fhp++ = *ptr++;
    697 			*fhp++ = *ptr++;
    698 			*fhp++ = *ptr++;
    699 			*fhp++ = *ptr++;
    700 			*fhp++ = *ptr++;
    701 			*fhp = *ptr++;
    702 			rda->rda_offset = IXDR_GET_U_INT32(ptr);
    703 			rda->rda_count = IXDR_GET_U_INT32(ptr);
    704 		} else {
    705 			fhp = (int32_t *)&rda->rda_fh;
    706 			*ptr++ = *fhp++;
    707 			*ptr++ = *fhp++;
    708 			*ptr++ = *fhp++;
    709 			*ptr++ = *fhp++;
    710 			*ptr++ = *fhp++;
    711 			*ptr++ = *fhp++;
    712 			*ptr++ = *fhp++;
    713 			*ptr++ = *fhp;
    714 			IXDR_PUT_U_INT32(ptr, rda->rda_offset);
    715 			IXDR_PUT_U_INT32(ptr, rda->rda_count);
    716 		}
    717 		return (TRUE);
    718 	}
    719 
    720 	if (xdr_fhandle(xdrs, &rda->rda_fh) &&
    721 	    xdr_u_int(xdrs, &rda->rda_offset) &&
    722 	    xdr_u_int(xdrs, &rda->rda_count)) {
    723 		return (TRUE);
    724 	}
    725 	return (FALSE);
    726 }
    727 
    728 
    729 /*
    730  * Directory read reply:
    731  * union (enum status) {
    732  *	NFS_OK: entlist;
    733  *		boolean eof;
    734  *	default:
    735  * }
    736  *
    737  * Directory entries
    738  *	struct  direct {
    739  *		off_t   d_off;			* offset of next entry *
    740  *		u_int	d_fileno;		* inode number of entry *
    741  *		u_short d_reclen;		* length of this record *
    742  *		u_short d_namlen;		* length of string in d_name *
    743  *		char    d_name[MAXNAMLEN + 1];	* name no longer than this *
    744  *	};
    745  * are on the wire as:
    746  * union entlist (boolean valid) {
    747  * 	TRUE:	struct otw_dirent;
    748  *		u_int nxtoffset;
    749  *		union entlist;
    750  *	FALSE:
    751  * }
    752  * where otw_dirent is:
    753  * 	struct dirent {
    754  *		u_int	de_fid;
    755  *		string	de_name<NFS_MAXNAMELEN>;
    756  *	}
    757  */
    758 
    759 #ifdef nextdp
    760 #undef	nextdp
    761 #endif
    762 #define	nextdp(dp)	((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
    763 #ifdef roundup
    764 #undef	roundup
    765 #endif
    766 #define	roundup(x, y)	((((x) + ((y) - 1)) / (y)) * (y))
    767 
    768 /*
    769  * ENCODE ONLY
    770  */
    771 bool_t
    772 xdr_putrddirres(XDR *xdrs, struct nfsrddirres *rd)
    773 {
    774 	struct dirent64 *dp;
    775 	char *name;
    776 	int size;
    777 	uint_t namlen;
    778 	bool_t true = TRUE;
    779 	bool_t false = FALSE;
    780 	int entrysz;
    781 	int tofit;
    782 	int bufsize;
    783 	uint32_t ino, off;
    784 
    785 	if (xdrs->x_op != XDR_ENCODE)
    786 		return (FALSE);
    787 	if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
    788 		return (FALSE);
    789 	if (rd->rd_status != NFS_OK)
    790 		return (TRUE);
    791 
    792 	bufsize = 1 * BYTES_PER_XDR_UNIT;
    793 	for (size = rd->rd_size, dp = rd->rd_entries;
    794 	    size > 0;
    795 	    size -= dp->d_reclen, dp = nextdp(dp)) {
    796 		if (dp->d_reclen == 0 /* || DIRSIZ(dp) > dp->d_reclen */)
    797 			return (FALSE);
    798 		if (dp->d_ino == 0)
    799 			continue;
    800 		ino = (uint32_t)dp->d_ino; /* for LP64 we clip the bits */
    801 		if (dp->d_ino != (ino64_t)ino)	/* and they better be zeros */
    802 			return (FALSE);
    803 		off = (uint32_t)dp->d_off;
    804 		name = dp->d_name;
    805 		namlen = (uint_t)strlen(name);
    806 		entrysz = (1 + 1 + 1 + 1) * BYTES_PER_XDR_UNIT +
    807 		    roundup(namlen, BYTES_PER_XDR_UNIT);
    808 		tofit = entrysz + 2 * BYTES_PER_XDR_UNIT;
    809 		if (bufsize + tofit > rd->rd_bufsize) {
    810 			rd->rd_eof = FALSE;
    811 			break;
    812 		}
    813 		if (!xdr_bool(xdrs, &true) ||
    814 		    !xdr_u_int(xdrs, &ino) ||
    815 		    !xdr_bytes(xdrs, &name, &namlen, NFS_MAXNAMLEN) ||
    816 		    !xdr_u_int(xdrs, &off)) {
    817 			return (FALSE);
    818 		}
    819 		bufsize += entrysz;
    820 	}
    821 	if (!xdr_bool(xdrs, &false))
    822 		return (FALSE);
    823 	if (!xdr_bool(xdrs, &rd->rd_eof))
    824 		return (FALSE);
    825 	return (TRUE);
    826 }
    827 
    828 /*
    829  * DECODE ONLY
    830  */
    831 bool_t
    832 xdr_getrddirres(XDR *xdrs, struct nfsrddirres *rd)
    833 {
    834 	struct dirent64 *dp;
    835 	uint_t namlen;
    836 	int size;
    837 	bool_t valid;
    838 	uint32_t offset;
    839 	uint_t fileid, this_reclen;
    840 
    841 	if (xdrs->x_op != XDR_DECODE)
    842 		return (FALSE);
    843 
    844 	if (!xdr_enum(xdrs, (enum_t *)&rd->rd_status))
    845 		return (FALSE);
    846 	if (rd->rd_status != NFS_OK)
    847 		return (TRUE);
    848 
    849 	size = rd->rd_size;
    850 	dp = rd->rd_entries;
    851 	offset = rd->rd_offset;
    852 	for (;;) {
    853 		if (!xdr_bool(xdrs, &valid))
    854 			return (FALSE);
    855 		if (!valid)
    856 			break;
    857 		if (!xdr_u_int(xdrs, &fileid) ||
    858 		    !xdr_u_int(xdrs, &namlen))
    859 			return (FALSE);
    860 		this_reclen = DIRENT64_RECLEN(namlen);
    861 		if (this_reclen > size) {
    862 			rd->rd_eof = FALSE;
    863 			goto bufovflw;
    864 		}
    865 		if (!xdr_opaque(xdrs, dp->d_name, namlen)||
    866 		    !xdr_u_int(xdrs, &offset)) {
    867 			return (FALSE);
    868 		}
    869 		bzero(&dp->d_name[namlen],
    870 		    DIRENT64_NAMELEN(this_reclen) - namlen);
    871 		dp->d_ino = (ino64_t)fileid;
    872 		dp->d_reclen = this_reclen;
    873 		dp->d_off = (off64_t)offset;
    874 		size -= dp->d_reclen;
    875 		dp = nextdp(dp);
    876 	}
    877 	if (!xdr_bool(xdrs, &rd->rd_eof))
    878 		return (FALSE);
    879 bufovflw:
    880 	rd->rd_size = (uint32_t)((char *)dp - (char *)(rd->rd_entries));
    881 	rd->rd_offset = offset;
    882 	return (TRUE);
    883 }
    884 
    885 /*
    886  * Arguments for directory operations
    887  */
    888 bool_t
    889 xdr_diropargs(XDR *xdrs, struct nfsdiropargs *da)
    890 {
    891 	int32_t *ptr;
    892 	int32_t *fhp;
    893 	uint32_t size;
    894 	uint32_t nodesize;
    895 	int i;
    896 	int rndup;
    897 	char *cptr;
    898 
    899 	if (xdrs->x_op == XDR_DECODE) {
    900 		da->da_fhandle = &da->da_fhandle_buf;
    901 		ptr = XDR_INLINE(xdrs, RNDUP(sizeof (fhandle_t)) +
    902 		    1 * BYTES_PER_XDR_UNIT);
    903 		if (ptr != NULL) {
    904 			fhp = (int32_t *)da->da_fhandle;
    905 			*fhp++ = *ptr++;
    906 			*fhp++ = *ptr++;
    907 			*fhp++ = *ptr++;
    908 			*fhp++ = *ptr++;
    909 			*fhp++ = *ptr++;
    910 			*fhp++ = *ptr++;
    911 			*fhp++ = *ptr++;
    912 			*fhp = *ptr++;
    913 			size = IXDR_GET_U_INT32(ptr);
    914 			if (size > NFS_MAXNAMLEN)
    915 				return (FALSE);
    916 			nodesize = size + 1;
    917 			if (nodesize == 0)
    918 				return (TRUE);
    919 			if (da->da_name == NULL) {
    920 				da->da_name = kmem_alloc(nodesize, KM_NOSLEEP);
    921 				if (da->da_name == NULL)
    922 					return (FALSE);
    923 				da->da_flags |= DA_FREENAME;
    924 			}
    925 			ptr = XDR_INLINE(xdrs, RNDUP(size));
    926 			if (ptr == NULL) {
    927 				if (!xdr_opaque(xdrs, da->da_name, size)) {
    928 					if (da->da_flags & DA_FREENAME) {
    929 						kmem_free(da->da_name,
    930 						    nodesize);
    931 						da->da_name = NULL;
    932 					}
    933 					return (FALSE);
    934 				}
    935 				da->da_name[size] = '\0';
    936 				if (strlen(da->da_name) != size) {
    937 					if (da->da_flags & DA_FREENAME) {
    938 						kmem_free(da->da_name,
    939 						    nodesize);
    940 						da->da_name = NULL;
    941 					}
    942 					return (FALSE);
    943 				}
    944 				return (TRUE);
    945 			}
    946 			bcopy(ptr, da->da_name, size);
    947 			da->da_name[size] = '\0';
    948 			if (strlen(da->da_name) != size) {
    949 				if (da->da_flags & DA_FREENAME) {
    950 					kmem_free(da->da_name, nodesize);
    951 					da->da_name = NULL;
    952 				}
    953 				return (FALSE);
    954 			}
    955 			return (TRUE);
    956 		}
    957 		if (da->da_name == NULL)
    958 			da->da_flags |= DA_FREENAME;
    959 	}
    960 
    961 	if (xdrs->x_op == XDR_ENCODE) {
    962 		size = (uint32_t)strlen(da->da_name);
    963 		if (size > NFS_MAXNAMLEN)
    964 			return (FALSE);
    965 		ptr = XDR_INLINE(xdrs, (int)(RNDUP(sizeof (fhandle_t)) +
    966 		    1 * BYTES_PER_XDR_UNIT + RNDUP(size)));
    967 		if (ptr != NULL) {
    968 			fhp = (int32_t *)da->da_fhandle;
    969 			*ptr++ = *fhp++;
    970 			*ptr++ = *fhp++;
    971 			*ptr++ = *fhp++;
    972 			*ptr++ = *fhp++;
    973 			*ptr++ = *fhp++;
    974 			*ptr++ = *fhp++;
    975 			*ptr++ = *fhp++;
    976 			*ptr++ = *fhp;
    977 			IXDR_PUT_U_INT32(ptr, (uint32_t)size);
    978 			bcopy(da->da_name, ptr, size);
    979 			rndup = BYTES_PER_XDR_UNIT -
    980 			    (size % BYTES_PER_XDR_UNIT);
    981 			if (rndup != BYTES_PER_XDR_UNIT) {
    982 				cptr = (char *)ptr + size;
    983 				for (i = 0; i < rndup; i++)
    984 					*cptr++ = '\0';
    985 			}
    986 			return (TRUE);
    987 		}
    988 	}
    989 
    990 	if (xdrs->x_op == XDR_FREE) {
    991 		if (da->da_name == NULL)
    992 			return (TRUE);
    993 		size = (uint32_t)strlen(da->da_name);
    994 		if (size > NFS_MAXNAMLEN)
    995 			return (FALSE);
    996 		if (da->da_flags & DA_FREENAME)
    997 			kmem_free(da->da_name, size + 1);
    998 		da->da_name = NULL;
    999 		return (TRUE);
   1000 	}
   1001 
   1002 	if (xdr_fhandle(xdrs, da->da_fhandle) &&
   1003 	    xdr_string(xdrs, &da->da_name, NFS_MAXNAMLEN)) {
   1004 		return (TRUE);
   1005 	}
   1006 	return (FALSE);
   1007 }
   1008 
   1009 /*
   1010  * NFS_OK part of directory operation result
   1011  */
   1012 bool_t
   1013 xdr_drok(XDR *xdrs, struct nfsdrok *drok)
   1014 {
   1015 	int32_t *ptr;
   1016 	int32_t *fhp;
   1017 	struct nfsfattr *na;
   1018 
   1019 	if (xdrs->x_op == XDR_FREE)
   1020 		return (TRUE);
   1021 
   1022 	ptr = XDR_INLINE(xdrs,
   1023 	    RNDUP(sizeof (fhandle_t)) + 17 * BYTES_PER_XDR_UNIT);
   1024 	if (ptr != NULL) {
   1025 		if (xdrs->x_op == XDR_DECODE) {
   1026 			fhp = (int32_t *)&drok->drok_fhandle;
   1027 			*fhp++ = *ptr++;
   1028 			*fhp++ = *ptr++;
   1029 			*fhp++ = *ptr++;
   1030 			*fhp++ = *ptr++;
   1031 			*fhp++ = *ptr++;
   1032 			*fhp++ = *ptr++;
   1033 			*fhp++ = *ptr++;
   1034 			*fhp = *ptr++;
   1035 			na = &drok->drok_attr;
   1036 			na->na_type = IXDR_GET_ENUM(ptr, enum nfsftype);
   1037 			na->na_mode = IXDR_GET_U_INT32(ptr);
   1038 			na->na_nlink = IXDR_GET_U_INT32(ptr);
   1039 			na->na_uid = IXDR_GET_U_INT32(ptr);
   1040 			na->na_gid = IXDR_GET_U_INT32(ptr);
   1041 			na->na_size = IXDR_GET_U_INT32(ptr);
   1042 			na->na_blocksize = IXDR_GET_U_INT32(ptr);
   1043 			na->na_rdev = IXDR_GET_U_INT32(ptr);
   1044 			na->na_blocks = IXDR_GET_U_INT32(ptr);
   1045 			na->na_fsid = IXDR_GET_U_INT32(ptr);
   1046 			na->na_nodeid = IXDR_GET_U_INT32(ptr);
   1047 			na->na_atime.tv_sec = IXDR_GET_U_INT32(ptr);
   1048 			na->na_atime.tv_usec = IXDR_GET_U_INT32(ptr);
   1049 			na->na_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
   1050 			na->na_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
   1051 			na->na_ctime.tv_sec = IXDR_GET_U_INT32(ptr);
   1052 			na->na_ctime.tv_usec = IXDR_GET_U_INT32(ptr);
   1053 		} else {
   1054 			fhp = (int32_t *)&drok->drok_fhandle;
   1055 			*ptr++ = *fhp++;
   1056 			*ptr++ = *fhp++;
   1057 			*ptr++ = *fhp++;
   1058 			*ptr++ = *fhp++;
   1059 			*ptr++ = *fhp++;
   1060 			*ptr++ = *fhp++;
   1061 			*ptr++ = *fhp++;
   1062 			*ptr++ = *fhp;
   1063 			na = &drok->drok_attr;
   1064 			IXDR_PUT_ENUM(ptr, na->na_type);
   1065 			IXDR_PUT_U_INT32(ptr, na->na_mode);
   1066 			IXDR_PUT_U_INT32(ptr, na->na_nlink);
   1067 			IXDR_PUT_U_INT32(ptr, na->na_uid);
   1068 			IXDR_PUT_U_INT32(ptr, na->na_gid);
   1069 			IXDR_PUT_U_INT32(ptr, na->na_size);
   1070 			IXDR_PUT_U_INT32(ptr, na->na_blocksize);
   1071 			IXDR_PUT_U_INT32(ptr, na->na_rdev);
   1072 			IXDR_PUT_U_INT32(ptr, na->na_blocks);
   1073 			IXDR_PUT_U_INT32(ptr, na->na_fsid);
   1074 			IXDR_PUT_U_INT32(ptr, na->na_nodeid);
   1075 			IXDR_PUT_U_INT32(ptr, na->na_atime.tv_sec);
   1076 			IXDR_PUT_U_INT32(ptr, na->na_atime.tv_usec);
   1077 			IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_sec);
   1078 			IXDR_PUT_U_INT32(ptr, na->na_mtime.tv_usec);
   1079 			IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_sec);
   1080 			IXDR_PUT_U_INT32(ptr, na->na_ctime.tv_usec);
   1081 		}
   1082 		return (TRUE);
   1083 	}
   1084 
   1085 	if (xdr_fhandle(xdrs, &drok->drok_fhandle) &&
   1086 	    xdr_fattr(xdrs, &drok->drok_attr)) {
   1087 		return (TRUE);
   1088 	}
   1089 	return (FALSE);
   1090 }
   1091 
   1092 #ifdef _LITTLE_ENDIAN
   1093 bool_t
   1094 xdr_fastdrok(XDR *xdrs, struct nfsdrok *drok)
   1095 {
   1096 	struct nfsfattr *na;
   1097 
   1098 	if (xdrs->x_op == XDR_FREE)
   1099 		return (TRUE);
   1100 	if (xdrs->x_op == XDR_DECODE)
   1101 		return (FALSE);
   1102 
   1103 	na = &drok->drok_attr;
   1104 	na->na_type = (enum nfsftype)htonl(na->na_type);
   1105 	na->na_mode = (uint32_t)htonl(na->na_mode);
   1106 	na->na_nlink = (uint32_t)htonl(na->na_nlink);
   1107 	na->na_uid = (uint32_t)htonl(na->na_uid);
   1108 	na->na_gid = (uint32_t)htonl(na->na_gid);
   1109 	na->na_size = (uint32_t)htonl(na->na_size);
   1110 	na->na_blocksize = (uint32_t)htonl(na->na_blocksize);
   1111 	na->na_rdev = (uint32_t)htonl(na->na_rdev);
   1112 	na->na_blocks = (uint32_t)htonl(na->na_blocks);
   1113 	na->na_fsid = (uint32_t)htonl(na->na_fsid);
   1114 	na->na_nodeid = (uint32_t)htonl(na->na_nodeid);
   1115 	na->na_atime.tv_sec = htonl(na->na_atime.tv_sec);
   1116 	na->na_atime.tv_usec = htonl(na->na_atime.tv_usec);
   1117 	na->na_mtime.tv_sec = htonl(na->na_mtime.tv_sec);
   1118 	na->na_mtime.tv_usec = htonl(na->na_mtime.tv_usec);
   1119 	na->na_ctime.tv_sec = htonl(na->na_ctime.tv_sec);
   1120 	na->na_ctime.tv_usec = htonl(na->na_ctime.tv_usec);
   1121 	return (TRUE);
   1122 }
   1123 #endif
   1124 
   1125 static struct xdr_discrim diropres_discrim[2] = {
   1126 	{ NFS_OK, xdr_drok },
   1127 	{ __dontcare__, NULL_xdrproc_t }
   1128 };
   1129 
   1130 /*
   1131  * Results from directory operation
   1132  */
   1133 bool_t
   1134 xdr_diropres(XDR *xdrs, struct nfsdiropres *dr)
   1135 {
   1136 	return (xdr_union(xdrs, (enum_t *)&(dr->dr_status),
   1137 	    (caddr_t)&(dr->dr_drok), diropres_discrim, xdr_void));
   1138 }
   1139 
   1140 /*
   1141  * Results from directory operation
   1142  */
   1143 bool_t
   1144 xdr_fastdiropres(XDR *xdrs, struct nfsdiropres *dr)
   1145 {
   1146 #if defined(_LITTLE_ENDIAN)
   1147 	/*
   1148 	 * we deal with the discriminator;  it's an enum
   1149 	 */
   1150 	if (!xdr_fastenum(xdrs, (enum_t *)&dr->dr_status))
   1151 		return (FALSE);
   1152 
   1153 	if (dr->dr_status == NFS_OK)
   1154 		return (xdr_fastdrok(xdrs, &dr->dr_drok));
   1155 #elif defined(_BIG_ENDIAN)
   1156 	if (dr->dr_status == NFS_OK)
   1157 		return (TRUE);
   1158 #endif
   1159 	return (xdr_fastshorten(xdrs, sizeof (*dr)));
   1160 }
   1161 
   1162 /*
   1163  * Time Structure, unsigned
   1164  */
   1165 bool_t
   1166 xdr_nfs2_timeval(XDR *xdrs, struct nfs2_timeval *tv)
   1167 {
   1168 	if (xdr_u_int(xdrs, &tv->tv_sec) &&
   1169 	    xdr_u_int(xdrs, &tv->tv_usec))
   1170 		return (TRUE);
   1171 	return (FALSE);
   1172 }
   1173 
   1174 /*
   1175  * arguments to setattr
   1176  */
   1177 bool_t
   1178 xdr_saargs(XDR *xdrs, struct nfssaargs *argp)
   1179 {
   1180 	int32_t *ptr;
   1181 	int32_t *arg;
   1182 	struct nfssattr *sa;
   1183 
   1184 	if (xdrs->x_op == XDR_FREE)
   1185 		return (TRUE);
   1186 
   1187 	ptr = XDR_INLINE(xdrs,
   1188 	    RNDUP(sizeof (fhandle_t)) + 8 * BYTES_PER_XDR_UNIT);
   1189 	if (ptr != NULL) {
   1190 		if (xdrs->x_op == XDR_DECODE) {
   1191 			arg = (int32_t *)&argp->saa_fh;
   1192 			*arg++ = *ptr++;
   1193 			*arg++ = *ptr++;
   1194 			*arg++ = *ptr++;
   1195 			*arg++ = *ptr++;
   1196 			*arg++ = *ptr++;
   1197 			*arg++ = *ptr++;
   1198 			*arg++ = *ptr++;
   1199 			*arg = *ptr++;
   1200 			sa = &argp->saa_sa;
   1201 			sa->sa_mode = IXDR_GET_U_INT32(ptr);
   1202 			sa->sa_uid = IXDR_GET_U_INT32(ptr);
   1203 			sa->sa_gid = IXDR_GET_U_INT32(ptr);
   1204 			sa->sa_size = IXDR_GET_U_INT32(ptr);
   1205 			sa->sa_atime.tv_sec = IXDR_GET_U_INT32(ptr);
   1206 			sa->sa_atime.tv_usec = IXDR_GET_U_INT32(ptr);
   1207 			sa->sa_mtime.tv_sec = IXDR_GET_U_INT32(ptr);
   1208 			sa->sa_mtime.tv_usec = IXDR_GET_U_INT32(ptr);
   1209 		} else {
   1210 			arg = (int32_t *)&argp->saa_fh;
   1211 			*ptr++ = *arg++;
   1212 			*ptr++ = *arg++;
   1213 			*ptr++ = *arg++;
   1214 			*ptr++ = *arg++;
   1215 			*ptr++ = *arg++;
   1216 			*ptr++ = *arg++;
   1217 			*ptr++ = *arg++;
   1218 			*ptr++ = *arg;
   1219 			sa = &argp->saa_sa;
   1220 			IXDR_PUT_U_INT32(ptr, sa->sa_mode);
   1221 			IXDR_PUT_U_INT32(ptr, sa->sa_uid);
   1222 			IXDR_PUT_U_INT32(ptr, sa->sa_gid);
   1223 			IXDR_PUT_U_INT32(ptr, sa->sa_size);
   1224 			IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_sec);
   1225 			IXDR_PUT_U_INT32(ptr, sa->sa_atime.tv_usec);
   1226 			IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_sec);
   1227 			IXDR_PUT_U_INT32(ptr, sa->sa_mtime.tv_usec);
   1228 		}
   1229 		return (TRUE);
   1230 	}
   1231 
   1232 	if (xdr_fhandle(xdrs, &argp->saa_fh) &&
   1233 	    xdr_sattr(xdrs, &argp->saa_sa)) {
   1234 		return (TRUE);
   1235 	}
   1236 	return (FALSE);
   1237 }
   1238 
   1239 
   1240 /*
   1241  * arguments to create and mkdir
   1242  */
   1243 bool_t
   1244 xdr_creatargs(XDR *xdrs, struct nfscreatargs *argp)
   1245 {
   1246 	argp->ca_sa = &argp->ca_sa_buf;
   1247 
   1248 	if (xdrs->x_op == XDR_DECODE)
   1249 		argp->ca_sa = &argp->ca_sa_buf;
   1250 	if (xdr_diropargs(xdrs, &argp->ca_da) &&
   1251 	    xdr_sattr(xdrs, argp->ca_sa)) {
   1252 		return (TRUE);
   1253 	}
   1254 	return (FALSE);
   1255 }
   1256 
   1257 /*
   1258  * arguments to link
   1259  */
   1260 bool_t
   1261 xdr_linkargs(XDR *xdrs, struct nfslinkargs *argp)
   1262 {
   1263 	if (xdrs->x_op == XDR_DECODE)
   1264 		argp->la_from = &argp->la_from_buf;
   1265 	if (xdr_fhandle(xdrs, argp->la_from) &&
   1266 	    xdr_diropargs(xdrs, &argp->la_to)) {
   1267 		return (TRUE);
   1268 	}
   1269 	return (FALSE);
   1270 }
   1271 
   1272 /*
   1273  * arguments to rename
   1274  */
   1275 bool_t
   1276 xdr_rnmargs(XDR *xdrs, struct nfsrnmargs *argp)
   1277 {
   1278 	if (xdr_diropargs(xdrs, &argp->rna_from) &&
   1279 	    xdr_diropargs(xdrs, &argp->rna_to))
   1280 		return (TRUE);
   1281 	return (FALSE);
   1282 }
   1283 
   1284 
   1285 /*
   1286  * arguments to symlink
   1287  */
   1288 bool_t
   1289 xdr_slargs(XDR *xdrs, struct nfsslargs *argp)
   1290 {
   1291 	if (xdrs->x_op == XDR_FREE) {
   1292 		if (!xdr_diropargs(xdrs, &argp->sla_from))
   1293 			return (FALSE);
   1294 		if ((argp->sla_tnm_flags & SLA_FREETNM) &&
   1295 		    !xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN))
   1296 			return (FALSE);
   1297 		return (TRUE);
   1298 	}
   1299 
   1300 	if (xdrs->x_op == XDR_DECODE) {
   1301 		argp->sla_sa = &argp->sla_sa_buf;
   1302 		if (argp->sla_tnm == NULL)
   1303 			argp->sla_tnm_flags |= SLA_FREETNM;
   1304 	}
   1305 
   1306 	if (xdr_diropargs(xdrs, &argp->sla_from) &&
   1307 	    xdr_string(xdrs, &argp->sla_tnm, (uint_t)NFS_MAXPATHLEN) &&
   1308 	    xdr_sattr(xdrs, argp->sla_sa)) {
   1309 		return (TRUE);
   1310 	}
   1311 	return (FALSE);
   1312 }
   1313 
   1314 
   1315 /*
   1316  * NFS_OK part of statfs operation
   1317  */
   1318 bool_t
   1319 xdr_fsok(XDR *xdrs, struct nfsstatfsok *fsok)
   1320 {
   1321 	int32_t *ptr;
   1322 
   1323 	if (xdrs->x_op == XDR_FREE)
   1324 		return (TRUE);
   1325 
   1326 	ptr = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT);
   1327 	if (ptr != NULL) {
   1328 		if (xdrs->x_op == XDR_DECODE) {
   1329 			fsok->fsok_tsize = IXDR_GET_INT32(ptr);
   1330 			fsok->fsok_bsize = IXDR_GET_INT32(ptr);
   1331 			fsok->fsok_blocks = IXDR_GET_INT32(ptr);
   1332 			fsok->fsok_bfree = IXDR_GET_INT32(ptr);
   1333 			fsok->fsok_bavail = IXDR_GET_INT32(ptr);
   1334 		} else {
   1335 			IXDR_PUT_INT32(ptr, fsok->fsok_tsize);
   1336 			IXDR_PUT_INT32(ptr, fsok->fsok_bsize);
   1337 			IXDR_PUT_INT32(ptr, fsok->fsok_blocks);
   1338 			IXDR_PUT_INT32(ptr, fsok->fsok_bfree);
   1339 			IXDR_PUT_INT32(ptr, fsok->fsok_bavail);
   1340 		}
   1341 		return (TRUE);
   1342 	}
   1343 
   1344 	if (xdr_u_int(xdrs, &fsok->fsok_tsize) &&
   1345 	    xdr_u_int(xdrs, &fsok->fsok_bsize) &&
   1346 	    xdr_u_int(xdrs, &fsok->fsok_blocks) &&
   1347 	    xdr_u_int(xdrs, &fsok->fsok_bfree) &&
   1348 	    xdr_u_int(xdrs, &fsok->fsok_bavail)) {
   1349 		return (TRUE);
   1350 	}
   1351 	return (FALSE);
   1352 }
   1353 
   1354 #ifdef _LITTLE_ENDIAN
   1355 bool_t
   1356 xdr_fastfsok(XDR *xdrs, struct nfsstatfsok *fsok)
   1357 {
   1358 
   1359 	if (xdrs->x_op == XDR_FREE)
   1360 		return (TRUE);
   1361 	if (xdrs->x_op == XDR_DECODE)
   1362 		return (FALSE);
   1363 
   1364 	fsok->fsok_tsize = htonl(fsok->fsok_tsize);
   1365 	fsok->fsok_bsize = htonl(fsok->fsok_bsize);
   1366 	fsok->fsok_blocks = htonl(fsok->fsok_blocks);
   1367 	fsok->fsok_bfree = htonl(fsok->fsok_bfree);
   1368 	fsok->fsok_bavail = htonl(fsok->fsok_bavail);
   1369 	return (TRUE);
   1370 }
   1371 #endif
   1372 
   1373 static struct xdr_discrim statfs_discrim[2] = {
   1374 	{ NFS_OK, xdr_fsok },
   1375 	{ __dontcare__, NULL_xdrproc_t }
   1376 };
   1377 
   1378 /*
   1379  * Results of statfs operation
   1380  */
   1381 bool_t
   1382 xdr_statfs(XDR *xdrs, struct nfsstatfs *fs)
   1383 {
   1384 	return (xdr_union(xdrs, (enum_t *)&(fs->fs_status),
   1385 	    (caddr_t)&(fs->fs_fsok), statfs_discrim, xdr_void));
   1386 }
   1387 
   1388 /*
   1389  * Results of statfs operation
   1390  */
   1391 bool_t
   1392 xdr_faststatfs(XDR *xdrs, struct nfsstatfs *fs)
   1393 {
   1394 #if defined(_LITTLE_ENDIAN)
   1395 	/*
   1396 	 * we deal with the discriminator;  it's an enum
   1397 	 */
   1398 	if (!xdr_fastenum(xdrs, (enum_t *)&fs->fs_status))
   1399 		return (FALSE);
   1400 
   1401 	if (fs->fs_status == NFS_OK)
   1402 		return (xdr_fastfsok(xdrs, &fs->fs_fsok));
   1403 #elif defined(_BIG_ENDIAN)
   1404 	if (fs->fs_status == NFS_OK)
   1405 		return (TRUE);
   1406 #endif
   1407 	return (xdr_fastshorten(xdrs, sizeof (*fs)));
   1408 }
   1409 
   1410 #ifdef _LITTLE_ENDIAN
   1411 /*
   1412  * XDR enumerations
   1413  */
   1414 #ifndef lint
   1415 static enum sizecheck { SIZEVAL } sizecheckvar;	/* used to find the size of */
   1416 						/* an enum */
   1417 #endif
   1418 bool_t
   1419 xdr_fastenum(XDR *xdrs, enum_t *ep)
   1420 {
   1421 	if (xdrs->x_op == XDR_FREE)
   1422 		return (TRUE);
   1423 	if (xdrs->x_op == XDR_DECODE)
   1424 		return (FALSE);
   1425 
   1426 #ifndef lint
   1427 	/*
   1428 	 * enums are treated as ints
   1429 	 */
   1430 	if (sizeof (sizecheckvar) == sizeof (int32_t)) {
   1431 		*ep = (enum_t)htonl((int32_t)(*ep));
   1432 	} else if (sizeof (sizecheckvar) == sizeof (short)) {
   1433 		*ep = (enum_t)htons((short)(*ep));
   1434 	} else {
   1435 		return (FALSE);
   1436 	}
   1437 	return (TRUE);
   1438 #else
   1439 	(void) (xdr_short(xdrs, (short *)ep));
   1440 	return (xdr_int(xdrs, (int *)ep));
   1441 #endif
   1442 }
   1443 #endif
   1444 
   1445 static bool_t
   1446 xdr_fastshorten(XDR *xdrs, uint_t ressize)
   1447 {
   1448 	uint_t curpos;
   1449 
   1450 	curpos = XDR_GETPOS(xdrs);
   1451 	ressize -= BYTES_PER_XDR_UNIT;
   1452 	curpos -= ressize;
   1453 	return (XDR_SETPOS(xdrs, curpos));
   1454 }
   1455