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.
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.
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]
23 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
27 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
28 * Use is subject to license terms.
31 * Copyright (c) 2013 by Delphix. All rights reserved.
35 * A handcoded version based on the original rpcgen code.
37 * Note: All future NFS4 protocol changes should be added by hand
40 * CAUTION: All protocol changes must also be propagated to:
41 * usr/src/cmd/cmd-inet/usr.sbin/snoop/nfs4_xdr.c
44 #include <sys/types.h>
45 #include <sys/sunddi.h>
48 #include <nfs/nfs4_kprot.h>
49 #include <nfs/rnode4.h>
51 #include <nfs/nfs4_clnt.h>
53 #include <sys/mkdev.h>
54 #include <rpc/rpc_rdma.h>
57 #define xdr_dev_t xdr_u_int
59 extern bool_t
xdr_netbuf(XDR
*, struct netbuf
*);
60 extern bool_t
xdr_vector(XDR
*, char *, const uint_t
, const uint_t
,
62 bool_t
xdr_knetconfig(XDR
*, struct knetconfig
*);
65 xdr_bitmap4(XDR
*xdrs
, bitmap4
*objp
)
69 if (xdrs
->x_op
== XDR_FREE
)
73 * Simplified bitmap4 processing, always encode from uint64_t
74 * to 2 uint32_t's, always decode first 2 uint32_t's into a
75 * uint64_t and ignore all of the rest.
77 if (xdrs
->x_op
== XDR_ENCODE
) {
80 if (!XDR_PUTINT32(xdrs
, &len
))
83 #if defined(_LITTLE_ENDIAN)
84 if (XDR_PUTINT32(xdrs
, (int32_t *)((char *)objp
+
85 BYTES_PER_XDR_UNIT
)) == TRUE
) {
86 return (XDR_PUTINT32(xdrs
, (int32_t *)objp
));
88 #elif defined(_BIG_ENDIAN)
89 if (XDR_PUTINT32(xdrs
, (int32_t *)objp
) == TRUE
) {
90 return (XDR_PUTINT32(xdrs
, (int32_t *)((char *)objp
+
91 BYTES_PER_XDR_UNIT
)));
97 if (!XDR_GETINT32(xdrs
, &len
))
101 * Common fast DECODE cases
104 #if defined(_LITTLE_ENDIAN)
105 if (XDR_GETINT32(xdrs
, (int32_t *)((char *)objp
+
106 BYTES_PER_XDR_UNIT
)) == TRUE
) {
107 return (XDR_GETINT32(xdrs
, (int32_t *)objp
));
109 #elif defined(_BIG_ENDIAN)
110 if (XDR_GETINT32(xdrs
, (int32_t *)objp
) == TRUE
) {
111 return (XDR_GETINT32(xdrs
, (int32_t *)((char *)objp
+
112 BYTES_PER_XDR_UNIT
)));
123 * The not so common DECODE cases, len == 1 || len > 2
125 #if defined(_LITTLE_ENDIAN)
126 if (!XDR_GETINT32(xdrs
, (int32_t *)((char *)objp
+ BYTES_PER_XDR_UNIT
)))
130 if (!XDR_GETINT32(xdrs
, (int32_t *)objp
))
132 #elif defined(_BIG_ENDIAN)
133 if (!XDR_GETINT32(xdrs
, (int32_t *)objp
))
137 if (!XDR_GETINT32(xdrs
, (int32_t *)((char *)objp
+ BYTES_PER_XDR_UNIT
)))
146 size
= len
* BYTES_PER_XDR_UNIT
;
147 return (XDR_CONTROL(xdrs
, XDR_SKIPBYTES
, &size
));
150 /* Called by xdr_array, nfsid_map_xdr */
152 xdr_utf8string(XDR
*xdrs
, utf8string
*objp
)
154 if (xdrs
->x_op
!= XDR_FREE
)
155 return (xdr_bytes(xdrs
, (char **)&objp
->utf8string_val
,
156 (uint_t
*)&objp
->utf8string_len
, NFS4_MAX_UTF8STRING
));
158 if (objp
->utf8string_val
!= NULL
) {
159 kmem_free(objp
->utf8string_val
, objp
->utf8string_len
);
160 objp
->utf8string_val
= NULL
;
166 * used by NFSv4 referrals to get info needed for NFSv4 referral mount.
169 xdr_nfs_fsl_info(XDR
*xdrs
, struct nfs_fsl_info
*objp
)
172 if (!xdr_u_int(xdrs
, &objp
->netbuf_len
))
174 if (!xdr_u_int(xdrs
, &objp
->netnm_len
))
176 if (!xdr_u_int(xdrs
, &objp
->knconf_len
))
181 * The object can come from a 32-bit binary; nfsmapid.
182 * To be safe we double the size of the knetconfig to
183 * allow some buffering for decoding.
185 if (xdrs
->x_op
== XDR_DECODE
)
186 objp
->knconf_len
+= sizeof (struct knetconfig
);
189 if (!xdr_string(xdrs
, &objp
->netname
, ~0))
191 if (!xdr_pointer(xdrs
, (char **)&objp
->addr
, objp
->netbuf_len
,
192 (xdrproc_t
)xdr_netbuf
))
194 if (!xdr_pointer(xdrs
, (char **)&objp
->knconf
,
195 objp
->knconf_len
, (xdrproc_t
)xdr_knetconfig
))
201 xdr_knetconfig(XDR
*xdrs
, struct knetconfig
*objp
)
206 uint32_t major
, minor
;
210 if (!xdr_u_int(xdrs
, &objp
->knc_semantics
))
212 if (xdrs
->x_op
== XDR_DECODE
) {
213 objp
->knc_protofmly
= (((char *)objp
) +
214 sizeof (struct knetconfig
));
215 objp
->knc_proto
= objp
->knc_protofmly
+ KNC_STRSIZE
;
217 if (!xdr_opaque(xdrs
, objp
->knc_protofmly
, KNC_STRSIZE
))
219 if (!xdr_opaque(xdrs
, objp
->knc_proto
, KNC_STRSIZE
))
223 * For interoperability between 32-bit daemon and 64-bit kernel,
224 * we always treat dev_t as 64-bit number and do the expanding
225 * or compression of dev_t as needed.
226 * We have to hand craft the conversion since there is no available
227 * function in ddi.c. Besides ddi.c is available only in the kernel
228 * and we want to keep both user and kernel of xdr_knetconfig() the
229 * same for consistency.
231 if (xdrs
->x_op
== XDR_ENCODE
) {
233 dev64
= objp
->knc_rdev
;
235 major
= (objp
->knc_rdev
>> NBITSMINOR32
) & MAXMAJ32
;
236 minor
= objp
->knc_rdev
& MAXMIN32
;
237 dev64
= (((unsigned long long)major
) << NBITSMINOR64
) | minor
;
239 if (!xdr_u_longlong_t(xdrs
, &dev64
))
242 if (xdrs
->x_op
== XDR_DECODE
) {
244 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->knc_rdev
))
247 if (!xdr_u_longlong_t(xdrs
, &dev64
))
250 major
= (dev64
>> NBITSMINOR64
) & L_MAXMAJ32
;
251 minor
= dev64
& L_MAXMIN32
;
252 objp
->knc_rdev
= (major
<< L_BITSMINOR32
) | minor
;
256 if (xdrs
->x_op
== XDR_ENCODE
) {
257 buf
= XDR_INLINE(xdrs
, (8) * BYTES_PER_XDR_UNIT
);
259 if (!xdr_vector(xdrs
, (char *)objp
->knc_unused
, 8,
260 sizeof (uint_t
), (xdrproc_t
)xdr_u_int
))
265 for (i
= 0, genp
= objp
->knc_unused
;
267 #if defined(_LP64) || defined(_KERNEL)
268 IXDR_PUT_U_INT32(buf
, *genp
++);
270 IXDR_PUT_U_LONG(buf
, *genp
++);
275 } else if (xdrs
->x_op
== XDR_DECODE
) {
276 buf
= XDR_INLINE(xdrs
, (8) * BYTES_PER_XDR_UNIT
);
278 if (!xdr_vector(xdrs
, (char *)objp
->knc_unused
, 8,
279 sizeof (uint_t
), (xdrproc_t
)xdr_u_int
))
284 for (i
= 0, genp
= objp
->knc_unused
;
286 #if defined(_LP64) || defined(_KERNEL)
287 *genp
++ = IXDR_GET_U_INT32(buf
);
289 *genp
++ = IXDR_GET_U_LONG(buf
);
296 if (!xdr_vector(xdrs
, (char *)objp
->knc_unused
, 8,
297 sizeof (uint_t
), (xdrproc_t
)xdr_u_int
))
303 * XDR_INLINE decode a filehandle.
306 xdr_inline_decode_nfs_fh4(uint32_t *ptr
, nfs_fh4_fmt_t
*fhp
, uint32_t fhsize
)
308 uchar_t
*bp
= (uchar_t
*)ptr
;
314 * Check to see if what the client sent us is bigger or smaller
315 * than what we can ever possibly send out. NFS_FHMAXDATA is
316 * unfortunately badly named as it is no longer the max and is
317 * really the min of what is sent over the wire.
319 if (fhsize
> sizeof (nfs_fh4_fmt_t
) || fhsize
< (sizeof (fsid_t
) +
320 sizeof (ushort_t
) + NFS_FHMAXDATA
+
321 sizeof (ushort_t
) + NFS_FHMAXDATA
)) {
326 * All internal parts of a filehandle are in native byte order.
328 * Decode what should be fh4_fsid, it is aligned.
330 fhp
->fh4_fsid
.val
[0] = *(uint32_t *)bp
;
331 bp
+= BYTES_PER_XDR_UNIT
;
332 fhp
->fh4_fsid
.val
[1] = *(uint32_t *)bp
;
333 bp
+= BYTES_PER_XDR_UNIT
;
336 * Decode what should be fh4_len. fh4_len is two bytes, so we're
339 cp
= (uchar_t
*)&fhp
->fh4_len
;
342 fhsize
-= 2 * BYTES_PER_XDR_UNIT
+ sizeof (ushort_t
);
345 * For backwards compatibility, the fid length may be less than
346 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
348 dsize
= fhp
->fh4_len
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_len
;
351 * Make sure the client isn't sending us a bogus length for fh4_data.
355 bcopy(bp
, fhp
->fh4_data
, dsize
);
359 if (fhsize
< sizeof (ushort_t
))
361 cp
= (uchar_t
*)&fhp
->fh4_xlen
;
364 fhsize
-= sizeof (ushort_t
);
366 dsize
= fhp
->fh4_xlen
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_xlen
;
369 * Make sure the client isn't sending us a bogus length for fh4_xdata.
373 bcopy(bp
, fhp
->fh4_xdata
, dsize
);
378 * We realign things on purpose, so skip any padding
380 resid
= (uintptr_t)bp
% BYTES_PER_XDR_UNIT
;
382 if (fhsize
< (BYTES_PER_XDR_UNIT
- resid
))
384 bp
+= BYTES_PER_XDR_UNIT
- resid
;
385 fhsize
-= BYTES_PER_XDR_UNIT
- resid
;
388 if (fhsize
< BYTES_PER_XDR_UNIT
)
390 fhp
->fh4_flag
= *(uint32_t *)bp
;
391 bp
+= BYTES_PER_XDR_UNIT
;
392 fhsize
-= BYTES_PER_XDR_UNIT
;
394 #ifdef VOLATILE_FH_TEST
395 if (fhsize
< BYTES_PER_XDR_UNIT
)
397 fhp
->fh4_volatile_id
= *(uint32_t *)bp
;
398 bp
+= BYTES_PER_XDR_UNIT
;
399 fhsize
-= BYTES_PER_XDR_UNIT
;
402 * Make sure client didn't send extra bytes
410 xdr_decode_nfs_fh4(XDR
*xdrs
, nfs_fh4
*objp
)
412 uint32_t fhsize
; /* filehandle size */
417 ASSERT(xdrs
->x_op
== XDR_DECODE
);
420 * Retrieve the filehandle length.
422 if (!XDR_GETINT32(xdrs
, (int32_t *)&fhsize
))
425 objp
->nfs_fh4_val
= NULL
;
426 objp
->nfs_fh4_len
= 0;
429 * Check to see if what the client sent us is bigger or smaller
430 * than what we can ever possibly send out. NFS_FHMAXDATA is
431 * unfortunately badly named as it is no longer the max and is
432 * really the min of what is sent over the wire.
434 if (fhsize
> sizeof (nfs_fh4_fmt_t
) || fhsize
< (sizeof (fsid_t
) +
435 sizeof (ushort_t
) + NFS_FHMAXDATA
+
436 sizeof (ushort_t
) + NFS_FHMAXDATA
)) {
437 if (!XDR_CONTROL(xdrs
, XDR_SKIPBYTES
, &fhsize
))
443 * bring in fhsize plus any padding
445 bufsize
= RNDUP(fhsize
);
446 ptr
= XDR_INLINE(xdrs
, bufsize
);
449 bp
= kmem_alloc(bufsize
, KM_SLEEP
);
450 if (!xdr_opaque(xdrs
, (char *)bp
, bufsize
)) {
451 kmem_free(bp
, bufsize
);
456 objp
->nfs_fh4_val
= kmem_zalloc(sizeof (nfs_fh4_fmt_t
), KM_SLEEP
);
457 objp
->nfs_fh4_len
= sizeof (nfs_fh4_fmt_t
);
459 if (xdr_inline_decode_nfs_fh4((uint32_t *)bp
,
460 (nfs_fh4_fmt_t
*)objp
->nfs_fh4_val
, fhsize
) == FALSE
) {
462 * If in the process of decoding we find the file handle
463 * is not correctly formed, we need to continue decoding
464 * and trigger an NFS layer error. Set the nfs_fh4_len to
465 * zero so it gets caught as a bad length.
467 kmem_free(objp
->nfs_fh4_val
, objp
->nfs_fh4_len
);
468 objp
->nfs_fh4_val
= NULL
;
469 objp
->nfs_fh4_len
= 0;
473 kmem_free(bp
, bufsize
);
478 * XDR_INLINE encode a filehandle.
481 xdr_inline_encode_nfs_fh4(uint32_t **ptrp
, uint32_t *ptr_redzone
,
484 uint32_t *ptr
= *ptrp
;
486 uint_t otw_len
, fsize
, xsize
; /* otw, file, and export sizes */
489 fsize
= fhp
->fh4_len
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_len
;
490 xsize
= fhp
->fh4_xlen
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_xlen
;
493 * First get the initial and variable sized part of the filehandle.
495 otw_len
= sizeof (fhp
->fh4_fsid
) +
496 sizeof (fhp
->fh4_len
) + fsize
+
497 sizeof (fhp
->fh4_xlen
) + xsize
;
500 * Round out to a full word.
502 otw_len
= RNDUP(otw_len
);
503 padword
= (otw_len
/ BYTES_PER_XDR_UNIT
); /* includes fhlen */
506 * Add in the fixed sized pieces.
508 otw_len
+= sizeof (fhp
->fh4_flag
);
509 #ifdef VOLATILE_FH_TEST
510 otw_len
+= sizeof (fhp
->fh4_volatile_id
);
514 * Make sure we don't exceed our buffer.
516 if ((ptr
+ (otw_len
/ BYTES_PER_XDR_UNIT
) + 1) > ptr_redzone
)
520 * Zero out the padding.
524 IXDR_PUT_U_INT32(ptr
, otw_len
);
527 * The rest of the filehandle is in native byteorder
530 *ptr
++ = (uint32_t)fhp
->fh4_fsid
.val
[0];
531 *ptr
++ = (uint32_t)fhp
->fh4_fsid
.val
[1];
534 * Since the next pieces are unaligned, we need to
535 * do bytewise copies.
539 /* fh4_len + fh4_data */
540 bcopy(&fhp
->fh4_len
, cp
, sizeof (fhp
->fh4_len
) + fsize
);
541 cp
+= sizeof (fhp
->fh4_len
) + fsize
;
543 /* fh4_xlen + fh4_xdata */
544 bcopy(&fhp
->fh4_xlen
, cp
, sizeof (fhp
->fh4_xlen
) + xsize
);
545 cp
+= sizeof (fhp
->fh4_xlen
) + xsize
;
547 /* do necessary rounding/padding */
548 cp
= (uchar_t
*)RNDUP((uintptr_t)cp
);
549 ptr
= (uint32_t *)cp
;
552 * With the above padding, we're word aligned again.
554 ASSERT(((uintptr_t)ptr
% BYTES_PER_XDR_UNIT
) == 0);
557 *ptr
++ = (uint32_t)fhp
->fh4_flag
;
559 #ifdef VOLATILE_FH_TEST
560 /* fh4_volatile_id */
561 *ptr
++ = (uint32_t)fhp
->fh4_volatile_id
;
569 xdr_encode_nfs_fh4(XDR
*xdrs
, nfs_fh4
*objp
)
571 uint_t otw_len
, fsize
, xsize
; /* otw, file, and export sizes */
574 rpc_inline_t
*buf
= NULL
;
575 uint32_t *ptr_redzone
;
578 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
580 fhp
= (nfs_fh4_fmt_t
*)objp
->nfs_fh4_val
;
581 fsize
= fhp
->fh4_len
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_len
;
582 xsize
= fhp
->fh4_xlen
< NFS_FHMAXDATA
? NFS_FHMAXDATA
: fhp
->fh4_xlen
;
585 * First get the over the wire size, it is the 4 bytes
586 * for the length, plus the combined size of the
587 * file handle components.
589 otw_len
= BYTES_PER_XDR_UNIT
+ sizeof (fhp
->fh4_fsid
) +
590 sizeof (fhp
->fh4_len
) + fsize
+
591 sizeof (fhp
->fh4_xlen
) + xsize
+
592 sizeof (fhp
->fh4_flag
);
593 #ifdef VOLATILE_FH_TEST
594 otw_len
+= sizeof (fhp
->fh4_volatile_id
);
597 * Round out to a full word.
599 otw_len
= RNDUP(otw_len
);
602 * Next try to inline the XDR stream, if that fails (rare)
603 * allocate a buffer to encode the file handle and then
604 * copy it using xdr_opaque and free the buffer.
606 ptr
= XDR_INLINE(xdrs
, otw_len
);
608 ptr
= buf
= kmem_alloc(otw_len
, KM_SLEEP
);
610 ptr_redzone
= (uint32_t *)(ptr
+ (otw_len
/ BYTES_PER_XDR_UNIT
));
611 ret
= xdr_inline_encode_nfs_fh4((uint32_t **)&ptr
, ptr_redzone
, fhp
);
615 ret
= xdr_opaque(xdrs
, (char *)buf
, otw_len
);
616 kmem_free(buf
, otw_len
);
622 * XDR a NFSv4 filehandle.
623 * Encoding interprets the contents (server).
624 * Decoding the contents are opaque (client).
627 xdr_nfs_fh4(XDR
*xdrs
, nfs_fh4
*objp
)
629 switch (xdrs
->x_op
) {
631 return (xdr_encode_nfs_fh4(xdrs
, objp
));
633 return (xdr_bytes(xdrs
, (char **)&objp
->nfs_fh4_val
,
634 (uint_t
*)&objp
->nfs_fh4_len
, NFS4_FHSIZE
));
636 if (objp
->nfs_fh4_val
!= NULL
) {
637 kmem_free(objp
->nfs_fh4_val
, objp
->nfs_fh4_len
);
638 objp
->nfs_fh4_val
= NULL
;
645 /* Called by xdr_array */
647 xdr_fs_location4(XDR
*xdrs
, fs_location4
*objp
)
649 if (xdrs
->x_op
== XDR_DECODE
) {
650 objp
->server_val
= NULL
;
651 objp
->rootpath
.pathname4_val
= NULL
;
653 if (!xdr_array(xdrs
, (char **)&objp
->server_val
,
654 (uint_t
*)&objp
->server_len
, NFS4_MAX_UTF8STRING
,
655 sizeof (utf8string
), (xdrproc_t
)xdr_utf8string
))
657 return (xdr_array(xdrs
, (char **)&objp
->rootpath
.pathname4_val
,
658 (uint_t
*)&objp
->rootpath
.pathname4_len
,
660 sizeof (utf8string
), (xdrproc_t
)xdr_utf8string
));
663 /* Called by xdr_array */
665 xdr_nfsace4(XDR
*xdrs
, nfsace4
*objp
)
667 if (xdrs
->x_op
!= XDR_FREE
) {
668 if (!xdr_u_int(xdrs
, &objp
->type
))
670 if (!xdr_u_int(xdrs
, &objp
->flag
))
672 if (!xdr_u_int(xdrs
, &objp
->access_mask
))
675 if (xdrs
->x_op
== XDR_DECODE
) {
676 objp
->who
.utf8string_val
= NULL
;
677 objp
->who
.utf8string_len
= 0;
680 return (xdr_bytes(xdrs
, (char **)&objp
->who
.utf8string_val
,
681 (uint_t
*)&objp
->who
.utf8string_len
,
682 NFS4_MAX_UTF8STRING
));
686 * Optimized free case
688 if (objp
->who
.utf8string_val
!= NULL
) {
689 kmem_free(objp
->who
.utf8string_val
, objp
->who
.utf8string_len
);
690 objp
->who
.utf8string_val
= NULL
;
696 * These functions are called out of nfs4_attr.c
699 xdr_fattr4_fsid(XDR
*xdrs
, fattr4_fsid
*objp
)
701 if (xdrs
->x_op
== XDR_FREE
)
704 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->major
))
706 return (xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->minor
));
711 xdr_fattr4_acl(XDR
*xdrs
, fattr4_acl
*objp
)
713 return (xdr_array(xdrs
, (char **)&objp
->fattr4_acl_val
,
714 (uint_t
*)&objp
->fattr4_acl_len
, NFS4_ACL_LIMIT
,
715 sizeof (nfsace4
), (xdrproc_t
)xdr_nfsace4
));
719 xdr_fattr4_fs_locations(XDR
*xdrs
, fattr4_fs_locations
*objp
)
721 if (xdrs
->x_op
== XDR_DECODE
) {
722 objp
->fs_root
.pathname4_len
= 0;
723 objp
->fs_root
.pathname4_val
= NULL
;
724 objp
->locations_val
= NULL
;
726 if (!xdr_array(xdrs
, (char **)&objp
->fs_root
.pathname4_val
,
727 (uint_t
*)&objp
->fs_root
.pathname4_len
,
729 sizeof (utf8string
), (xdrproc_t
)xdr_utf8string
))
731 return (xdr_array(xdrs
, (char **)&objp
->locations_val
,
732 (uint_t
*)&objp
->locations_len
, NFS4_FS_LOCATIONS_LIMIT
,
733 sizeof (fs_location4
), (xdrproc_t
)xdr_fs_location4
));
737 xdr_fattr4_rawdev(XDR
*xdrs
, fattr4_rawdev
*objp
)
739 if (xdrs
->x_op
== XDR_FREE
)
742 if (!xdr_u_int(xdrs
, &objp
->specdata1
))
744 return (xdr_u_int(xdrs
, &objp
->specdata2
));
748 xdr_nfstime4(XDR
*xdrs
, nfstime4
*objp
)
750 if (xdrs
->x_op
== XDR_FREE
)
753 if (!xdr_longlong_t(xdrs
, (longlong_t
*)&objp
->seconds
))
755 return (xdr_u_int(xdrs
, &objp
->nseconds
));
760 * structured used for calls into xdr_ga_fattr_res() as a means
761 * to do an immediate/short-term cache of owner/group strings
762 * for callers like the readdir processing. In the case of readdir,
763 * it is likely that the directory objects will be owned by the same
764 * owner/group and if so there is no need to call into the uid/gid
765 * mapping code. While the uid/gid interfaces have their own cache
766 * having one here will reduct pathlength further.
768 #define MAX_OG_NAME 100
769 typedef struct ug_cache
773 utf8string u_curr
, u_last
;
774 utf8string g_curr
, g_last
;
775 char u_buf1
[MAX_OG_NAME
];
776 char u_buf2
[MAX_OG_NAME
];
777 char g_buf1
[MAX_OG_NAME
];
778 char g_buf2
[MAX_OG_NAME
];
781 #define U_SWAP_CURR_LAST(ug) \
782 (ug)->u_last.utf8string_len = (ug)->u_curr.utf8string_len; \
783 if ((ug)->u_last.utf8string_val == (ug)->u_buf1) { \
784 (ug)->u_last.utf8string_val = (ug)->u_buf2; \
785 (ug)->u_curr.utf8string_val = (ug)->u_buf1; \
787 (ug)->u_last.utf8string_val = (ug)->u_buf1; \
788 (ug)->u_curr.utf8string_val = (ug)->u_buf2; \
791 #define G_SWAP_CURR_LAST(ug) \
792 (ug)->g_last.utf8string_len = (ug)->g_curr.utf8string_len; \
793 if ((ug)->g_last.utf8string_val == (ug)->g_buf1) { \
794 (ug)->g_last.utf8string_val = (ug)->g_buf2; \
795 (ug)->g_curr.utf8string_val = (ug)->g_buf1; \
797 (ug)->g_last.utf8string_val = (ug)->g_buf1; \
798 (ug)->g_curr.utf8string_val = (ug)->g_buf2; \
804 ug_cache_t
*pug
= kmem_alloc(sizeof (ug_cache_t
), KM_SLEEP
);
806 pug
->uid
= pug
->gid
= 0;
807 pug
->u_curr
.utf8string_len
= 0;
808 pug
->u_last
.utf8string_len
= 0;
809 pug
->g_curr
.utf8string_len
= 0;
810 pug
->g_last
.utf8string_len
= 0;
811 pug
->u_curr
.utf8string_val
= pug
->u_buf1
;
812 pug
->u_last
.utf8string_val
= pug
->u_buf2
;
813 pug
->g_curr
.utf8string_val
= pug
->g_buf1
;
814 pug
->g_last
.utf8string_val
= pug
->g_buf2
;
820 xdr_ga_prefill_vattr(struct nfs4_ga_res
*garp
, struct mntinfo4
*mi
)
822 static vattr_t s_vattr
= {
823 AT_ALL
, /* va_mask */
826 UID_NOBODY
, /* va_uid */
827 GID_NOBODY
, /* va_gid */
832 {0, 0}, /* va_atime */
833 {0, 0}, /* va_mtime */
834 {0, 0}, /* va_ctime */
836 MAXBSIZE
, /* va_blksize */
842 garp
->n4g_va
= s_vattr
;
843 garp
->n4g_va
.va_fsid
= mi
->mi_vfsp
->vfs_dev
;
844 hrt2ts(gethrtime(), &garp
->n4g_va
.va_atime
);
845 garp
->n4g_va
.va_mtime
= garp
->n4g_va
.va_ctime
= garp
->n4g_va
.va_atime
;
849 xdr_ga_prefill_statvfs(struct nfs4_ga_ext_res
*gesp
, struct mntinfo4
*mi
)
851 static statvfs64_t s_sb
= {
852 MAXBSIZE
, /* f_bsize */
853 DEV_BSIZE
, /* f_frsize */
854 (fsfilcnt64_t
)-1, /* f_blocks */
855 (fsfilcnt64_t
)-1, /* f_bfree */
856 (fsfilcnt64_t
)-1, /* f_bavail */
857 (fsfilcnt64_t
)-1, /* f_files */
858 (fsfilcnt64_t
)-1, /* f_ffree */
859 (fsfilcnt64_t
)-1, /* f_favail */
861 "\0", /* f_basetype */
863 MAXNAMELEN
, /* f_namemax */
868 gesp
->n4g_sb
.f_fsid
= mi
->mi_vfsp
->vfs_fsid
.val
[0];
872 xdr_ga_fattr_res(XDR
*xdrs
, struct nfs4_ga_res
*garp
, bitmap4 resbmap
,
873 bitmap4 argbmap
, struct mntinfo4
*mi
, ug_cache_t
*pug
)
876 struct nfs4_ga_ext_res ges
, *gesp
;
877 vattr_t
*vap
= &garp
->n4g_va
;
878 vsecattr_t
*vsap
= &garp
->n4g_vsa
;
880 ASSERT(xdrs
->x_op
== XDR_DECODE
);
882 if (garp
->n4g_ext_res
)
883 gesp
= garp
->n4g_ext_res
;
889 /* Check to see if the vattr should be pre-filled */
890 if (argbmap
& NFS4_VATTR_MASK
)
891 xdr_ga_prefill_vattr(garp
, mi
);
893 if (argbmap
& NFS4_STATFS_ATTR_MASK
)
894 xdr_ga_prefill_statvfs(gesp
, mi
);
897 (FATTR4_SUPPORTED_ATTRS_MASK
|
899 FATTR4_FH_EXPIRE_TYPE_MASK
|
902 FATTR4_LINK_SUPPORT_MASK
|
903 FATTR4_SYMLINK_SUPPORT_MASK
|
904 FATTR4_NAMED_ATTR_MASK
)) {
906 if (resbmap
& FATTR4_SUPPORTED_ATTRS_MASK
) {
907 if (!xdr_bitmap4(xdrs
, &gesp
->n4g_suppattrs
))
910 if (resbmap
& FATTR4_TYPE_MASK
) {
911 if (!XDR_GETINT32(xdrs
, (int *)&vap
->va_type
))
914 if ((nfs_ftype4
)vap
->va_type
< NF4REG
||
915 (nfs_ftype4
)vap
->va_type
> NF4NAMEDATTR
)
918 vap
->va_type
= nf4_to_vt
[vap
->va_type
];
919 if (vap
->va_type
== VBLK
)
920 vap
->va_blksize
= DEV_BSIZE
;
922 vap
->va_mask
|= AT_TYPE
;
924 if (resbmap
& FATTR4_FH_EXPIRE_TYPE_MASK
) {
925 if (!XDR_GETINT32(xdrs
, (int *)&gesp
->n4g_fet
))
928 if (resbmap
& FATTR4_CHANGE_MASK
) {
929 if (!xdr_u_longlong_t(xdrs
,
930 (u_longlong_t
*)&garp
->n4g_change
))
932 garp
->n4g_change_valid
= 1;
934 if (resbmap
& FATTR4_SIZE_MASK
) {
935 if (!xdr_u_longlong_t(xdrs
,
936 (u_longlong_t
*)&vap
->va_size
))
938 if (!NFS4_SIZE_OK(vap
->va_size
)) {
939 garp
->n4g_attrerr
= EFBIG
;
940 garp
->n4g_attrwhy
= NFS4_GETATTR_ATSIZE_ERR
;
942 vap
->va_mask
|= AT_SIZE
;
945 if (resbmap
& FATTR4_LINK_SUPPORT_MASK
) {
946 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
948 gesp
->n4g_pc4
.pc4_link_support
=
949 (truefalse
? TRUE
: FALSE
);
951 if (resbmap
& FATTR4_SYMLINK_SUPPORT_MASK
) {
952 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
954 gesp
->n4g_pc4
.pc4_symlink_support
=
955 (truefalse
? TRUE
: FALSE
);
957 if (resbmap
& FATTR4_NAMED_ATTR_MASK
) {
958 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
960 gesp
->n4g_pc4
.pc4_xattr_exists
= TRUE
;
961 gesp
->n4g_pc4
.pc4_xattr_exists
=
962 (truefalse
? TRUE
: FALSE
);
967 FATTR4_UNIQUE_HANDLES_MASK
|
968 FATTR4_LEASE_TIME_MASK
|
969 FATTR4_RDATTR_ERROR_MASK
)) {
971 if (resbmap
& FATTR4_FSID_MASK
) {
972 if ((!xdr_u_longlong_t(xdrs
,
973 (u_longlong_t
*)&garp
->n4g_fsid
.major
)) ||
974 (!xdr_u_longlong_t(xdrs
,
975 (u_longlong_t
*)&garp
->n4g_fsid
.minor
)))
977 garp
->n4g_fsid_valid
= 1;
979 if (resbmap
& FATTR4_UNIQUE_HANDLES_MASK
) {
980 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
982 gesp
->n4g_pc4
.pc4_unique_handles
=
983 (truefalse
? TRUE
: FALSE
);
985 if (resbmap
& FATTR4_LEASE_TIME_MASK
) {
986 if (!XDR_GETINT32(xdrs
, (int *)&gesp
->n4g_leasetime
))
989 if (resbmap
& FATTR4_RDATTR_ERROR_MASK
) {
990 if (!XDR_GETINT32(xdrs
,
991 (int *)&gesp
->n4g_rdattr_error
))
997 FATTR4_ACLSUPPORT_MASK
|
998 FATTR4_ARCHIVE_MASK
|
999 FATTR4_CANSETTIME_MASK
)) {
1001 if (resbmap
& FATTR4_ACL_MASK
) {
1004 acl
.fattr4_acl_val
= NULL
;
1005 acl
.fattr4_acl_len
= 0;
1007 if (!xdr_fattr4_acl(xdrs
, &acl
))
1010 vsap
->vsa_aclcnt
= acl
.fattr4_acl_len
;
1011 vsap
->vsa_aclentp
= acl
.fattr4_acl_val
;
1012 vsap
->vsa_mask
= VSA_ACE
| VSA_ACECNT
;
1013 vsap
->vsa_aclentsz
= vsap
->vsa_aclcnt
* sizeof (ace_t
);
1016 if (resbmap
& FATTR4_ACLSUPPORT_MASK
) {
1017 if (!XDR_GETINT32(xdrs
, (int *)&gesp
->n4g_aclsupport
))
1020 if (resbmap
& FATTR4_ARCHIVE_MASK
) {
1023 if (resbmap
& FATTR4_CANSETTIME_MASK
) {
1024 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1026 gesp
->n4g_pc4
.pc4_cansettime
=
1027 (truefalse
? TRUE
: FALSE
);
1031 (FATTR4_CASE_INSENSITIVE_MASK
|
1032 FATTR4_CASE_PRESERVING_MASK
|
1033 FATTR4_CHOWN_RESTRICTED_MASK
|
1034 FATTR4_FILEHANDLE_MASK
|
1035 FATTR4_FILEID_MASK
|
1036 FATTR4_FILES_AVAIL_MASK
|
1037 FATTR4_FILES_FREE_MASK
|
1038 FATTR4_FILES_TOTAL_MASK
)) {
1040 if (resbmap
& FATTR4_CASE_INSENSITIVE_MASK
) {
1041 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1043 gesp
->n4g_pc4
.pc4_case_insensitive
=
1044 (truefalse
? TRUE
: FALSE
);
1046 if (resbmap
& FATTR4_CASE_PRESERVING_MASK
) {
1047 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1049 gesp
->n4g_pc4
.pc4_case_preserving
=
1050 (truefalse
? TRUE
: FALSE
);
1052 if (resbmap
& FATTR4_CHOWN_RESTRICTED_MASK
) {
1053 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1055 gesp
->n4g_pc4
.pc4_chown_restricted
=
1056 (truefalse
? TRUE
: FALSE
);
1058 if (resbmap
& FATTR4_FILEHANDLE_MASK
) {
1059 gesp
->n4g_fh_u
.nfs_fh4_alt
.len
= 0;
1060 gesp
->n4g_fh_u
.nfs_fh4_alt
.val
=
1061 gesp
->n4g_fh_u
.nfs_fh4_alt
.data
;
1062 if (!xdr_bytes(xdrs
,
1063 (char **)&gesp
->n4g_fh_u
.n4g_fh
.nfs_fh4_val
,
1064 (uint_t
*)&gesp
->n4g_fh_u
.n4g_fh
.nfs_fh4_len
,
1068 if (resbmap
& FATTR4_FILEID_MASK
) {
1069 if (!xdr_u_longlong_t(xdrs
,
1070 (u_longlong_t
*)&vap
->va_nodeid
))
1072 vap
->va_mask
|= AT_NODEID
;
1074 if (resbmap
& FATTR4_FILES_AVAIL_MASK
) {
1075 if (!xdr_u_longlong_t(xdrs
,
1076 (u_longlong_t
*)&gesp
->n4g_sb
.f_favail
))
1079 if (resbmap
& FATTR4_FILES_FREE_MASK
) {
1080 if (!xdr_u_longlong_t(xdrs
,
1081 (u_longlong_t
*)&gesp
->n4g_sb
.f_ffree
))
1084 if (resbmap
& FATTR4_FILES_TOTAL_MASK
) {
1085 if (!xdr_u_longlong_t(xdrs
,
1086 (u_longlong_t
*)&gesp
->n4g_sb
.f_files
))
1091 (FATTR4_FS_LOCATIONS_MASK
|
1092 FATTR4_HIDDEN_MASK
|
1093 FATTR4_HOMOGENEOUS_MASK
)) {
1095 if (resbmap
& FATTR4_FS_LOCATIONS_MASK
) {
1096 if (!xdr_fattr4_fs_locations(xdrs
,
1097 &gesp
->n4g_fslocations
))
1100 if (resbmap
& FATTR4_HIDDEN_MASK
) {
1103 if (resbmap
& FATTR4_HOMOGENEOUS_MASK
) {
1104 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1106 gesp
->n4g_pc4
.pc4_homogeneous
=
1107 (truefalse
? TRUE
: FALSE
);
1111 (FATTR4_MAXFILESIZE_MASK
|
1112 FATTR4_MAXLINK_MASK
|
1113 FATTR4_MAXNAME_MASK
|
1114 FATTR4_MAXREAD_MASK
|
1115 FATTR4_MAXWRITE_MASK
)) {
1117 if (resbmap
& FATTR4_MAXFILESIZE_MASK
) {
1118 if (!xdr_u_longlong_t(xdrs
,
1119 (u_longlong_t
*)&gesp
->n4g_maxfilesize
))
1122 if (resbmap
& FATTR4_MAXLINK_MASK
) {
1123 if (!XDR_GETINT32(xdrs
,
1124 (int *)&gesp
->n4g_pc4
.pc4_link_max
))
1127 if (resbmap
& FATTR4_MAXNAME_MASK
) {
1128 if (!XDR_GETINT32(xdrs
,
1129 (int *)&gesp
->n4g_pc4
.pc4_name_max
))
1131 gesp
->n4g_sb
.f_namemax
= gesp
->n4g_pc4
.pc4_name_max
;
1133 if (resbmap
& FATTR4_MAXREAD_MASK
) {
1134 if (!xdr_u_longlong_t(xdrs
,
1135 (u_longlong_t
*)&gesp
->n4g_maxread
))
1138 if (resbmap
& FATTR4_MAXWRITE_MASK
) {
1139 if (!xdr_u_longlong_t(xdrs
,
1140 (u_longlong_t
*)&gesp
->n4g_maxwrite
))
1145 (FATTR4_MIMETYPE_MASK
|
1147 FATTR4_NO_TRUNC_MASK
|
1148 FATTR4_NUMLINKS_MASK
)) {
1150 if (resbmap
& FATTR4_MIMETYPE_MASK
) {
1153 if (resbmap
& FATTR4_MODE_MASK
) {
1154 if (!XDR_GETINT32(xdrs
, (int *)&vap
->va_mode
))
1156 vap
->va_mask
|= AT_MODE
;
1158 if (resbmap
& FATTR4_NO_TRUNC_MASK
) {
1159 if (!XDR_GETINT32(xdrs
, (int *)&truefalse
))
1161 gesp
->n4g_pc4
.pc4_no_trunc
=
1162 (truefalse
? TRUE
: FALSE
);
1164 if (resbmap
& FATTR4_NUMLINKS_MASK
) {
1165 if (!XDR_GETINT32(xdrs
, (int *)&vap
->va_nlink
))
1167 vap
->va_mask
|= AT_NLINK
;
1171 (FATTR4_OWNER_MASK
|
1172 FATTR4_OWNER_GROUP_MASK
|
1173 FATTR4_QUOTA_AVAIL_HARD_MASK
|
1174 FATTR4_QUOTA_AVAIL_SOFT_MASK
)) {
1176 if (resbmap
& FATTR4_OWNER_MASK
) {
1177 uint_t
*owner_length
, ol
;
1178 char *owner_val
= NULL
;
1179 char *owner_alloc
= NULL
;
1183 /* get the OWNER_LENGTH */
1184 if (!xdr_u_int(xdrs
, &ol
))
1187 /* Manage the owner length location */
1188 if (pug
&& ol
<= MAX_OG_NAME
) {
1189 owner_length
= &pug
->u_curr
.utf8string_len
;
1195 /* find memory to store the decode */
1196 if (*owner_length
> MAX_OG_NAME
|| pug
== NULL
)
1197 owner_val
= owner_alloc
=
1198 kmem_alloc(*owner_length
, KM_SLEEP
);
1200 owner_val
= pug
->u_curr
.utf8string_val
;
1202 /* get the OWNER string */
1203 if (!xdr_opaque(xdrs
, owner_val
, *owner_length
)) {
1205 kmem_free(owner_alloc
, *owner_length
);
1209 /* Optimize for matching if called for */
1211 *owner_length
== pug
->u_last
.utf8string_len
&&
1212 bcmp(owner_val
, pug
->u_last
.utf8string_val
,
1213 *owner_length
) == 0) {
1214 vap
->va_uid
= pug
->uid
;
1215 vap
->va_mask
|= AT_UID
;
1219 ov
.utf8string_len
= *owner_length
;
1220 ov
.utf8string_val
= owner_val
;
1221 error
= nfs_idmap_str_uid(&ov
, &uid
, FALSE
);
1223 * String was mapped, but to nobody because
1224 * we are nfsmapid, indicate it should not
1227 if (error
== ENOTSUP
) {
1230 NFS4_GETATTR_NOCACHE_OK
;
1234 garp
->n4g_attrerr
= error
;
1236 NFS4_GETATTR_ATUID_ERR
;
1239 vap
->va_mask
|= AT_UID
;
1240 if (pug
&& ol
<= MAX_OG_NAME
) {
1242 U_SWAP_CURR_LAST(pug
);
1246 kmem_free(owner_alloc
, *owner_length
);
1249 if (resbmap
& FATTR4_OWNER_GROUP_MASK
) {
1250 uint_t
*group_length
, gl
;
1251 char *group_val
= NULL
;
1252 char *group_alloc
= NULL
;
1256 /* get the OWNER_GROUP_LENGTH */
1257 if (!xdr_u_int(xdrs
, &gl
))
1260 /* Manage the group length location */
1261 if (pug
&& gl
<= MAX_OG_NAME
) {
1262 group_length
= &pug
->g_curr
.utf8string_len
;
1268 /* find memory to store the decode */
1269 if (*group_length
> MAX_OG_NAME
|| pug
== NULL
)
1270 group_val
= group_alloc
=
1271 kmem_alloc(*group_length
, KM_SLEEP
);
1273 group_val
= pug
->g_curr
.utf8string_val
;
1275 /* get the OWNER_GROUP string */
1276 if (!xdr_opaque(xdrs
, group_val
, *group_length
)) {
1278 kmem_free(group_alloc
, *group_length
);
1282 /* Optimize for matching if called for */
1284 *group_length
== pug
->g_last
.utf8string_len
&&
1285 bcmp(group_val
, pug
->g_last
.utf8string_val
,
1286 *group_length
) == 0) {
1287 vap
->va_gid
= pug
->gid
;
1288 vap
->va_mask
|= AT_GID
;
1292 gv
.utf8string_len
= *group_length
;
1293 gv
.utf8string_val
= group_val
;
1294 error
= nfs_idmap_str_gid(&gv
, &gid
, FALSE
);
1296 * String was mapped, but to nobody because
1297 * we are nfsmapid, indicate it should not
1300 if (error
== ENOTSUP
) {
1303 NFS4_GETATTR_NOCACHE_OK
;
1307 garp
->n4g_attrerr
= error
;
1309 NFS4_GETATTR_ATGID_ERR
;
1312 vap
->va_mask
|= AT_GID
;
1313 if (pug
&& gl
<= MAX_OG_NAME
) {
1315 G_SWAP_CURR_LAST(pug
);
1319 kmem_free(group_alloc
, *group_length
);
1323 if (resbmap
& FATTR4_QUOTA_AVAIL_HARD_MASK
) {
1326 if (resbmap
& FATTR4_QUOTA_AVAIL_SOFT_MASK
) {
1331 (FATTR4_QUOTA_USED_MASK
|
1332 FATTR4_SPACE_AVAIL_MASK
|
1333 FATTR4_SPACE_FREE_MASK
|
1334 FATTR4_SPACE_TOTAL_MASK
|
1335 FATTR4_SPACE_USED_MASK
|
1336 FATTR4_SYSTEM_MASK
)) {
1338 if (resbmap
& FATTR4_QUOTA_USED_MASK
) {
1341 if (resbmap
& FATTR4_RAWDEV_MASK
) {
1342 fattr4_rawdev rawdev
;
1343 if (!xdr_fattr4_rawdev(xdrs
, &rawdev
))
1346 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1347 vap
->va_rdev
= makedevice(rawdev
.specdata1
,
1352 vap
->va_mask
|= AT_RDEV
;
1354 if (resbmap
& FATTR4_SPACE_AVAIL_MASK
) {
1355 if (!xdr_u_longlong_t(xdrs
,
1356 (u_longlong_t
*)&gesp
->n4g_sb
.f_bavail
))
1358 gesp
->n4g_sb
.f_bavail
/= DEV_BSIZE
;
1360 if (resbmap
& FATTR4_SPACE_FREE_MASK
) {
1361 if (!xdr_u_longlong_t(xdrs
,
1362 (u_longlong_t
*)&gesp
->n4g_sb
.f_bfree
))
1364 gesp
->n4g_sb
.f_bfree
/= DEV_BSIZE
;
1366 if (resbmap
& FATTR4_SPACE_TOTAL_MASK
) {
1367 if (!xdr_u_longlong_t(xdrs
,
1368 (u_longlong_t
*)&gesp
->n4g_sb
.f_blocks
))
1370 gesp
->n4g_sb
.f_blocks
/= DEV_BSIZE
;
1372 if (resbmap
& FATTR4_SPACE_USED_MASK
) {
1373 uint64_t space_used
;
1374 if (!xdr_u_longlong_t(xdrs
,
1375 (u_longlong_t
*)&space_used
))
1378 /* Compute space depending on device type */
1379 ASSERT((vap
->va_mask
& AT_TYPE
));
1380 if (vap
->va_type
== VREG
|| vap
->va_type
== VDIR
||
1381 vap
->va_type
== VLNK
) {
1382 vap
->va_nblocks
= (u_longlong_t
)
1383 ((space_used
+ (offset4
)DEV_BSIZE
-
1384 (offset4
)1) / (offset4
)DEV_BSIZE
);
1386 vap
->va_nblocks
= 0;
1388 vap
->va_mask
|= AT_NBLOCKS
;
1390 if (resbmap
& FATTR4_SYSTEM_MASK
) {
1395 (FATTR4_TIME_ACCESS_MASK
|
1396 FATTR4_TIME_ACCESS_SET_MASK
|
1397 FATTR4_TIME_BACKUP_MASK
|
1398 FATTR4_TIME_CREATE_MASK
|
1399 FATTR4_TIME_DELTA_MASK
|
1400 FATTR4_TIME_METADATA_MASK
|
1401 FATTR4_TIME_MODIFY_MASK
|
1402 FATTR4_TIME_MODIFY_SET_MASK
|
1403 FATTR4_MOUNTED_ON_FILEID_MASK
)) {
1405 if (resbmap
& FATTR4_TIME_ACCESS_MASK
) {
1409 if (!xdr_longlong_t(xdrs
,
1410 (longlong_t
*)&atime
.seconds
))
1412 if (!XDR_GETINT32(xdrs
, (int *)&atime
.nseconds
))
1414 error
= nfs4_time_ntov(&atime
, &vap
->va_atime
);
1416 garp
->n4g_attrerr
= error
;
1417 garp
->n4g_attrwhy
= NFS4_GETATTR_ATATIME_ERR
;
1419 vap
->va_mask
|= AT_ATIME
;
1421 if (resbmap
& FATTR4_TIME_ACCESS_SET_MASK
) {
1424 if (resbmap
& FATTR4_TIME_BACKUP_MASK
) {
1427 if (resbmap
& FATTR4_TIME_CREATE_MASK
) {
1430 if (resbmap
& FATTR4_TIME_DELTA_MASK
) {
1431 if ((!xdr_u_longlong_t(xdrs
,
1432 (u_longlong_t
*)&gesp
->n4g_delta
.seconds
)) ||
1433 (!xdr_u_int(xdrs
, &gesp
->n4g_delta
.nseconds
)))
1436 if (resbmap
& FATTR4_TIME_METADATA_MASK
) {
1440 if (!xdr_longlong_t(xdrs
, (longlong_t
*)&mdt
.seconds
))
1442 if (!XDR_GETINT32(xdrs
, (int32_t *)&mdt
.nseconds
))
1444 error
= nfs4_time_ntov(&mdt
, &vap
->va_ctime
);
1446 garp
->n4g_attrerr
= error
;
1447 garp
->n4g_attrwhy
= NFS4_GETATTR_ATCTIME_ERR
;
1449 vap
->va_mask
|= AT_CTIME
;
1451 if (resbmap
& FATTR4_TIME_MODIFY_MASK
) {
1455 if (!xdr_longlong_t(xdrs
,
1456 (longlong_t
*)&mtime
.seconds
))
1458 if (!XDR_GETINT32(xdrs
, (int32_t *)&mtime
.nseconds
))
1460 error
= nfs4_time_ntov(&mtime
, &vap
->va_mtime
);
1462 garp
->n4g_attrerr
= error
;
1463 garp
->n4g_attrwhy
= NFS4_GETATTR_ATMTIME_ERR
;
1465 vap
->va_mask
|= AT_MTIME
;
1467 if (resbmap
& FATTR4_TIME_MODIFY_SET_MASK
) {
1470 if (resbmap
& FATTR4_MOUNTED_ON_FILEID_MASK
) {
1471 if (!xdr_u_longlong_t(xdrs
,
1472 (u_longlong_t
*)&garp
->n4g_mon_fid
))
1474 garp
->n4g_mon_fid_valid
= 1;
1478 if (resbmap
& ~(NFS4_VATTR_MASK
| FATTR4_ACL_MASK
)) {
1479 /* copy only if not provided */
1480 if (garp
->n4g_ext_res
== NULL
) {
1481 garp
->n4g_ext_res
= kmem_alloc(sizeof (ges
), KM_SLEEP
);
1482 bcopy(&ges
, garp
->n4g_ext_res
, sizeof (ges
));
1490 * Inlined version of get_bitmap4 processing
1493 xdr_get_bitmap4_inline(uint32_t **iptr
)
1495 uint32_t resbmaplen
;
1497 uint32_t *ptr
= *iptr
;
1500 resbmaplen
= IXDR_GET_U_INT32(ptr
);
1502 /* Inline the bitmap and attrlen for common case of two word map */
1503 if (resbmaplen
== 2) {
1504 IXDR_GET_HYPER(ptr
, bm
);
1509 #if defined(_LITTLE_ENDIAN)
1510 bm
= IXDR_GET_U_INT32(ptr
);
1511 if (--resbmaplen
== 0) {
1515 *((uint32_t *)&bm
) |= IXDR_GET_U_INT32(ptr
);
1516 if (--resbmaplen
== 0) {
1523 #elif defined(_BIG_ENDIAN)
1524 *((uint32_t *)&bm
) = IXDR_GET_U_INT32(ptr
);
1525 if (--resbmaplen
== 0) {
1529 bm
|= IXDR_GET_U_INT32(ptr
);
1530 if (--resbmaplen
== 0) {
1546 xdr_ga_fattr_res_inline(uint32_t *ptr
, struct nfs4_ga_res
*garp
,
1547 bitmap4 resbmap
, bitmap4 argbmap
, struct mntinfo4
*mi
, ug_cache_t
*pug
)
1550 struct nfs4_ga_ext_res ges
, *gesp
;
1551 vattr_t
*vap
= &garp
->n4g_va
;
1553 if (garp
->n4g_ext_res
)
1554 gesp
= garp
->n4g_ext_res
;
1560 /* Check to see if the vattr should be pre-filled */
1561 if (argbmap
& NFS4_VATTR_MASK
)
1562 xdr_ga_prefill_vattr(garp
, mi
);
1564 if (argbmap
& NFS4_STATFS_ATTR_MASK
)
1565 xdr_ga_prefill_statvfs(gesp
, mi
);
1568 (FATTR4_SUPPORTED_ATTRS_MASK
|
1570 FATTR4_FH_EXPIRE_TYPE_MASK
|
1571 FATTR4_CHANGE_MASK
|
1573 FATTR4_LINK_SUPPORT_MASK
|
1574 FATTR4_SYMLINK_SUPPORT_MASK
|
1575 FATTR4_NAMED_ATTR_MASK
)) {
1577 if (resbmap
& FATTR4_SUPPORTED_ATTRS_MASK
) {
1578 gesp
->n4g_suppattrs
= xdr_get_bitmap4_inline(&ptr
);
1580 if (resbmap
& FATTR4_TYPE_MASK
) {
1581 vap
->va_type
= IXDR_GET_U_INT32(ptr
);
1583 if ((nfs_ftype4
)vap
->va_type
< NF4REG
||
1584 (nfs_ftype4
)vap
->va_type
> NF4NAMEDATTR
)
1585 vap
->va_type
= VBAD
;
1587 vap
->va_type
= nf4_to_vt
[vap
->va_type
];
1588 if (vap
->va_type
== VBLK
)
1589 vap
->va_blksize
= DEV_BSIZE
;
1591 vap
->va_mask
|= AT_TYPE
;
1593 if (resbmap
& FATTR4_FH_EXPIRE_TYPE_MASK
) {
1594 gesp
->n4g_fet
= IXDR_GET_U_INT32(ptr
);
1596 if (resbmap
& FATTR4_CHANGE_MASK
) {
1597 IXDR_GET_U_HYPER(ptr
, garp
->n4g_change
);
1598 garp
->n4g_change_valid
= 1;
1600 if (resbmap
& FATTR4_SIZE_MASK
) {
1601 IXDR_GET_U_HYPER(ptr
, vap
->va_size
);
1603 if (!NFS4_SIZE_OK(vap
->va_size
)) {
1604 garp
->n4g_attrerr
= EFBIG
;
1605 garp
->n4g_attrwhy
= NFS4_GETATTR_ATSIZE_ERR
;
1607 vap
->va_mask
|= AT_SIZE
;
1610 if (resbmap
& FATTR4_LINK_SUPPORT_MASK
) {
1611 truefalse
= IXDR_GET_U_INT32(ptr
);
1612 gesp
->n4g_pc4
.pc4_link_support
=
1613 (truefalse
? TRUE
: FALSE
);
1615 if (resbmap
& FATTR4_SYMLINK_SUPPORT_MASK
) {
1616 truefalse
= IXDR_GET_U_INT32(ptr
);
1617 gesp
->n4g_pc4
.pc4_symlink_support
=
1618 (truefalse
? TRUE
: FALSE
);
1620 if (resbmap
& FATTR4_NAMED_ATTR_MASK
) {
1621 truefalse
= IXDR_GET_U_INT32(ptr
);
1622 gesp
->n4g_pc4
.pc4_xattr_exists
= TRUE
;
1623 gesp
->n4g_pc4
.pc4_xattr_exists
=
1624 (truefalse
? TRUE
: FALSE
);
1629 FATTR4_UNIQUE_HANDLES_MASK
|
1630 FATTR4_LEASE_TIME_MASK
|
1631 FATTR4_RDATTR_ERROR_MASK
)) {
1633 if (resbmap
& FATTR4_FSID_MASK
) {
1634 IXDR_GET_U_HYPER(ptr
, garp
->n4g_fsid
.major
);
1635 IXDR_GET_U_HYPER(ptr
, garp
->n4g_fsid
.minor
);
1636 garp
->n4g_fsid_valid
= 1;
1638 if (resbmap
& FATTR4_UNIQUE_HANDLES_MASK
) {
1639 truefalse
= IXDR_GET_U_INT32(ptr
);
1640 gesp
->n4g_pc4
.pc4_unique_handles
=
1641 (truefalse
? TRUE
: FALSE
);
1643 if (resbmap
& FATTR4_LEASE_TIME_MASK
) {
1644 gesp
->n4g_leasetime
= IXDR_GET_U_INT32(ptr
);
1646 if (resbmap
& FATTR4_RDATTR_ERROR_MASK
) {
1647 gesp
->n4g_rdattr_error
= IXDR_GET_U_INT32(ptr
);
1652 FATTR4_ACLSUPPORT_MASK
|
1653 FATTR4_ARCHIVE_MASK
|
1654 FATTR4_CANSETTIME_MASK
)) {
1656 if (resbmap
& FATTR4_ACL_MASK
) {
1659 if (resbmap
& FATTR4_ACLSUPPORT_MASK
) {
1660 gesp
->n4g_aclsupport
= IXDR_GET_U_INT32(ptr
);
1662 if (resbmap
& FATTR4_ARCHIVE_MASK
) {
1665 if (resbmap
& FATTR4_CANSETTIME_MASK
) {
1666 truefalse
= IXDR_GET_U_INT32(ptr
);
1667 gesp
->n4g_pc4
.pc4_cansettime
=
1668 (truefalse
? TRUE
: FALSE
);
1672 (FATTR4_CASE_INSENSITIVE_MASK
|
1673 FATTR4_CASE_PRESERVING_MASK
|
1674 FATTR4_CHOWN_RESTRICTED_MASK
|
1675 FATTR4_FILEHANDLE_MASK
|
1676 FATTR4_FILEID_MASK
|
1677 FATTR4_FILES_AVAIL_MASK
|
1678 FATTR4_FILES_FREE_MASK
|
1679 FATTR4_FILES_TOTAL_MASK
)) {
1681 if (resbmap
& FATTR4_CASE_INSENSITIVE_MASK
) {
1682 truefalse
= IXDR_GET_U_INT32(ptr
);
1683 gesp
->n4g_pc4
.pc4_case_insensitive
=
1684 (truefalse
? TRUE
: FALSE
);
1686 if (resbmap
& FATTR4_CASE_PRESERVING_MASK
) {
1687 truefalse
= IXDR_GET_U_INT32(ptr
);
1688 gesp
->n4g_pc4
.pc4_case_preserving
=
1689 (truefalse
? TRUE
: FALSE
);
1691 if (resbmap
& FATTR4_CHOWN_RESTRICTED_MASK
) {
1692 truefalse
= IXDR_GET_U_INT32(ptr
);
1693 gesp
->n4g_pc4
.pc4_chown_restricted
=
1694 (truefalse
? TRUE
: FALSE
);
1696 if (resbmap
& FATTR4_FILEHANDLE_MASK
) {
1697 int len
= IXDR_GET_U_INT32(ptr
);
1699 gesp
->n4g_fh_u
.nfs_fh4_alt
.len
= 0;
1700 gesp
->n4g_fh_u
.nfs_fh4_alt
.val
=
1701 gesp
->n4g_fh_u
.nfs_fh4_alt
.data
;
1702 gesp
->n4g_fh_u
.n4g_fh
.nfs_fh4_len
= len
;
1704 bcopy(ptr
, gesp
->n4g_fh_u
.n4g_fh
.nfs_fh4_val
, len
);
1706 ptr
+= RNDUP(len
) / BYTES_PER_XDR_UNIT
;
1708 if (resbmap
& FATTR4_FILEID_MASK
) {
1709 IXDR_GET_U_HYPER(ptr
, vap
->va_nodeid
);
1710 vap
->va_mask
|= AT_NODEID
;
1712 if (resbmap
& FATTR4_FILES_AVAIL_MASK
) {
1713 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_favail
);
1715 if (resbmap
& FATTR4_FILES_FREE_MASK
) {
1716 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_ffree
);
1718 if (resbmap
& FATTR4_FILES_TOTAL_MASK
) {
1719 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_files
);
1723 (FATTR4_FS_LOCATIONS_MASK
|
1724 FATTR4_HIDDEN_MASK
|
1725 FATTR4_HOMOGENEOUS_MASK
)) {
1727 if (resbmap
& FATTR4_FS_LOCATIONS_MASK
) {
1730 if (resbmap
& FATTR4_HIDDEN_MASK
) {
1733 if (resbmap
& FATTR4_HOMOGENEOUS_MASK
) {
1734 truefalse
= IXDR_GET_U_INT32(ptr
);
1735 gesp
->n4g_pc4
.pc4_homogeneous
=
1736 (truefalse
? TRUE
: FALSE
);
1740 (FATTR4_MAXFILESIZE_MASK
|
1741 FATTR4_MAXLINK_MASK
|
1742 FATTR4_MAXNAME_MASK
|
1743 FATTR4_MAXREAD_MASK
|
1744 FATTR4_MAXWRITE_MASK
)) {
1746 if (resbmap
& FATTR4_MAXFILESIZE_MASK
) {
1747 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_maxfilesize
);
1749 if (resbmap
& FATTR4_MAXLINK_MASK
) {
1750 gesp
->n4g_pc4
.pc4_link_max
= IXDR_GET_U_INT32(ptr
);
1752 if (resbmap
& FATTR4_MAXNAME_MASK
) {
1753 gesp
->n4g_pc4
.pc4_name_max
= IXDR_GET_U_INT32(ptr
);
1754 gesp
->n4g_sb
.f_namemax
= gesp
->n4g_pc4
.pc4_name_max
;
1756 if (resbmap
& FATTR4_MAXREAD_MASK
) {
1757 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_maxread
);
1759 if (resbmap
& FATTR4_MAXWRITE_MASK
) {
1760 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_maxwrite
);
1764 (FATTR4_MIMETYPE_MASK
|
1766 FATTR4_NO_TRUNC_MASK
|
1767 FATTR4_NUMLINKS_MASK
)) {
1769 if (resbmap
& FATTR4_MIMETYPE_MASK
) {
1772 if (resbmap
& FATTR4_MODE_MASK
) {
1773 vap
->va_mode
= IXDR_GET_U_INT32(ptr
);
1774 vap
->va_mask
|= AT_MODE
;
1776 if (resbmap
& FATTR4_NO_TRUNC_MASK
) {
1777 truefalse
= IXDR_GET_U_INT32(ptr
);
1778 gesp
->n4g_pc4
.pc4_no_trunc
=
1779 (truefalse
? TRUE
: FALSE
);
1781 if (resbmap
& FATTR4_NUMLINKS_MASK
) {
1782 vap
->va_nlink
= IXDR_GET_U_INT32(ptr
);
1783 vap
->va_mask
|= AT_NLINK
;
1787 (FATTR4_OWNER_MASK
|
1788 FATTR4_OWNER_GROUP_MASK
|
1789 FATTR4_QUOTA_AVAIL_HARD_MASK
|
1790 FATTR4_QUOTA_AVAIL_SOFT_MASK
)) {
1792 if (resbmap
& FATTR4_OWNER_MASK
) {
1793 uint_t
*owner_length
, ol
;
1794 char *owner_val
= NULL
;
1798 /* get the OWNER_LENGTH */
1799 ol
= IXDR_GET_U_INT32(ptr
);
1801 /* Manage the owner length location */
1802 if (pug
&& ol
<= MAX_OG_NAME
) {
1803 owner_length
= &pug
->u_curr
.utf8string_len
;
1809 /* find memory to store the decode */
1810 if (*owner_length
> MAX_OG_NAME
|| pug
== NULL
)
1811 owner_val
= (char *)ptr
;
1813 owner_val
= (char *)ptr
;
1815 /* Optimize for matching if called for */
1817 *owner_length
== pug
->u_last
.utf8string_len
&&
1818 bcmp(owner_val
, pug
->u_last
.utf8string_val
,
1819 *owner_length
) == 0) {
1820 vap
->va_uid
= pug
->uid
;
1821 vap
->va_mask
|= AT_UID
;
1825 ov
.utf8string_len
= *owner_length
;
1826 ov
.utf8string_val
= owner_val
;
1827 error
= nfs_idmap_str_uid(&ov
, &uid
, FALSE
);
1829 * String was mapped, but to nobody because
1830 * we are nfsmapid, indicate it should not
1833 if (error
== ENOTSUP
) {
1836 NFS4_GETATTR_NOCACHE_OK
;
1840 garp
->n4g_attrerr
= error
;
1842 NFS4_GETATTR_ATUID_ERR
;
1845 vap
->va_mask
|= AT_UID
;
1846 /* save the results for next time */
1847 if (pug
&& ol
<= MAX_OG_NAME
) {
1849 pug
->u_curr
.utf8string_len
=
1852 pug
->u_curr
.utf8string_val
,
1854 U_SWAP_CURR_LAST(pug
);
1858 ptr
+= RNDUP(ol
) / BYTES_PER_XDR_UNIT
;
1860 if (resbmap
& FATTR4_OWNER_GROUP_MASK
) {
1861 uint_t
*group_length
, gl
;
1862 char *group_val
= NULL
;
1866 /* get the OWNER_GROUP_LENGTH */
1867 gl
= IXDR_GET_U_INT32(ptr
);
1869 /* Manage the group length location */
1870 if (pug
&& gl
<= MAX_OG_NAME
) {
1871 group_length
= &pug
->g_curr
.utf8string_len
;
1877 /* find memory to store the decode */
1878 if (*group_length
> MAX_OG_NAME
|| pug
== NULL
)
1879 group_val
= (char *)ptr
;
1881 group_val
= (char *)ptr
;
1883 /* Optimize for matching if called for */
1885 *group_length
== pug
->g_last
.utf8string_len
&&
1886 bcmp(group_val
, pug
->g_last
.utf8string_val
,
1887 *group_length
) == 0) {
1888 vap
->va_gid
= pug
->gid
;
1889 vap
->va_mask
|= AT_GID
;
1893 gv
.utf8string_len
= *group_length
;
1894 gv
.utf8string_val
= group_val
;
1895 error
= nfs_idmap_str_gid(&gv
, &gid
, FALSE
);
1897 * String was mapped, but to nobody because
1898 * we are nfsmapid, indicate it should not
1901 if (error
== ENOTSUP
) {
1904 NFS4_GETATTR_NOCACHE_OK
;
1908 garp
->n4g_attrerr
= error
;
1910 NFS4_GETATTR_ATGID_ERR
;
1913 vap
->va_mask
|= AT_GID
;
1914 if (pug
&& gl
<= MAX_OG_NAME
) {
1916 pug
->g_curr
.utf8string_len
=
1919 pug
->g_curr
.utf8string_val
,
1921 G_SWAP_CURR_LAST(pug
);
1925 ptr
+= RNDUP(gl
) / BYTES_PER_XDR_UNIT
;
1927 if (resbmap
& FATTR4_QUOTA_AVAIL_HARD_MASK
) {
1930 if (resbmap
& FATTR4_QUOTA_AVAIL_SOFT_MASK
) {
1935 (FATTR4_QUOTA_USED_MASK
|
1936 FATTR4_SPACE_AVAIL_MASK
|
1937 FATTR4_SPACE_FREE_MASK
|
1938 FATTR4_SPACE_TOTAL_MASK
|
1939 FATTR4_SPACE_USED_MASK
|
1940 FATTR4_SYSTEM_MASK
)) {
1942 if (resbmap
& FATTR4_QUOTA_USED_MASK
) {
1945 if (resbmap
& FATTR4_RAWDEV_MASK
) {
1946 fattr4_rawdev rawdev
;
1948 rawdev
.specdata1
= IXDR_GET_U_INT32(ptr
);
1949 rawdev
.specdata2
= IXDR_GET_U_INT32(ptr
);
1951 if (vap
->va_type
== VCHR
|| vap
->va_type
== VBLK
) {
1952 vap
->va_rdev
= makedevice(rawdev
.specdata1
,
1957 vap
->va_mask
|= AT_RDEV
;
1959 if (resbmap
& FATTR4_SPACE_AVAIL_MASK
) {
1960 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_bavail
);
1961 gesp
->n4g_sb
.f_bavail
/= DEV_BSIZE
;
1963 if (resbmap
& FATTR4_SPACE_FREE_MASK
) {
1964 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_bfree
);
1965 gesp
->n4g_sb
.f_bfree
/= DEV_BSIZE
;
1967 if (resbmap
& FATTR4_SPACE_TOTAL_MASK
) {
1968 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_sb
.f_blocks
);
1969 gesp
->n4g_sb
.f_blocks
/= DEV_BSIZE
;
1971 if (resbmap
& FATTR4_SPACE_USED_MASK
) {
1972 uint64_t space_used
;
1973 IXDR_GET_U_HYPER(ptr
, space_used
);
1975 /* Compute space depending on device type */
1976 ASSERT((vap
->va_mask
& AT_TYPE
));
1977 if (vap
->va_type
== VREG
|| vap
->va_type
== VDIR
||
1978 vap
->va_type
== VLNK
) {
1979 vap
->va_nblocks
= (u_longlong_t
)
1980 ((space_used
+ (offset4
)DEV_BSIZE
-
1981 (offset4
)1) / (offset4
)DEV_BSIZE
);
1983 vap
->va_nblocks
= 0;
1985 vap
->va_mask
|= AT_NBLOCKS
;
1987 if (resbmap
& FATTR4_SYSTEM_MASK
) {
1992 (FATTR4_TIME_ACCESS_MASK
|
1993 FATTR4_TIME_ACCESS_SET_MASK
|
1994 FATTR4_TIME_BACKUP_MASK
|
1995 FATTR4_TIME_CREATE_MASK
|
1996 FATTR4_TIME_DELTA_MASK
|
1997 FATTR4_TIME_METADATA_MASK
|
1998 FATTR4_TIME_MODIFY_MASK
|
1999 FATTR4_TIME_MODIFY_SET_MASK
|
2000 FATTR4_MOUNTED_ON_FILEID_MASK
)) {
2002 if (resbmap
& FATTR4_TIME_ACCESS_MASK
) {
2006 IXDR_GET_U_HYPER(ptr
, atime
.seconds
);
2007 atime
.nseconds
= IXDR_GET_U_INT32(ptr
);
2009 error
= nfs4_time_ntov(&atime
, &vap
->va_atime
);
2011 garp
->n4g_attrerr
= error
;
2012 garp
->n4g_attrwhy
= NFS4_GETATTR_ATATIME_ERR
;
2014 vap
->va_mask
|= AT_ATIME
;
2016 if (resbmap
& FATTR4_TIME_ACCESS_SET_MASK
) {
2019 if (resbmap
& FATTR4_TIME_BACKUP_MASK
) {
2022 if (resbmap
& FATTR4_TIME_CREATE_MASK
) {
2025 if (resbmap
& FATTR4_TIME_DELTA_MASK
) {
2026 IXDR_GET_U_HYPER(ptr
, gesp
->n4g_delta
.seconds
);
2027 gesp
->n4g_delta
.nseconds
= IXDR_GET_U_INT32(ptr
);
2029 if (resbmap
& FATTR4_TIME_METADATA_MASK
) {
2033 IXDR_GET_U_HYPER(ptr
, mdt
.seconds
);
2034 mdt
.nseconds
= IXDR_GET_U_INT32(ptr
);
2036 error
= nfs4_time_ntov(&mdt
, &vap
->va_ctime
);
2038 garp
->n4g_attrerr
= error
;
2039 garp
->n4g_attrwhy
= NFS4_GETATTR_ATCTIME_ERR
;
2041 vap
->va_mask
|= AT_CTIME
;
2043 if (resbmap
& FATTR4_TIME_MODIFY_MASK
) {
2047 IXDR_GET_U_HYPER(ptr
, mtime
.seconds
);
2048 mtime
.nseconds
= IXDR_GET_U_INT32(ptr
);
2050 error
= nfs4_time_ntov(&mtime
, &vap
->va_mtime
);
2052 garp
->n4g_attrerr
= error
;
2053 garp
->n4g_attrwhy
= NFS4_GETATTR_ATMTIME_ERR
;
2055 vap
->va_mask
|= AT_MTIME
;
2057 if (resbmap
& FATTR4_TIME_MODIFY_SET_MASK
) {
2060 if (resbmap
& FATTR4_MOUNTED_ON_FILEID_MASK
) {
2061 IXDR_GET_U_HYPER(ptr
, garp
->n4g_mon_fid
);
2062 garp
->n4g_mon_fid_valid
= 1;
2067 * FATTR4_ACL_MASK is not yet supported by this function, but
2068 * we check against it anyway, in case it ever is.
2070 if (resbmap
& ~(NFS4_VATTR_MASK
| FATTR4_ACL_MASK
)) {
2071 /* copy only if not provided */
2072 if (garp
->n4g_ext_res
== NULL
) {
2073 garp
->n4g_ext_res
= kmem_alloc(sizeof (ges
), KM_SLEEP
);
2074 bcopy(&ges
, garp
->n4g_ext_res
, sizeof (ges
));
2083 * "." and ".." buffers for filling in on read and readdir
2084 * calls. Intialize the first time and fill in on every
2085 * call to to readdir.
2087 char *nfs4_dot_entries
;
2088 char *nfs4_dot_dot_entry
;
2091 * Create the "." or ".." and pad the buffer once so they are
2092 * copied out as required into the user supplied buffer everytime.
2093 * DIRENT64_RECLEN(sizeof (".") - 1) = DIRENT64_RECLEN(1)
2094 * DIRENT64_RECLEN(sizeof ("..") - 1) = DIRENT64_RECLEN(2)
2097 nfs4_init_dot_entries()
2099 struct dirent64
*odp
;
2102 * zalloc it so it zeros the buffer out. Need
2103 * to just do it once.
2105 nfs4_dot_entries
= kmem_zalloc(DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2),
2108 odp
= (struct dirent64
*)nfs4_dot_entries
;
2109 odp
->d_off
= 1; /* magic cookie for "." entry */
2110 odp
->d_reclen
= DIRENT64_RECLEN(1);
2111 odp
->d_name
[0] = '.';
2112 odp
->d_name
[1] = '\0';
2114 nfs4_dot_dot_entry
= nfs4_dot_entries
+ DIRENT64_RECLEN(1);
2115 odp
= (struct dirent64
*)nfs4_dot_dot_entry
;
2118 odp
->d_reclen
= DIRENT64_RECLEN(2);
2119 odp
->d_name
[0] = '.';
2120 odp
->d_name
[1] = '.';
2121 odp
->d_name
[2] = '\0';
2125 nfs4_destroy_dot_entries()
2127 if (nfs4_dot_entries
)
2128 kmem_free(nfs4_dot_entries
, DIRENT64_RECLEN(1) +
2129 DIRENT64_RECLEN(2));
2131 nfs4_dot_entries
= nfs4_dot_dot_entry
= NULL
;
2135 xdr_READDIR4res_clnt(XDR
*xdrs
, READDIR4res_clnt
*objp
, READDIR4args
*aobjp
)
2138 rddir4_cache
*rdc
= aobjp
->rdc
;
2139 dirent64_t
*dp
= NULL
;
2140 int entry_length
= 0;
2145 struct nfs4_ga_ext_res ges
;
2146 uint64_t last_cookie
= 0;
2148 ug_cache_t
*pug
= NULL
;
2150 ASSERT(xdrs
->x_op
== XDR_DECODE
);
2151 ASSERT(rdc
->entries
== NULL
);
2152 ASSERT(aobjp
->dircount
> 0);
2154 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2156 if (objp
->status
!= NFS4_OK
)
2159 gar
.n4g_va
.va_mask
= 0;
2160 gar
.n4g_change_valid
= 0;
2161 gar
.n4g_mon_fid_valid
= 0;
2162 gar
.n4g_fsid_valid
= 0;
2163 gar
.n4g_vsa
.vsa_mask
= 0;
2164 gar
.n4g_attrwhy
= NFS4_GETATTR_OP_OK
;
2165 ges
.n4g_pc4
.pc4_cache_valid
= 0;
2166 ges
.n4g_pc4
.pc4_xattr_valid
= 0;
2167 gar
.n4g_ext_res
= &ges
;
2169 /* READDIR4res_clnt_free needs to kmem_free this buffer */
2170 rdc
->entries
= kmem_alloc(aobjp
->dircount
, KM_SLEEP
);
2172 dp
= (dirent64_t
*)rdc
->entries
;
2173 rdc
->entlen
= rdc
->buflen
= space_left
= aobjp
->dircount
;
2175 /* Fill in dot and dot-dot if needed */
2176 if (rdc
->nfs4_cookie
== (nfs_cookie4
) 0 ||
2177 rdc
->nfs4_cookie
== (nfs_cookie4
) 1) {
2179 if (rdc
->nfs4_cookie
== (nfs_cookie4
)0) {
2180 bcopy(nfs4_dot_entries
, rdc
->entries
,
2181 DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2));
2183 dp
= (struct dirent64
*)(((char *)dp
) +
2184 DIRENT64_RECLEN(1));
2186 dp
= (struct dirent64
*)(((char *)dp
) +
2187 DIRENT64_RECLEN(2));
2188 space_left
-= DIRENT64_RECLEN(1) + DIRENT64_RECLEN(2);
2190 } else { /* for ".." entry */
2191 bcopy(nfs4_dot_dot_entry
, rdc
->entries
,
2192 DIRENT64_RECLEN(2));
2195 dp
= (struct dirent64
*)(((char *)dp
) +
2196 DIRENT64_RECLEN(2));
2197 space_left
-= DIRENT64_RECLEN(2);
2199 /* Magic NFSv4 number for entry after start */
2203 /* Get the cookie VERIFIER */
2204 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cookieverf
))
2207 /* Get the do-we-have-a-next-entry BOOL */
2208 if (!xdr_bool(xdrs
, &more_data
))
2211 if (aobjp
->attr_request
& (FATTR4_OWNER_MASK
| FATTR4_OWNER_GROUP_MASK
))
2212 pug
= alloc_ugcache();
2219 /* Get the COOKIE */
2220 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&cookie
))
2223 /* Get the LENGTH of the entry name */
2224 if (!xdr_u_int(xdrs
, &namelen
))
2229 * With the length of the directory entry name
2230 * in hand, figure out if there is room left
2231 * to encode it for the requestor. If not,
2232 * that is okay, but the rest of the readdir
2233 * operation result must be decoded in the
2234 * case there are following operations
2235 * in the compound request. Therefore, mark
2236 * the rest of the response as "skip" and
2237 * decode or skip the remaining data
2239 entry_length
= DIRENT64_RECLEN(namelen
);
2240 if (space_left
< entry_length
)
2244 /* Get the NAME of the entry */
2246 if (!xdr_opaque(xdrs
, dp
->d_name
, namelen
))
2248 bzero(&dp
->d_name
[namelen
],
2249 DIRENT64_NAMELEN(entry_length
) - namelen
);
2250 dp
->d_off
= last_cookie
= cookie
;
2251 dp
->d_reclen
= entry_length
;
2253 if (!XDR_CONTROL(xdrs
, XDR_SKIPBYTES
, &namelen
))
2257 /* Get the attribute BITMAP */
2258 if (!xdr_bitmap4(xdrs
, &resbmap
))
2260 /* Get the LENGTH of the attributes */
2261 if (!xdr_u_int(xdrs
, (uint_t
*)&attrlen
))
2264 /* Get the ATTRIBUTES */
2268 if (!(resbmap
& FATTR4_ACL_MASK
) &&
2269 (ptr
= (uint32_t *)XDR_INLINE(xdrs
, attrlen
))
2271 if (!xdr_ga_fattr_res_inline(ptr
, &gar
, resbmap
,
2272 aobjp
->attr_request
, aobjp
->mi
, pug
))
2275 if (!xdr_ga_fattr_res(xdrs
, &gar
, resbmap
,
2276 aobjp
->attr_request
, aobjp
->mi
, pug
))
2280 /* Fill in the d_ino per the server's fid values */
2282 * Important to note that the mounted on fileid
2283 * is returned in d_ino if supported. This is
2284 * expected, readdir returns the mounted on fileid
2285 * while stat() returns the fileid of the object
2286 * on "top" of the mount.
2288 if (gar
.n4g_mon_fid_valid
)
2289 dp
->d_ino
= gar
.n4g_mon_fid
;
2290 else if (gar
.n4g_va
.va_mask
& AT_NODEID
)
2291 dp
->d_ino
= gar
.n4g_va
.va_nodeid
;
2295 /* See about creating an rnode for this entry */
2297 (NFS4_VATTR_MASK
| FATTR4_FILEHANDLE_MASK
)) ==
2298 (NFS4_VATTR_MASK
| FATTR4_FILEHANDLE_MASK
)) {
2299 nfs4_sharedfh_t
*sfhp
;
2302 sfhp
= sfh4_put(&ges
.n4g_fh_u
.n4g_fh
,
2304 vp
= makenfs4node(sfhp
, &gar
,
2309 fn_get(VTOSV(aobjp
->dvp
)->sv_name
,
2312 dnlc_update(aobjp
->dvp
, dp
->d_name
, vp
);
2316 dp
= (struct dirent64
*)(((caddr_t
)dp
) + dp
->d_reclen
);
2318 space_left
-= entry_length
;
2321 if (!XDR_CONTROL(xdrs
, XDR_SKIPBYTES
, &attrlen
))
2325 /* Get the do-we-have-a-next-entry BOOL */
2326 if (!xdr_bool(xdrs
, &more_data
))
2331 kmem_free(pug
, sizeof (ug_cache_t
));
2336 * Finish up the rddir cache
2337 * If no entries were returned, free up buffer &
2338 * set ncookie to the starting cookie for this
2339 * readdir request so that the direof caching
2340 * will work properly.
2342 ASSERT(rdc
->entries
);
2343 if (last_cookie
== 0) {
2344 kmem_free(rdc
->entries
, rdc
->entlen
);
2345 rdc
->entries
= NULL
;
2346 last_cookie
= rdc
->nfs4_cookie
;
2349 rdc
->actlen
= rdc
->entlen
- space_left
;
2350 rdc
->nfs4_ncookie
= last_cookie
;
2352 /* Get the EOF marker */
2353 if (!xdr_bool(xdrs
, &objp
->eof
))
2357 * If the server returns eof and there were no
2358 * skipped entries, set eof
2360 rdc
->eof
= (objp
->eof
&& !skip_to_end
) ? TRUE
: FALSE
;
2363 * If we encoded entries we are done
2371 * If there were no entries and we skipped because
2372 * there was not enough space, return EINVAL
2375 rdc
->error
= EINVAL
;
2380 * No entries, nothing skipped, and EOF, return OK.
2382 if (objp
->eof
== TRUE
) {
2388 * No entries, nothing skipped, and not EOF
2389 * probably a bad cookie, return ENOENT.
2391 rdc
->error
= ENOENT
;
2396 kmem_free(rdc
->entries
, rdc
->entlen
);
2397 rdc
->entries
= NULL
;
2400 kmem_free(pug
, sizeof (ug_cache_t
));
2408 * Returns: FALSE on raw data processing errors, TRUE otherwise.
2410 * This function pre-processes the OP_GETATTR response, and then
2411 * calls common routines to process the GETATTR fattr4 results into
2412 * vnode attributes and other components that the client is interested
2413 * in. If an error other than an RPC error is encountered, the details
2414 * of the error are filled into objp, although the result of the
2415 * processing is set to TRUE.
2418 xdr_ga_res(XDR
*xdrs
, GETATTR4res
*objp
, GETATTR4args
*aobjp
)
2426 ASSERT(xdrs
->x_op
== XDR_DECODE
);
2428 /* Initialize objp attribute error values */
2429 objp
->ga_res
.n4g_attrerr
=
2430 objp
->ga_res
.n4g_attrwhy
= NFS4_GETATTR_OP_OK
;
2432 if (!xdr_bitmap4(xdrs
, &resbmap
))
2435 /* save the response bitmap for the caller */
2436 objp
->ga_res
.n4g_resbmap
= resbmap
;
2439 if (!XDR_GETINT32(xdrs
, (int32_t *)&attrlen
))
2443 * Handle case where request and response bitmaps don't match.
2445 if (aobjp
->attr_request
&& aobjp
->attr_request
!= resbmap
) {
2449 * Return error for case where server sent extra attributes
2450 * because the "unknown" attributes may be anywhere in the
2451 * xdr stream and can't be properly processed.
2453 deltabmap
= ((aobjp
->attr_request
^ resbmap
) & resbmap
);
2455 objp
->ga_res
.n4g_attrerr
= EINVAL
;
2456 objp
->ga_res
.n4g_attrwhy
= NFS4_GETATTR_BITMAP_ERR
;
2461 * Return error for case where there is a mandatory
2462 * attribute missing in the server response. Note that
2463 * missing recommended attributes are evaluated in the
2464 * specific routines that decode the server response.
2466 deltabmap
= ((aobjp
->attr_request
^ resbmap
)
2467 & aobjp
->attr_request
);
2468 if ((deltabmap
& FATTR4_MANDATTR_MASK
)) {
2469 objp
->ga_res
.n4g_attrerr
= EINVAL
;
2470 objp
->ga_res
.n4g_attrwhy
= NFS4_GETATTR_MANDATTR_ERR
;
2475 /* Check to see if the attrs can be inlined and go for it if so */
2477 if (!(resbmap
& FATTR4_ACL_MASK
) &&
2478 (ptr
= (uint32_t *)XDR_INLINE(xdrs
, attrlen
)) != NULL
)
2479 return (xdr_ga_fattr_res_inline(ptr
, &objp
->ga_res
,
2480 resbmap
, aobjp
->attr_request
, aobjp
->mi
, NULL
));
2483 return (xdr_ga_fattr_res(xdrs
, &objp
->ga_res
,
2484 resbmap
, aobjp
->attr_request
, aobjp
->mi
, NULL
));
2487 #if defined(DEBUG) && !defined(lint)
2489 * We assume that an enum is a 32-bit value, check it once
2491 static enum szchk
{ SZVAL
} szchkvar
;
2495 xdr_settime4(XDR
*xdrs
, settime4
*objp
)
2497 #if defined(DEBUG) && !defined(lint)
2498 ASSERT(sizeof (szchkvar
) == sizeof (int32_t));
2500 if (xdrs
->x_op
== XDR_FREE
)
2503 if (!xdr_int(xdrs
, (int *)&objp
->set_it
))
2505 if (objp
->set_it
!= SET_TO_CLIENT_TIME4
)
2508 if (!xdr_longlong_t(xdrs
, (longlong_t
*)&objp
->time
.seconds
))
2510 return (xdr_u_int(xdrs
, &objp
->time
.nseconds
));
2514 xdr_fattr4(XDR
*xdrs
, fattr4
*objp
)
2516 if (xdrs
->x_op
!= XDR_FREE
) {
2517 if (!xdr_bitmap4(xdrs
, &objp
->attrmask
))
2519 return (xdr_bytes(xdrs
, (char **)&objp
->attrlist4
,
2520 (uint_t
*)&objp
->attrlist4_len
, NFS4_FATTR4_LIMIT
));
2524 * Optimized free case
2526 if (objp
->attrlist4
!= NULL
)
2527 kmem_free(objp
->attrlist4
, objp
->attrlist4_len
);
2532 xdr_ACCESS4res(XDR
*xdrs
, ACCESS4res
*objp
)
2534 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2536 if (objp
->status
!= NFS4_OK
)
2538 if (!xdr_u_int(xdrs
, &objp
->supported
))
2540 return (xdr_u_int(xdrs
, &objp
->access
));
2544 xdr_CLOSE4args(XDR
*xdrs
, CLOSE4args
*objp
)
2546 if (!xdr_u_int(xdrs
, &objp
->seqid
))
2548 if (!xdr_u_int(xdrs
, &objp
->open_stateid
.seqid
))
2550 return (xdr_opaque(xdrs
, objp
->open_stateid
.other
, NFS4_OTHER_SIZE
));
2554 xdr_CLOSE4res(XDR
*xdrs
, CLOSE4res
*objp
)
2556 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2558 if (objp
->status
!= NFS4_OK
)
2560 if (!xdr_u_int(xdrs
, &objp
->open_stateid
.seqid
))
2562 return (xdr_opaque(xdrs
, objp
->open_stateid
.other
, NFS4_OTHER_SIZE
));
2566 xdr_CREATE4args(XDR
*xdrs
, CREATE4args
*objp
)
2568 if (xdrs
->x_op
!= XDR_FREE
) {
2569 if (!xdr_int(xdrs
, (int32_t *)&objp
->type
))
2571 switch (objp
->type
) {
2573 if (!xdr_bytes(xdrs
,
2574 (char **)&objp
->ftype4_u
.linkdata
.linktext4_val
,
2575 (uint_t
*)&objp
->ftype4_u
.linkdata
.linktext4_len
,
2576 NFS4_MAX_UTF8STRING
))
2581 if (!xdr_u_int(xdrs
, &objp
->ftype4_u
.devdata
.specdata1
))
2583 if (!xdr_u_int(xdrs
, &objp
->ftype4_u
.devdata
.specdata2
))
2590 break; /* server should return NFS4ERR_BADTYPE */
2592 if (!xdr_bytes(xdrs
, (char **)&objp
->objname
.utf8string_val
,
2593 (uint_t
*)&objp
->objname
.utf8string_len
,
2594 NFS4_MAX_UTF8STRING
))
2596 return (xdr_fattr4(xdrs
, &objp
->createattrs
));
2600 * Optimized free case
2602 if (objp
->type
== NF4LNK
) {
2603 if (objp
->ftype4_u
.linkdata
.linktext4_val
!= NULL
)
2604 kmem_free(objp
->ftype4_u
.linkdata
.linktext4_val
,
2605 objp
->ftype4_u
.linkdata
.linktext4_len
);
2607 if (objp
->objname
.utf8string_val
!= NULL
)
2608 kmem_free(objp
->objname
.utf8string_val
,
2609 objp
->objname
.utf8string_len
);
2610 return (xdr_fattr4(xdrs
, &objp
->createattrs
));
2614 xdr_CREATE4cargs(XDR
*xdrs
, CREATE4cargs
*objp
)
2618 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
2620 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->type
))
2622 switch (objp
->type
) {
2624 len
= strlen(objp
->ftype4_u
.clinkdata
);
2625 if (len
> NFS4_MAX_UTF8STRING
)
2627 if (!XDR_PUTINT32(xdrs
, &len
))
2629 if (!xdr_opaque(xdrs
, objp
->ftype4_u
.clinkdata
, len
))
2634 if (!XDR_PUTINT32(xdrs
,
2635 (int32_t *)&objp
->ftype4_u
.devdata
.specdata1
))
2637 if (!XDR_PUTINT32(xdrs
,
2638 (int32_t *)&objp
->ftype4_u
.devdata
.specdata2
))
2645 break; /* server should return NFS4ERR_BADTYPE */
2648 len
= strlen(objp
->cname
);
2649 if (len
> NFS4_MAX_UTF8STRING
)
2651 if (!XDR_PUTINT32(xdrs
, &len
))
2653 if (!xdr_opaque(xdrs
, objp
->cname
, len
))
2656 return (xdr_fattr4(xdrs
, &objp
->createattrs
));
2660 xdr_CREATE4res(XDR
*xdrs
, CREATE4res
*objp
)
2662 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2664 if (objp
->status
!= NFS4_OK
)
2666 if (!xdr_bool(xdrs
, &objp
->cinfo
.atomic
))
2668 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.before
))
2670 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.after
))
2672 return (xdr_bitmap4(xdrs
, &objp
->attrset
));
2676 xdr_LINK4res(XDR
*xdrs
, LINK4res
*objp
)
2678 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2680 if (objp
->status
!= NFS4_OK
)
2682 if (!xdr_bool(xdrs
, &objp
->cinfo
.atomic
))
2684 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.before
))
2686 return (xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.after
));
2690 xdr_LOCK4args(XDR
*xdrs
, LOCK4args
*objp
)
2692 if (xdrs
->x_op
!= XDR_FREE
) {
2693 if (!xdr_int(xdrs
, (int *)&objp
->locktype
))
2695 if (!xdr_bool(xdrs
, &objp
->reclaim
))
2697 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->offset
))
2699 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->length
))
2701 if (!xdr_bool(xdrs
, &objp
->locker
.new_lock_owner
))
2703 if (objp
->locker
.new_lock_owner
== TRUE
) {
2704 if (!xdr_u_int(xdrs
, &objp
->locker
.locker4_u
.open_owner
.
2707 if (!xdr_u_int(xdrs
, &objp
->locker
.locker4_u
.open_owner
.
2708 open_stateid
.seqid
))
2710 if (!xdr_opaque(xdrs
, objp
->locker
.locker4_u
.open_owner
.
2711 open_stateid
.other
, NFS4_OTHER_SIZE
))
2713 if (!xdr_u_int(xdrs
, &objp
->locker
.locker4_u
.open_owner
.
2716 if (!xdr_u_longlong_t(xdrs
,
2717 (u_longlong_t
*)&objp
->locker
.locker4_u
.
2718 open_owner
.lock_owner
.clientid
))
2720 return (xdr_bytes(xdrs
,
2721 (char **)&objp
->locker
.locker4_u
.open_owner
.
2722 lock_owner
.owner_val
,
2723 (uint_t
*)&objp
->locker
.locker4_u
.open_owner
.
2724 lock_owner
.owner_len
,
2725 NFS4_OPAQUE_LIMIT
));
2728 if (objp
->locker
.new_lock_owner
!= FALSE
)
2731 if (!xdr_u_int(xdrs
, &objp
->locker
.locker4_u
.lock_owner
.
2732 lock_stateid
.seqid
))
2734 if (!xdr_opaque(xdrs
, objp
->locker
.locker4_u
.lock_owner
.
2735 lock_stateid
.other
, NFS4_OTHER_SIZE
))
2737 return (xdr_u_int(xdrs
, &objp
->locker
.locker4_u
.lock_owner
.
2742 * Optimized free case
2744 if (objp
->locker
.new_lock_owner
== TRUE
) {
2745 if (objp
->locker
.locker4_u
.open_owner
.lock_owner
.owner_val
!=
2747 kmem_free(objp
->locker
.locker4_u
.open_owner
.lock_owner
.
2749 objp
->locker
.locker4_u
.open_owner
.lock_owner
.
2758 xdr_LOCK4res(XDR
*xdrs
, LOCK4res
*objp
)
2760 if (xdrs
->x_op
!= XDR_FREE
) {
2761 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2763 if (objp
->status
== NFS4_OK
) {
2764 if (!xdr_u_int(xdrs
,
2765 &objp
->LOCK4res_u
.lock_stateid
.seqid
))
2767 return (xdr_opaque(xdrs
,
2768 objp
->LOCK4res_u
.lock_stateid
.other
,
2771 if (objp
->status
!= NFS4ERR_DENIED
)
2774 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->LOCK4res_u
.
2777 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->LOCK4res_u
.
2780 if (!xdr_int(xdrs
, (int *)&objp
->LOCK4res_u
.denied
.locktype
))
2782 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->LOCK4res_u
.
2783 denied
.owner
.clientid
))
2785 return (xdr_bytes(xdrs
,
2786 (char **)&objp
->LOCK4res_u
.denied
.owner
.owner_val
,
2787 (uint_t
*)&objp
->LOCK4res_u
.denied
.owner
.owner_len
,
2788 NFS4_OPAQUE_LIMIT
));
2792 * Optimized free case
2794 if (objp
->status
== NFS4_OK
|| objp
->status
!= NFS4ERR_DENIED
)
2797 if (objp
->LOCK4res_u
.denied
.owner
.owner_val
!= NULL
)
2798 kmem_free(objp
->LOCK4res_u
.denied
.owner
.owner_val
,
2799 objp
->LOCK4res_u
.denied
.owner
.owner_len
);
2804 xdr_LOCKT4args(XDR
*xdrs
, LOCKT4args
*objp
)
2806 if (xdrs
->x_op
!= XDR_FREE
) {
2807 if (!xdr_int(xdrs
, (int *)&objp
->locktype
))
2809 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->offset
))
2811 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->length
))
2813 if (!xdr_u_longlong_t(xdrs
,
2814 (u_longlong_t
*)&objp
->owner
.clientid
))
2816 return (xdr_bytes(xdrs
, (char **)&objp
->owner
.owner_val
,
2817 (uint_t
*)&objp
->owner
.owner_len
,
2818 NFS4_OPAQUE_LIMIT
));
2822 * Optimized free case
2824 if (objp
->owner
.owner_val
!= NULL
)
2825 kmem_free(objp
->owner
.owner_val
, objp
->owner
.owner_len
);
2830 xdr_LOCKT4res(XDR
*xdrs
, LOCKT4res
*objp
)
2832 if (xdrs
->x_op
!= XDR_FREE
) {
2833 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
2835 if (objp
->status
== NFS4_OK
)
2837 if (objp
->status
!= NFS4ERR_DENIED
)
2839 /* xdr_LOCK4denied */
2840 if (!xdr_u_longlong_t(xdrs
,
2841 (u_longlong_t
*)&objp
->denied
.offset
))
2843 if (!xdr_u_longlong_t(xdrs
,
2844 (u_longlong_t
*)&objp
->denied
.length
))
2846 if (!xdr_int(xdrs
, (int *)&objp
->denied
.locktype
))
2848 if (!xdr_u_longlong_t(xdrs
,
2849 (u_longlong_t
*)&objp
->denied
.owner
.clientid
))
2851 return (xdr_bytes(xdrs
,
2852 (char **)&objp
->denied
.owner
.owner_val
,
2853 (uint_t
*)&objp
->denied
.owner
.owner_len
,
2854 NFS4_OPAQUE_LIMIT
));
2858 * Optimized free case
2860 if (objp
->status
== NFS4_OK
|| objp
->status
!= NFS4ERR_DENIED
)
2862 if (objp
->denied
.owner
.owner_val
!= NULL
)
2863 kmem_free(objp
->denied
.owner
.owner_val
,
2864 objp
->denied
.owner
.owner_len
);
2869 xdr_LOCKU4args(XDR
*xdrs
, LOCKU4args
*objp
)
2871 if (!xdr_int(xdrs
, (int *)&objp
->locktype
))
2873 if (!xdr_u_int(xdrs
, &objp
->seqid
))
2875 if (!xdr_u_int(xdrs
, &objp
->lock_stateid
.seqid
))
2877 if (!xdr_opaque(xdrs
, objp
->lock_stateid
.other
, NFS4_OTHER_SIZE
))
2879 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->offset
))
2881 return (xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->length
));
2885 xdr_OPEN4args(XDR
*xdrs
, OPEN4args
*objp
)
2887 if (xdrs
->x_op
!= XDR_FREE
) {
2888 if (!xdr_u_int(xdrs
, &objp
->seqid
))
2890 if (!xdr_u_int(xdrs
, &objp
->share_access
))
2892 if (!xdr_u_int(xdrs
, &objp
->share_deny
))
2895 /* xdr_open_owner4 */
2896 if (!xdr_u_longlong_t(xdrs
,
2897 (u_longlong_t
*)&objp
->owner
.clientid
))
2899 if (!xdr_bytes(xdrs
, (char **)&objp
->owner
.owner_val
,
2900 (uint_t
*)&objp
->owner
.owner_len
,
2905 if (!xdr_int(xdrs
, (int *)&objp
->opentype
))
2907 if (objp
->opentype
== OPEN4_CREATE
) {
2909 /* xdr_createhow4 */
2910 if (!xdr_int(xdrs
, (int *)&objp
->mode
))
2912 switch (objp
->mode
) {
2915 if (!xdr_fattr4(xdrs
,
2916 &objp
->createhow4_u
.createattrs
))
2920 if (!xdr_u_longlong_t(xdrs
,
2921 (u_longlong_t
*)&objp
->createhow4_u
.
2930 /* xdr_open_claim4 */
2931 if (!xdr_int(xdrs
, (int *)&objp
->claim
))
2934 switch (objp
->claim
) {
2936 return (xdr_bytes(xdrs
, (char **)&objp
->open_claim4_u
.
2937 file
.utf8string_val
,
2938 (uint_t
*)&objp
->open_claim4_u
.file
.
2940 NFS4_MAX_UTF8STRING
));
2941 case CLAIM_PREVIOUS
:
2942 return (xdr_int(xdrs
,
2943 (int *)&objp
->open_claim4_u
.delegate_type
));
2944 case CLAIM_DELEGATE_CUR
:
2945 if (!xdr_u_int(xdrs
, (uint_t
*)&objp
->open_claim4_u
.
2946 delegate_cur_info
.delegate_stateid
.seqid
))
2948 if (!xdr_opaque(xdrs
, objp
->open_claim4_u
.
2949 delegate_cur_info
.delegate_stateid
.other
,
2952 return (xdr_bytes(xdrs
, (char **)&objp
->open_claim4_u
.
2953 delegate_cur_info
.file
.utf8string_val
,
2954 (uint_t
*)&objp
->open_claim4_u
.
2955 delegate_cur_info
.file
.utf8string_len
,
2956 NFS4_MAX_UTF8STRING
));
2957 case CLAIM_DELEGATE_PREV
:
2958 return (xdr_bytes(xdrs
, (char **)&objp
->open_claim4_u
.
2959 file_delegate_prev
.utf8string_val
,
2960 (uint_t
*)&objp
->open_claim4_u
.
2961 file_delegate_prev
.utf8string_len
,
2962 NFS4_MAX_UTF8STRING
));
2969 * Optimized free case
2971 if (objp
->owner
.owner_val
!= NULL
)
2972 kmem_free(objp
->owner
.owner_val
, objp
->owner
.owner_len
);
2974 if (objp
->opentype
== OPEN4_CREATE
) {
2975 switch (objp
->mode
) {
2978 (void) xdr_fattr4(xdrs
,
2979 &objp
->createhow4_u
.createattrs
);
2987 switch (objp
->claim
) {
2989 if (objp
->open_claim4_u
.file
.utf8string_val
!= NULL
)
2990 kmem_free(objp
->open_claim4_u
.file
.utf8string_val
,
2991 objp
->open_claim4_u
.file
.utf8string_len
);
2993 case CLAIM_PREVIOUS
:
2995 case CLAIM_DELEGATE_CUR
:
2996 if (objp
->open_claim4_u
.delegate_cur_info
.file
.utf8string_val
!=
2998 kmem_free(objp
->open_claim4_u
.delegate_cur_info
.file
.
3000 objp
->open_claim4_u
.delegate_cur_info
.file
.
3004 case CLAIM_DELEGATE_PREV
:
3005 if (objp
->open_claim4_u
.file_delegate_prev
.utf8string_val
!=
3007 kmem_free(objp
->open_claim4_u
.file_delegate_prev
.
3009 objp
->open_claim4_u
.file_delegate_prev
.
3019 xdr_OPEN4cargs(XDR
*xdrs
, OPEN4cargs
*objp
)
3025 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
3028 * We must always define the client's open_owner to be
3029 * 4 byte aligned and sized.
3031 ASSERT(objp
->owner
.owner_len
<= NFS4_OPAQUE_LIMIT
);
3032 ASSERT(!(objp
->owner
.owner_len
% BYTES_PER_XDR_UNIT
));
3034 len
= objp
->owner
.owner_len
;
3035 if ((ptr
= XDR_INLINE(xdrs
, 8 * BYTES_PER_XDR_UNIT
+ len
)) != NULL
) {
3039 IXDR_PUT_U_INT32(ptr
, OP_OPEN
);
3040 IXDR_PUT_U_INT32(ptr
, objp
->seqid
);
3041 IXDR_PUT_U_INT32(ptr
, objp
->share_access
);
3042 IXDR_PUT_U_INT32(ptr
, objp
->share_deny
);
3044 /* xdr_open_owner4 */
3045 IXDR_PUT_HYPER(ptr
, objp
->owner
.clientid
);
3046 IXDR_PUT_U_INT32(ptr
, objp
->owner
.owner_len
);
3047 /* We know this is very short so don't bcopy */
3048 ip
= (int32_t *)objp
->owner
.owner_val
;
3049 len
/= BYTES_PER_XDR_UNIT
;
3050 for (i
= 0; i
< len
; i
++)
3054 IXDR_PUT_U_INT32(ptr
, objp
->opentype
);
3057 if (!XDR_PUTINT32(xdrs
, (int32_t *)&op
))
3059 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->seqid
))
3061 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->share_access
))
3063 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->share_deny
))
3066 /* xdr_open_owner4 */
3067 if (!xdr_u_longlong_t(xdrs
,
3068 (u_longlong_t
*)&objp
->owner
.clientid
))
3070 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->owner
.owner_len
))
3072 if (!xdr_opaque(xdrs
, objp
->owner
.owner_val
,
3073 objp
->owner
.owner_len
))
3077 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->opentype
))
3081 if (objp
->opentype
== OPEN4_CREATE
) {
3082 /* xdr_createhow4 */
3083 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->mode
))
3085 switch (objp
->mode
) {
3088 if (!xdr_fattr4(xdrs
,
3089 &objp
->createhow4_u
.createattrs
))
3093 if (!xdr_u_longlong_t(xdrs
,
3094 (u_longlong_t
*)&objp
->createhow4_u
.
3103 /* xdr_open_claim4 */
3104 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->claim
))
3107 switch (objp
->claim
) {
3109 len
= strlen(objp
->open_claim4_u
.cfile
);
3110 if (len
> NFS4_MAX_UTF8STRING
)
3112 if (XDR_PUTINT32(xdrs
, &len
)) {
3113 return (xdr_opaque(xdrs
,
3114 objp
->open_claim4_u
.cfile
, len
));
3117 case CLAIM_PREVIOUS
:
3118 return (XDR_PUTINT32(xdrs
,
3119 (int32_t *)&objp
->open_claim4_u
.delegate_type
));
3120 case CLAIM_DELEGATE_CUR
:
3121 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->open_claim4_u
.
3122 delegate_cur_info
.delegate_stateid
.seqid
))
3124 if (!xdr_opaque(xdrs
, objp
->open_claim4_u
.
3125 delegate_cur_info
.delegate_stateid
.other
,
3128 len
= strlen(objp
->open_claim4_u
.delegate_cur_info
.cfile
);
3129 if (len
> NFS4_MAX_UTF8STRING
)
3131 if (XDR_PUTINT32(xdrs
, &len
)) {
3132 return (xdr_opaque(xdrs
,
3133 objp
->open_claim4_u
.delegate_cur_info
.cfile
,
3137 case CLAIM_DELEGATE_PREV
:
3138 len
= strlen(objp
->open_claim4_u
.cfile_delegate_prev
);
3139 if (len
> NFS4_MAX_UTF8STRING
)
3141 if (XDR_PUTINT32(xdrs
, &len
)) {
3142 return (xdr_opaque(xdrs
,
3143 objp
->open_claim4_u
.cfile_delegate_prev
, len
));
3152 xdr_OPEN4res(XDR
*xdrs
, OPEN4res
*objp
)
3154 if (xdrs
->x_op
!= XDR_FREE
) {
3155 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3157 if (objp
->status
!= NFS4_OK
)
3159 if (!xdr_u_int(xdrs
, &objp
->stateid
.seqid
))
3161 if (!xdr_opaque(xdrs
, objp
->stateid
.other
, NFS4_OTHER_SIZE
))
3163 if (!xdr_bool(xdrs
, &objp
->cinfo
.atomic
))
3165 if (!xdr_u_longlong_t(xdrs
,
3166 (u_longlong_t
*)&objp
->cinfo
.before
))
3168 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.after
))
3170 if (!xdr_u_int(xdrs
, &objp
->rflags
))
3172 if (!xdr_bitmap4(xdrs
, &objp
->attrset
))
3175 (int *)&objp
->delegation
.delegation_type
))
3177 switch (objp
->delegation
.delegation_type
) {
3178 case OPEN_DELEGATE_NONE
:
3180 case OPEN_DELEGATE_READ
:
3181 if (!xdr_u_int(xdrs
, &objp
->delegation
.
3182 open_delegation4_u
.read
.stateid
.seqid
))
3184 if (!xdr_opaque(xdrs
, objp
->delegation
.
3185 open_delegation4_u
.read
.stateid
.other
,
3188 if (!xdr_bool(xdrs
, &objp
->delegation
.
3189 open_delegation4_u
.read
.recall
))
3191 return (xdr_nfsace4(xdrs
, &objp
->delegation
.
3192 open_delegation4_u
.read
.permissions
));
3193 case OPEN_DELEGATE_WRITE
:
3194 if (!xdr_u_int(xdrs
, &objp
->delegation
.
3195 open_delegation4_u
.write
.stateid
.seqid
))
3197 if (!xdr_opaque(xdrs
, objp
->delegation
.
3198 open_delegation4_u
.write
.stateid
.other
,
3201 if (!xdr_bool(xdrs
, &objp
->delegation
.
3202 open_delegation4_u
.write
.recall
))
3204 if (!xdr_int(xdrs
, (int *)&objp
->delegation
.
3205 open_delegation4_u
.write
.space_limit
.
3208 switch (objp
->delegation
.
3209 open_delegation4_u
.write
.space_limit
.
3211 case NFS_LIMIT_SIZE
:
3212 if (!xdr_u_longlong_t(xdrs
,
3213 (u_longlong_t
*)&objp
->delegation
.
3214 open_delegation4_u
.write
.space_limit
.
3215 nfs_space_limit4_u
.filesize
))
3218 case NFS_LIMIT_BLOCKS
:
3219 if (!xdr_u_int(xdrs
,
3220 &objp
->delegation
.open_delegation4_u
.write
.
3221 space_limit
.nfs_space_limit4_u
.
3222 mod_blocks
.num_blocks
))
3224 if (!xdr_u_int(xdrs
, &objp
->delegation
.
3225 open_delegation4_u
.write
.space_limit
.
3226 nfs_space_limit4_u
.mod_blocks
.
3233 return (xdr_nfsace4(xdrs
, &objp
->delegation
.
3234 open_delegation4_u
.write
.permissions
));
3240 * Optimized free case
3242 if (objp
->status
!= NFS4_OK
)
3245 switch (objp
->delegation
.delegation_type
) {
3246 case OPEN_DELEGATE_NONE
:
3248 case OPEN_DELEGATE_READ
:
3249 return (xdr_nfsace4(xdrs
, &objp
->delegation
.
3250 open_delegation4_u
.read
.permissions
));
3251 case OPEN_DELEGATE_WRITE
:
3252 switch (objp
->delegation
.
3253 open_delegation4_u
.write
.space_limit
.limitby
) {
3254 case NFS_LIMIT_SIZE
:
3255 case NFS_LIMIT_BLOCKS
:
3260 return (xdr_nfsace4(xdrs
, &objp
->delegation
.
3261 open_delegation4_u
.write
.permissions
));
3267 xdr_OPEN_CONFIRM4res(XDR
*xdrs
, OPEN_CONFIRM4res
*objp
)
3269 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3271 if (objp
->status
!= NFS4_OK
)
3273 if (!xdr_u_int(xdrs
, &objp
->open_stateid
.seqid
))
3275 return (xdr_opaque(xdrs
, objp
->open_stateid
.other
, NFS4_OTHER_SIZE
));
3279 xdr_OPEN_DOWNGRADE4args(XDR
*xdrs
, OPEN_DOWNGRADE4args
*objp
)
3281 if (!xdr_u_int(xdrs
, &objp
->open_stateid
.seqid
))
3283 if (!xdr_opaque(xdrs
, objp
->open_stateid
.other
, NFS4_OTHER_SIZE
))
3285 if (!xdr_u_int(xdrs
, &objp
->seqid
))
3287 if (!xdr_u_int(xdrs
, &objp
->share_access
))
3289 return (xdr_u_int(xdrs
, &objp
->share_deny
));
3293 xdr_OPEN_DOWNGRADE4res(XDR
*xdrs
, OPEN_DOWNGRADE4res
*objp
)
3295 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3297 if (objp
->status
!= NFS4_OK
)
3299 if (!xdr_u_int(xdrs
, &objp
->open_stateid
.seqid
))
3301 return (xdr_opaque(xdrs
, objp
->open_stateid
.other
, NFS4_OTHER_SIZE
));
3305 xdr_READ4args(XDR
*xdrs
, READ4args
*objp
)
3307 rdma_chunkinfo_t rci
;
3308 rdma_wlist_conn_info_t rwci
;
3309 struct xdr_ops
*xops
= xdrrdma_xops();
3311 if (!xdr_u_int(xdrs
, &objp
->stateid
.seqid
))
3313 if (!xdr_opaque(xdrs
, objp
->stateid
.other
, NFS4_OTHER_SIZE
))
3315 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->offset
))
3317 if (!xdr_u_int(xdrs
, &objp
->count
))
3320 DTRACE_PROBE1(xdr__i__read4args_buf_len
,
3325 if (xdrs
->x_ops
== xops
&& xdrs
->x_op
== XDR_ENCODE
) {
3326 rci
.rci_type
= RCI_WRITE_ADDR_CHUNK
;
3327 rci
.rci_len
= objp
->count
;
3328 (void) XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
3331 if (xdrs
->x_ops
!= &xdrrdma_ops
|| xdrs
->x_op
== XDR_FREE
)
3334 if (xdrs
->x_op
== XDR_ENCODE
) {
3335 if (objp
->res_uiop
!= NULL
) {
3336 rci
.rci_type
= RCI_WRITE_UIO_CHUNK
;
3337 rci
.rci_a
.rci_uiop
= objp
->res_uiop
;
3338 rci
.rci_len
= objp
->count
;
3339 rci
.rci_clpp
= &objp
->wlist
;
3341 rci
.rci_type
= RCI_WRITE_ADDR_CHUNK
;
3342 rci
.rci_a
.rci_addr
= objp
->res_data_val_alt
;
3343 rci
.rci_len
= objp
->count
;
3344 rci
.rci_clpp
= &objp
->wlist
;
3347 return (XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
));
3350 /* XDR_DECODE case */
3351 (void) XDR_CONTROL(xdrs
, XDR_RDMA_GET_WCINFO
, &rwci
);
3352 objp
->wlist
= rwci
.rwci_wlist
;
3353 objp
->conn
= rwci
.rwci_conn
;
3359 xdr_READ4res(XDR
*xdrs
, READ4res
*objp
)
3363 if (xdrs
->x_op
== XDR_DECODE
)
3366 if (xdrs
->x_op
== XDR_FREE
) {
3368 * Optimized free case
3370 if (objp
->status
!= NFS4_OK
)
3372 if (objp
->data_val
!= NULL
)
3373 kmem_free(objp
->data_val
, objp
->data_len
);
3377 /* on with ENCODE paths */
3378 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->status
))
3380 if (objp
->status
!= NFS4_OK
)
3383 if (!XDR_PUTINT32(xdrs
, &objp
->eof
))
3388 if (xdrs
->x_ops
== &xdrmblk_ops
) {
3389 if (xdrmblk_putmblk(xdrs
, mp
, objp
->data_len
)) {
3395 } else if (mp
->b_cont
!= NULL
) {
3397 * See xdr_READ3res() for an explanation of why we need
3398 * to do a pullup here.
3400 if (pullupmsg(mp
, -1) == 0)
3402 objp
->data_val
= (caddr_t
)mp
->b_rptr
;
3405 if (xdr_u_int(xdrs
, &objp
->data_len
) == FALSE
) {
3409 * If read data sent by wlist (RDMA_WRITE), don't do
3410 * xdr_bytes() below. RDMA_WRITE transfers the data.
3411 * Note: this is encode-only because the client code
3412 * uses xdr_READ4res_clnt to decode results.
3415 if (objp
->data_len
!= 0) {
3416 return (xdrrdma_send_read_data(
3417 xdrs
, objp
->data_len
, objp
->wlist
));
3423 return (xdr_bytes(xdrs
, (char **)&objp
->data_val
,
3424 (uint_t
*)&objp
->data_len
,
3429 xdr_READ4res_clnt(XDR
*xdrs
, READ4res
*objp
, READ4args
*aobjp
)
3434 uint_t size
= aobjp
->res_maxsize
;
3437 if (xdrs
->x_op
== XDR_ENCODE
)
3440 if (xdrs
->x_op
== XDR_FREE
) {
3442 * Optimized free case
3444 if (objp
->status
!= NFS4_OK
)
3446 if (objp
->data_val
!= NULL
)
3447 kmem_free(objp
->data_val
, objp
->data_len
);
3451 if (!XDR_GETINT32(xdrs
, (int32_t *)&objp
->status
))
3453 if (objp
->status
!= NFS4_OK
)
3456 if (!XDR_GETINT32(xdrs
, &objp
->eof
))
3461 * This is a special case such that the caller is providing a
3462 * uio as a guide to eventual data location; this is used for
3463 * handling DIRECTIO reads.
3465 if (aobjp
->res_uiop
!= NULL
) {
3466 struct uio
*uiop
= aobjp
->res_uiop
;
3469 if (xdrs
->x_ops
== &xdrmblk_ops
) {
3470 if (!xdrmblk_getmblk(xdrs
, &mp
, &objp
->data_len
))
3473 if (objp
->data_len
== 0)
3476 if (objp
->data_len
> size
)
3479 size
= objp
->data_len
;
3481 n
= MIN(size
, mp
->b_wptr
- mp
->b_rptr
);
3482 if ((n
= MIN(uiop
->uio_resid
, n
)) != 0) {
3484 error
= uiomove((char *)mp
->b_rptr
, n
,
3492 while (mp
&& (mp
->b_rptr
>= mp
->b_wptr
))
3494 } while (mp
&& size
> 0 && uiop
->uio_resid
> 0);
3499 if (xdrs
->x_ops
== &xdrrdma_ops
) {
3502 XDR_CONTROL(xdrs
, XDR_RDMA_GET_WLIST
, &cl
);
3508 if (!xdr_u_int(xdrs
, &ocount
)) {
3513 objp
->wlist_len
= clist_len(cl
);
3514 objp
->data_len
= ocount
;
3516 if (objp
->wlist_len
!=
3518 objp
->data_len
, BYTES_PER_XDR_UNIT
)) {
3520 xdr__e__read4resuio_clnt_fail
,
3522 int, objp
->data_len
);
3527 uiop
->uio_resid
-= objp
->data_len
;
3528 uiop
->uio_iov
->iov_len
-= objp
->data_len
;
3529 uiop
->uio_iov
->iov_base
+= objp
->data_len
;
3530 uiop
->uio_loffset
+= objp
->data_len
;
3538 * This isn't an xdrmblk stream nor RDMA.
3539 * Handle the likely case that it can be
3540 * inlined (ex. xdrmem).
3542 if (!XDR_GETINT32(xdrs
, (int32_t *)&objp
->data_len
))
3545 if (objp
->data_len
== 0)
3548 if (objp
->data_len
> size
)
3551 size
= (int)objp
->data_len
;
3552 if ((ptr
= XDR_INLINE(xdrs
, size
)) != NULL
)
3553 return (uiomove(ptr
, size
, UIO_READ
, uiop
) ?
3557 * Handle some other (unlikely) stream type that will
3560 if ((ptr
= kmem_alloc(size
, KM_NOSLEEP
)) == NULL
)
3563 if (!XDR_GETBYTES(xdrs
, (caddr_t
)ptr
, size
)) {
3564 kmem_free(ptr
, size
);
3567 error
= uiomove(ptr
, size
, UIO_READ
, uiop
);
3568 kmem_free(ptr
, size
);
3570 return (error
? FALSE
: TRUE
);
3574 * Check for the other special case of the caller providing
3575 * the target area for the data.
3577 if (aobjp
->res_data_val_alt
== NULL
)
3581 * If read data received via RDMA_WRITE, don't do xdr_bytes().
3582 * RDMA_WRITE already moved the data so decode length of
3585 if (xdrs
->x_ops
== &xdrrdma_ops
) {
3588 XDR_CONTROL(xdrs
, XDR_RDMA_GET_WLIST
, &cl
);
3593 * Data transferred through inline if
3594 * objp->wlist == NULL
3598 if (!xdr_u_int(xdrs
, &ocount
)) {
3603 objp
->wlist_len
= clist_len(cl
);
3604 objp
->data_len
= ocount
;
3606 if (objp
->wlist_len
!=
3608 objp
->data_len
, BYTES_PER_XDR_UNIT
)) {
3610 xdr__e__read4res_clnt_fail
,
3612 int, objp
->data_len
);
3622 return (xdr_bytes(xdrs
, (char **)&aobjp
->res_data_val_alt
,
3623 (uint_t
*)&objp
->data_len
,
3624 aobjp
->res_maxsize
));
3628 xdr_READDIR4args(XDR
*xdrs
, READDIR4args
*objp
)
3630 rdma_chunkinfo_t rci
;
3631 struct xdr_ops
*xops
= xdrrdma_xops();
3633 if ((xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) &&
3634 xdrs
->x_op
== XDR_ENCODE
) {
3635 rci
.rci_type
= RCI_REPLY_CHUNK
;
3636 rci
.rci_len
= objp
->maxcount
;
3637 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
3640 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cookie
))
3642 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cookieverf
))
3644 if (!xdr_u_int(xdrs
, &objp
->dircount
))
3646 if (!xdr_u_int(xdrs
, &objp
->maxcount
))
3648 return (xdr_bitmap4(xdrs
, &objp
->attr_request
));
3652 xdr_READDIR4res(XDR
*xdrs
, READDIR4res
*objp
)
3654 mblk_t
*mp
= objp
->mblk
;
3658 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
3660 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3662 if (objp
->status
!= NFS4_OK
)
3667 if (xdrs
->x_ops
== &xdrmblk_ops
) {
3668 if (xdrmblk_putmblk_raw(xdrs
, mp
)
3670 /* mblk successfully inserted into outgoing chain */
3676 ASSERT(mp
->b_cont
== NULL
);
3679 * If transport is RDMA, the pre-encoded m_blk needs to be moved
3680 * without being chunked.
3681 * Check if chunking is enabled for the xdr stream.
3682 * If it is enabled, disable it temporarily for this op,
3685 XDR_CONTROL(xdrs
, XDR_RDMA_GET_FLAGS
, &flags
);
3687 if (!(flags
& XDR_RDMA_CHUNK
))
3688 return (xdr_opaque(xdrs
, (char *)mp
->b_rptr
, objp
->data_len
));
3690 flags
&= ~XDR_RDMA_CHUNK
;
3692 (void) XDR_CONTROL(xdrs
, XDR_RDMA_SET_FLAGS
, &flags
);
3694 ret_val
= xdr_opaque(xdrs
, (char *)mp
->b_rptr
, objp
->data_len
);
3696 flags
|= XDR_RDMA_CHUNK
;
3698 (void) XDR_CONTROL(xdrs
, XDR_RDMA_SET_FLAGS
, &flags
);
3704 xdr_READLINK4res(XDR
*xdrs
, READLINK4res
*objp
)
3706 if (xdrs
->x_op
!= XDR_FREE
) {
3707 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3709 if (objp
->status
!= NFS4_OK
)
3711 return (xdr_bytes(xdrs
, (char **)&objp
->link
.linktext4_val
,
3712 (uint_t
*)&objp
->link
.linktext4_len
,
3713 NFS4_MAX_UTF8STRING
));
3717 * Optimized free case
3719 if (objp
->status
!= NFS4_OK
)
3721 if (objp
->link
.linktext4_val
!= NULL
)
3722 kmem_free(objp
->link
.linktext4_val
, objp
->link
.linktext4_len
);
3727 xdr_REMOVE4res(XDR
*xdrs
, REMOVE4res
*objp
)
3729 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3731 if (objp
->status
!= NFS4_OK
)
3733 if (!xdr_bool(xdrs
, &objp
->cinfo
.atomic
))
3735 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->cinfo
.before
))
3737 return (xdr_u_longlong_t(xdrs
,
3738 (u_longlong_t
*)&objp
->cinfo
.after
));
3742 xdr_RENAME4res(XDR
*xdrs
, RENAME4res
*objp
)
3744 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3746 if (objp
->status
!= NFS4_OK
)
3748 if (!xdr_bool(xdrs
, &objp
->source_cinfo
.atomic
))
3750 if (!xdr_u_longlong_t(xdrs
,
3751 (u_longlong_t
*)&objp
->source_cinfo
.before
))
3753 if (!xdr_u_longlong_t(xdrs
,
3754 (u_longlong_t
*)&objp
->source_cinfo
.after
))
3756 if (!xdr_bool(xdrs
, &objp
->target_cinfo
.atomic
))
3758 if (!xdr_u_longlong_t(xdrs
,
3759 (u_longlong_t
*)&objp
->target_cinfo
.before
))
3761 return (xdr_u_longlong_t(xdrs
,
3762 (u_longlong_t
*)&objp
->target_cinfo
.after
));
3766 xdr_secinfo4(XDR
*xdrs
, secinfo4
*objp
)
3768 if (xdrs
->x_op
!= XDR_FREE
) {
3769 if (!xdr_u_int(xdrs
, &objp
->flavor
))
3771 if (objp
->flavor
!= RPCSEC_GSS
)
3773 if (!xdr_bytes(xdrs
,
3774 (char **)&objp
->flavor_info
.oid
.sec_oid4_val
,
3775 (uint_t
*)&objp
->flavor_info
.oid
.sec_oid4_len
,
3778 if (!xdr_u_int(xdrs
, &objp
->flavor_info
.qop
))
3780 return (xdr_int(xdrs
, (int *)&objp
->flavor_info
.service
));
3784 * Optimized free path
3786 if (objp
->flavor
!= RPCSEC_GSS
)
3789 if (objp
->flavor_info
.oid
.sec_oid4_val
!= NULL
)
3790 kmem_free(objp
->flavor_info
.oid
.sec_oid4_val
,
3791 objp
->flavor_info
.oid
.sec_oid4_len
);
3796 xdr_SETCLIENTID4args(XDR
*xdrs
, SETCLIENTID4args
*objp
)
3798 if (xdrs
->x_op
!= XDR_FREE
) {
3799 if (!xdr_u_longlong_t(xdrs
,
3800 (u_longlong_t
*)&objp
->client
.verifier
))
3802 if (!xdr_bytes(xdrs
, (char **)&objp
->client
.id_val
,
3803 (uint_t
*)&objp
->client
.id_len
, NFS4_OPAQUE_LIMIT
))
3805 if (!xdr_u_int(xdrs
, &objp
->callback
.cb_program
))
3807 if (!xdr_string(xdrs
, &objp
->callback
.cb_location
.r_netid
,
3810 if (!xdr_string(xdrs
, &objp
->callback
.cb_location
.r_addr
,
3813 return (xdr_u_int(xdrs
, &objp
->callback_ident
));
3817 * Optimized free case
3819 if (objp
->client
.id_val
!= NULL
)
3820 kmem_free(objp
->client
.id_val
, objp
->client
.id_len
);
3821 (void) xdr_string(xdrs
, &objp
->callback
.cb_location
.r_netid
,
3823 return (xdr_string(xdrs
, &objp
->callback
.cb_location
.r_addr
,
3824 NFS4_OPAQUE_LIMIT
));
3828 xdr_SETCLIENTID4res(XDR
*xdrs
, SETCLIENTID4res
*objp
)
3830 if (xdrs
->x_op
!= XDR_FREE
) {
3831 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3833 switch (objp
->status
) {
3835 if (!xdr_u_longlong_t(xdrs
,
3836 (u_longlong_t
*)&objp
->SETCLIENTID4res_u
.resok4
.
3839 return (xdr_u_longlong_t(xdrs
,
3840 (u_longlong_t
*)&objp
->SETCLIENTID4res_u
.
3841 resok4
.setclientid_confirm
));
3842 case NFS4ERR_CLID_INUSE
:
3843 if (!xdr_string(xdrs
,
3844 &objp
->SETCLIENTID4res_u
.client_using
.
3845 r_netid
, NFS4_OPAQUE_LIMIT
))
3847 return (xdr_string(xdrs
,
3848 &objp
->SETCLIENTID4res_u
.client_using
.
3849 r_addr
, NFS4_OPAQUE_LIMIT
));
3855 * Optimized free case
3857 if (objp
->status
!= NFS4ERR_CLID_INUSE
)
3860 if (!xdr_string(xdrs
, &objp
->SETCLIENTID4res_u
.client_using
.r_netid
,
3863 return (xdr_string(xdrs
, &objp
->SETCLIENTID4res_u
.client_using
.r_addr
,
3864 NFS4_OPAQUE_LIMIT
));
3868 xdr_WRITE4args(XDR
*xdrs
, WRITE4args
*objp
)
3870 if (xdrs
->x_op
!= XDR_FREE
) {
3871 if (!xdr_u_int(xdrs
, &objp
->stateid
.seqid
))
3873 if (!xdr_opaque(xdrs
, objp
->stateid
.other
, NFS4_OTHER_SIZE
))
3875 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->offset
))
3877 if (!xdr_int(xdrs
, (int *)&objp
->stable
))
3879 if (xdrs
->x_op
== XDR_DECODE
) {
3880 if (xdrs
->x_ops
== &xdrmblk_ops
) {
3881 objp
->data_val
= NULL
;
3882 return (xdrmblk_getmblk(xdrs
, &objp
->mblk
,
3886 if (xdrs
->x_ops
== &xdrrdmablk_ops
) {
3888 retval
= xdrrdma_getrdmablk(xdrs
,
3891 &objp
->conn
, NFS4_DATA_LIMIT
);
3892 if (retval
== FALSE
)
3894 return (xdrrdma_read_from_client(objp
->rlist
,
3895 &objp
->conn
, objp
->data_len
));
3898 /* Else fall thru for the xdr_bytes(). */
3899 return (xdr_bytes(xdrs
, (char **)&objp
->data_val
,
3900 (uint_t
*)&objp
->data_len
, NFS4_DATA_LIMIT
));
3902 if (objp
->rlist
!= NULL
) {
3903 (void) xdrrdma_free_clist(objp
->conn
, objp
->rlist
);
3905 objp
->data_val
= NULL
;
3911 * Optimized free case
3913 if (objp
->data_val
!= NULL
)
3914 kmem_free(objp
->data_val
, objp
->data_len
);
3919 xdr_WRITE4res(XDR
*xdrs
, WRITE4res
*objp
)
3921 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
3923 if (objp
->status
!= NFS4_OK
)
3925 if (!xdr_u_int(xdrs
, &objp
->count
))
3927 if (!xdr_int(xdrs
, (int *)&objp
->committed
))
3929 return (xdr_u_longlong_t(xdrs
,
3930 (u_longlong_t
*)&objp
->writeverf
));
3934 xdr_snfs_argop4_free(XDR
*xdrs
, nfs_argop4
**arrayp
, int len
)
3937 nfs_argop4
*array
= *arrayp
;
3940 * Optimized XDR_FREE only args array
3942 ASSERT(xdrs
->x_op
== XDR_FREE
);
3950 for (i
= 0; i
< len
; i
++) {
3952 * These should be ordered by frequency of use
3954 switch (array
[i
].argop
) {
3956 nfs_fh4
*objp
= &array
[i
].nfs_argop4_u
.opputfh
.object
;
3958 if (objp
->nfs_fh4_val
!= NULL
) {
3959 kmem_free(objp
->nfs_fh4_val
, objp
->nfs_fh4_len
);
3967 if (array
[i
].nfs_argop4_u
.oplookup
.objname
.
3968 utf8string_val
!= NULL
) {
3969 kmem_free(array
[i
].nfs_argop4_u
.oplookup
.
3970 objname
.utf8string_val
,
3971 array
[i
].nfs_argop4_u
.oplookup
.
3972 objname
.utf8string_len
);
3976 (void) xdr_OPEN4args(xdrs
,
3977 &array
[i
].nfs_argop4_u
.opopen
);
3984 (void) xdr_WRITE4args(xdrs
,
3985 &array
[i
].nfs_argop4_u
.opwrite
);
3987 case OP_DELEGRETURN
:
3992 if (array
[i
].nfs_argop4_u
.opremove
.target
.
3993 utf8string_val
!= NULL
) {
3994 kmem_free(array
[i
].nfs_argop4_u
.opremove
.target
.
3996 array
[i
].nfs_argop4_u
.opremove
.target
.
4003 (void) xdr_CREATE4args(xdrs
,
4004 &array
[i
].nfs_argop4_u
.opcreate
);
4009 if (array
[i
].nfs_argop4_u
.oplink
.newname
.
4010 utf8string_val
!= NULL
) {
4011 kmem_free(array
[i
].nfs_argop4_u
.oplink
.newname
.
4013 array
[i
].nfs_argop4_u
.oplink
.newname
.
4018 (void) xdr_LOCK4args(xdrs
,
4019 &array
[i
].nfs_argop4_u
.oplock
);
4022 (void) xdr_LOCKT4args(xdrs
,
4023 &array
[i
].nfs_argop4_u
.oplockt
);
4028 (void) xdr_fattr4(xdrs
,
4029 &array
[i
].nfs_argop4_u
.opnverify
.obj_attributes
);
4032 case OP_OPEN_CONFIRM
:
4033 case OP_OPEN_DOWNGRADE
:
4039 if (array
[i
].nfs_argop4_u
.oprename
.oldname
.
4040 utf8string_val
!= NULL
) {
4041 kmem_free(array
[i
].nfs_argop4_u
.oprename
.
4042 oldname
.utf8string_val
,
4043 array
[i
].nfs_argop4_u
.oprename
.
4044 oldname
.utf8string_len
);
4046 if (array
[i
].nfs_argop4_u
.oprename
.newname
.
4047 utf8string_val
!= NULL
) {
4048 kmem_free(array
[i
].nfs_argop4_u
.oprename
.
4049 newname
.utf8string_val
,
4050 array
[i
].nfs_argop4_u
.oprename
.
4051 newname
.utf8string_len
);
4059 if (array
[i
].nfs_argop4_u
.opsecinfo
.name
.
4060 utf8string_val
!= NULL
) {
4061 kmem_free(array
[i
].nfs_argop4_u
.opsecinfo
.name
.
4063 array
[i
].nfs_argop4_u
.opsecinfo
.name
.
4068 (void) xdr_fattr4(xdrs
,
4069 &array
[i
].nfs_argop4_u
.opsetattr
.obj_attributes
);
4071 case OP_SETCLIENTID
:
4072 (void) xdr_SETCLIENTID4args(xdrs
,
4073 &array
[i
].nfs_argop4_u
.opsetclientid
);
4075 case OP_SETCLIENTID_CONFIRM
:
4078 (void) xdr_fattr4(xdrs
,
4079 &array
[i
].nfs_argop4_u
.opverify
.obj_attributes
);
4081 case OP_RELEASE_LOCKOWNER
:
4082 if (array
[i
].nfs_argop4_u
.oprelease_lockowner
.
4083 lock_owner
.owner_val
!= NULL
) {
4084 kmem_free(array
[i
].nfs_argop4_u
.
4085 oprelease_lockowner
.lock_owner
.owner_val
,
4086 array
[i
].nfs_argop4_u
.
4087 oprelease_lockowner
.lock_owner
.owner_len
);
4094 * An invalid op is a coding error, it should never
4095 * have been decoded.
4096 * Don't error because the caller cannot finish
4097 * freeing the residual memory of the array.
4103 kmem_free(*arrayp
, len
* sizeof (nfs_argop4
));
4109 xdr_nfs_argop4(XDR
*xdrs
, nfs_argop4
*objp
)
4111 rdma_chunkinfo_t rci
;
4112 struct xdr_ops
*xops
= xdrrdma_xops();
4115 * These should be ordered by frequency of use
4117 switch (objp
->argop
) {
4119 return (xdr_bytes(xdrs
,
4120 (char **)&objp
->nfs_argop4_u
.opputfh
.object
.nfs_fh4_val
,
4121 (uint_t
*)&objp
->nfs_argop4_u
.opputfh
.object
.nfs_fh4_len
,
4125 * ACLs can become relatively large ( > 8K) and the default
4126 * 8K reply chunk of RDMA may not suffice. Check for
4127 * get ACL bit and if it's RDMA, add a chunk equal the size
4128 * of the transfer size to the reply chunk list.
4130 if ((xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) &&
4131 (xdrs
->x_op
== XDR_ENCODE
) &&
4132 (objp
->nfs_argop4_u
.opgetattr
.attr_request
&
4134 rci
.rci_type
= RCI_REPLY_CHUNK
;
4135 rci
.rci_len
= objp
->nfs_argop4_u
.opgetattr
.mi
->mi_tsize
;
4136 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
4138 DTRACE_PROBE1(xdr__i__argop4__getattr
, int,
4141 return (xdr_bitmap4(xdrs
,
4142 &objp
->nfs_argop4_u
.opgetattr
.attr_request
));
4146 return (xdr_bytes(xdrs
, (char **)&objp
->nfs_argop4_u
.oplookup
.
4147 objname
.utf8string_val
,
4148 (uint_t
*)&objp
->nfs_argop4_u
.oplookup
.
4149 objname
.utf8string_len
,
4150 NFS4_MAX_UTF8STRING
));
4152 return (xdr_OPEN4args(xdrs
, &objp
->nfs_argop4_u
.opopen
));
4154 return (xdr_CLOSE4args(xdrs
, &objp
->nfs_argop4_u
.opclose
));
4156 return (xdr_u_int(xdrs
,
4157 &objp
->nfs_argop4_u
.opaccess
.access
));
4159 return (xdr_READ4args(xdrs
, &objp
->nfs_argop4_u
.opread
));
4161 return (xdr_WRITE4args(xdrs
, &objp
->nfs_argop4_u
.opwrite
));
4162 case OP_DELEGRETURN
:
4163 if (!xdr_u_int(xdrs
,
4164 &objp
->nfs_argop4_u
.opdelegreturn
.deleg_stateid
.seqid
))
4166 return (xdr_opaque(xdrs
,
4167 objp
->nfs_argop4_u
.opdelegreturn
.deleg_stateid
.other
,
4172 return (xdr_READDIR4args(xdrs
, &objp
->nfs_argop4_u
.opreaddir
));
4174 return (xdr_bytes(xdrs
, (char **)&objp
->nfs_argop4_u
.opremove
.
4175 target
.utf8string_val
,
4176 (uint_t
*)&objp
->nfs_argop4_u
.opremove
.
4177 target
.utf8string_len
,
4178 NFS4_MAX_UTF8STRING
));
4180 if (!xdr_u_longlong_t(xdrs
,
4181 (u_longlong_t
*)&objp
->nfs_argop4_u
.opcommit
.offset
))
4183 return (xdr_u_int(xdrs
, &objp
->nfs_argop4_u
.opcommit
.count
));
4185 return (xdr_CREATE4args(xdrs
, &objp
->nfs_argop4_u
.opcreate
));
4187 return (xdr_u_longlong_t(xdrs
,
4188 (u_longlong_t
*)&objp
->nfs_argop4_u
.opdelegpurge
.clientid
));
4190 return (xdr_bytes(xdrs
,
4191 (char **)&objp
->nfs_argop4_u
.oplink
.newname
.utf8string_val
,
4192 (uint_t
*)&objp
->nfs_argop4_u
.oplink
.newname
.utf8string_len
,
4193 NFS4_MAX_UTF8STRING
));
4195 return (xdr_LOCK4args(xdrs
, &objp
->nfs_argop4_u
.oplock
));
4197 return (xdr_LOCKT4args(xdrs
, &objp
->nfs_argop4_u
.oplockt
));
4199 return (xdr_LOCKU4args(xdrs
, &objp
->nfs_argop4_u
.oplocku
));
4201 return (xdr_fattr4(xdrs
,
4202 &objp
->nfs_argop4_u
.opnverify
.obj_attributes
));
4204 return (xdr_bool(xdrs
,
4205 &objp
->nfs_argop4_u
.opopenattr
.createdir
));
4206 case OP_OPEN_CONFIRM
:
4207 if (!xdr_u_int(xdrs
, &objp
->nfs_argop4_u
.opopen_confirm
.
4208 open_stateid
.seqid
))
4210 if (!xdr_opaque(xdrs
, objp
->nfs_argop4_u
.opopen_confirm
.
4211 open_stateid
.other
, NFS4_OTHER_SIZE
))
4213 return (xdr_u_int(xdrs
, &objp
->nfs_argop4_u
.opopen_confirm
.
4215 case OP_OPEN_DOWNGRADE
:
4216 return (xdr_OPEN_DOWNGRADE4args(xdrs
,
4217 &objp
->nfs_argop4_u
.opopen_downgrade
));
4223 if ((xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) &&
4224 xdrs
->x_op
== XDR_ENCODE
) {
4225 rci
.rci_type
= RCI_REPLY_CHUNK
;
4226 rci
.rci_len
= MAXPATHLEN
;
4227 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
4231 if (!xdr_bytes(xdrs
, (char **)&objp
->nfs_argop4_u
.oprename
.
4232 oldname
.utf8string_val
,
4233 (uint_t
*)&objp
->nfs_argop4_u
.oprename
.
4234 oldname
.utf8string_len
,
4235 NFS4_MAX_UTF8STRING
))
4237 return (xdr_bytes(xdrs
, (char **)&objp
->nfs_argop4_u
.oprename
.
4238 newname
.utf8string_val
,
4239 (uint_t
*)&objp
->nfs_argop4_u
.oprename
.
4240 newname
.utf8string_len
,
4241 NFS4_MAX_UTF8STRING
));
4243 return (xdr_u_longlong_t(xdrs
,
4244 (u_longlong_t
*)&objp
->nfs_argop4_u
.oprenew
.clientid
));
4250 return (xdr_bytes(xdrs
,
4251 (char **)&objp
->nfs_argop4_u
.opsecinfo
.name
.utf8string_val
,
4252 (uint_t
*)&objp
->nfs_argop4_u
.opsecinfo
.name
.utf8string_len
,
4253 NFS4_MAX_UTF8STRING
));
4255 if (!xdr_u_int(xdrs
, &objp
->nfs_argop4_u
.opsetattr
.
4258 if (!xdr_opaque(xdrs
, objp
->nfs_argop4_u
.opsetattr
.
4259 stateid
.other
, NFS4_OTHER_SIZE
))
4261 return (xdr_fattr4(xdrs
, &objp
->nfs_argop4_u
.opsetattr
.
4263 case OP_SETCLIENTID
:
4264 return (xdr_SETCLIENTID4args(xdrs
,
4265 &objp
->nfs_argop4_u
.opsetclientid
));
4266 case OP_SETCLIENTID_CONFIRM
:
4267 if (!xdr_u_longlong_t(xdrs
, (u_longlong_t
*)&objp
->nfs_argop4_u
.
4268 opsetclientid_confirm
.clientid
))
4270 return (xdr_u_longlong_t(xdrs
,
4271 (u_longlong_t
*)&objp
->nfs_argop4_u
.
4272 opsetclientid_confirm
.setclientid_confirm
));
4274 return (xdr_fattr4(xdrs
,
4275 &objp
->nfs_argop4_u
.opverify
.obj_attributes
));
4276 case OP_RELEASE_LOCKOWNER
:
4277 if (!xdr_u_longlong_t(xdrs
,
4278 (u_longlong_t
*)&objp
->nfs_argop4_u
.
4279 oprelease_lockowner
.lock_owner
.clientid
))
4281 return (xdr_bytes(xdrs
,
4282 (char **)&objp
->nfs_argop4_u
.oprelease_lockowner
.
4283 lock_owner
.owner_val
,
4284 (uint_t
*)&objp
->nfs_argop4_u
.oprelease_lockowner
.
4285 lock_owner
.owner_len
, NFS4_OPAQUE_LIMIT
));
4293 xdr_cnfs_argop4_wrap(XDR
*xdrs
, nfs_argop4
*objp
)
4295 if (!xdr_int(xdrs
, (int *)&objp
->argop
))
4298 return (xdr_nfs_argop4(xdrs
, objp
));
4302 xdr_snfs_argop4(XDR
*xdrs
, nfs_argop4
*objp
)
4304 if (!xdr_int(xdrs
, (int *)&objp
->argop
))
4307 switch (objp
->argop
) {
4309 return (xdr_decode_nfs_fh4(xdrs
,
4310 &objp
->nfs_argop4_u
.opputfh
.object
));
4312 return (xdr_nfs_argop4(xdrs
, objp
));
4317 * Client side encode only arg op processing
4320 xdr_cnfs_argop4(XDR
*xdrs
, nfs_argop4
*objp
)
4324 nfs4_sharedfh_t
*sfh
;
4328 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
4331 * Special case the private pseudo ops
4333 if (!(objp
->argop
& SUNW_PRIVATE_OP
))
4334 return (xdr_cnfs_argop4_wrap(xdrs
, objp
));
4337 * These should be ordered by frequency of use
4339 switch (objp
->argop
) {
4342 * We are passed in the file handle as a nfs4_sharedfh_t *
4343 * We need to acquire the correct locks so we can copy it out.
4345 sfh
= (nfs4_sharedfh_t
*)objp
->nfs_argop4_u
.opcputfh
.sfh
;
4347 (void) nfs_rw_enter_sig(&mi
->mi_fh_lock
, RW_READER
, 0);
4349 len
= sfh
->sfh_fh
.nfs_fh4_len
;
4350 ASSERT(len
<= NFS4_FHSIZE
);
4353 * First try and inline the copy
4354 * Must first be a multiple of BYTES_PER_XDR_UNIT
4356 if (!(len
% BYTES_PER_XDR_UNIT
) &&
4357 (ptr
= XDR_INLINE(xdrs
, 2 * BYTES_PER_XDR_UNIT
+ len
)) !=
4359 IXDR_PUT_U_INT32(ptr
, OP_PUTFH
);
4360 IXDR_PUT_U_INT32(ptr
, len
);
4361 bcopy(sfh
->sfh_fh
.nfs_fh4_val
, ptr
, len
);
4362 nfs_rw_exit(&mi
->mi_fh_lock
);
4367 if (!XDR_PUTINT32(xdrs
, &op
)) {
4368 nfs_rw_exit(&mi
->mi_fh_lock
);
4371 if (!XDR_PUTINT32(xdrs
, &len
)) {
4372 nfs_rw_exit(&mi
->mi_fh_lock
);
4375 if (!(len
% BYTES_PER_XDR_UNIT
)) {
4376 if (XDR_PUTBYTES(xdrs
, sfh
->sfh_fh
.nfs_fh4_val
, len
)) {
4377 nfs_rw_exit(&mi
->mi_fh_lock
);
4380 } else if (xdr_opaque(xdrs
, sfh
->sfh_fh
.nfs_fh4_val
, len
)) {
4381 nfs_rw_exit(&mi
->mi_fh_lock
);
4384 nfs_rw_exit(&mi
->mi_fh_lock
);
4387 len
= strlen(objp
->nfs_argop4_u
.opclookup
.cname
);
4388 if (len
> NFS4_MAX_UTF8STRING
)
4391 if (XDR_PUTINT32(xdrs
, &op
)) {
4392 if (XDR_PUTINT32(xdrs
, &len
)) {
4393 return (xdr_opaque(xdrs
,
4394 objp
->nfs_argop4_u
.opclookup
.cname
,
4400 /* op processing inlined in xdr_OPEN4cargs */
4401 return (xdr_OPEN4cargs(xdrs
, &objp
->nfs_argop4_u
.opcopen
));
4403 len
= strlen(objp
->nfs_argop4_u
.opcremove
.ctarget
);
4404 if (len
> NFS4_MAX_UTF8STRING
)
4407 if (XDR_PUTINT32(xdrs
, &op
)) {
4408 if (XDR_PUTINT32(xdrs
, &len
)) {
4409 return (xdr_opaque(xdrs
,
4410 objp
->nfs_argop4_u
.opcremove
.ctarget
,
4417 if (!XDR_PUTINT32(xdrs
, &op
))
4419 return (xdr_CREATE4cargs(xdrs
, &objp
->nfs_argop4_u
.opccreate
));
4421 len
= strlen(objp
->nfs_argop4_u
.opclink
.cnewname
);
4422 if (len
> NFS4_MAX_UTF8STRING
)
4425 if (XDR_PUTINT32(xdrs
, &op
)) {
4426 if (XDR_PUTINT32(xdrs
, &len
)) {
4427 return (xdr_opaque(xdrs
,
4428 objp
->nfs_argop4_u
.opclink
.cnewname
,
4434 len
= strlen(objp
->nfs_argop4_u
.opcrename
.coldname
);
4435 if (len
> NFS4_MAX_UTF8STRING
)
4438 if (!XDR_PUTINT32(xdrs
, &op
))
4440 if (!XDR_PUTINT32(xdrs
, &len
))
4442 if (!xdr_opaque(xdrs
,
4443 objp
->nfs_argop4_u
.opcrename
.coldname
, len
))
4445 len
= strlen(objp
->nfs_argop4_u
.opcrename
.cnewname
);
4446 if (len
> NFS4_MAX_UTF8STRING
)
4448 if (XDR_PUTINT32(xdrs
, &len
)) {
4449 return (xdr_opaque(xdrs
,
4450 objp
->nfs_argop4_u
.opcrename
.cnewname
, len
));
4454 len
= strlen(objp
->nfs_argop4_u
.opcsecinfo
.cname
);
4455 if (len
> NFS4_MAX_UTF8STRING
)
4458 if (XDR_PUTINT32(xdrs
, &op
)) {
4459 if (XDR_PUTINT32(xdrs
, &len
)) {
4460 return (xdr_opaque(xdrs
,
4461 objp
->nfs_argop4_u
.opcsecinfo
.cname
,
4471 * Note that the len and decode_len will only be different in the case
4472 * of the client's use of this free function. If the server is
4473 * freeing results, then the len/decode_len will always match.
4476 xdr_nfs_resop4_free(XDR
*xdrs
, nfs_resop4
**arrayp
, int len
, int decode_len
)
4479 nfs_resop4
*array
= *arrayp
;
4483 * Optimized XDR_FREE only results array
4485 ASSERT(xdrs
->x_op
== XDR_FREE
);
4490 for (i
= 0; i
< decode_len
; i
++) {
4492 * These should be ordered by frequency of use
4494 switch (array
[i
].resop
) {
4498 if (array
[i
].nfs_resop4_u
.opgetattr
.status
!= NFS4_OK
)
4501 gr
= &array
[i
].nfs_resop4_u
.opgetattr
.ga_res
;
4502 if (gr
->n4g_ext_res
) {
4503 if (gr
->n4g_resbmap
& FATTR4_FS_LOCATIONS_MASK
)
4504 (void) xdr_fattr4_fs_locations(xdrs
,
4505 &gr
->n4g_ext_res
->n4g_fslocations
);
4506 kmem_free(gr
->n4g_ext_res
,
4507 sizeof (struct nfs4_ga_ext_res
));
4511 if (array
[i
].nfs_resop4_u
.opgetfh
.status
!= NFS4_OK
)
4513 if (array
[i
].nfs_resop4_u
.opgetfh
.object
.nfs_fh4_val
!=
4515 kmem_free(array
[i
].nfs_resop4_u
.opgetfh
.object
.
4517 array
[i
].nfs_resop4_u
.opgetfh
.object
.
4524 (void) xdr_OPEN4res(xdrs
, &array
[i
].nfs_resop4_u
.
4531 (void) xdr_READ4res(xdrs
,
4532 &array
[i
].nfs_resop4_u
.opread
);
4535 case OP_DELEGRETURN
:
4545 (void) xdr_LOCK4res(xdrs
, &array
[i
].nfs_resop4_u
.
4549 (void) xdr_LOCKT4res(xdrs
, &array
[i
].nfs_resop4_u
.
4555 case OP_OPEN_CONFIRM
:
4556 case OP_OPEN_DOWNGRADE
:
4565 (void) xdr_READLINK4res(xdrs
, &array
[i
].nfs_resop4_u
.
4569 (void) xdr_array(xdrs
,
4570 (char **)&array
[i
].nfs_resop4_u
.opsecinfo
.
4572 (uint_t
*)&array
[i
].nfs_resop4_u
.opsecinfo
.
4574 NFS4_SECINFO_LIMIT
, sizeof (secinfo4
),
4575 (xdrproc_t
)xdr_secinfo4
);
4577 case OP_SETCLIENTID
:
4578 (void) xdr_SETCLIENTID4res(xdrs
,
4579 &array
[i
].nfs_resop4_u
.opsetclientid
);
4582 case OP_SETCLIENTID_CONFIRM
:
4584 case OP_RELEASE_LOCKOWNER
:
4589 * An invalid op is a coding error, it should never
4590 * have been decoded.
4591 * Don't error because the caller cannot finish
4592 * freeing the residual memory of the array.
4598 kmem_free(*arrayp
, len
* sizeof (nfs_resop4
));
4604 xdr_snfs_resop4_free(XDR
*xdrs
, nfs_resop4
**arrayp
, int len
, int decode_len
)
4606 return (xdr_nfs_resop4_free(xdrs
, arrayp
, len
, decode_len
));
4610 xdr_nfs_resop4(XDR
*xdrs
, nfs_resop4
*objp
)
4613 * These should be ordered by frequency of use
4615 switch (objp
->resop
) {
4617 return (xdr_int(xdrs
,
4618 (int32_t *)&objp
->nfs_resop4_u
.opputfh
.status
));
4621 (int32_t *)&objp
->nfs_resop4_u
.opgetattr
.status
))
4623 if (objp
->nfs_resop4_u
.opgetattr
.status
!= NFS4_OK
)
4625 return (xdr_fattr4(xdrs
,
4626 &objp
->nfs_resop4_u
.opgetattr
.obj_attributes
));
4629 (int32_t *)&objp
->nfs_resop4_u
.opgetfh
.status
))
4631 if (objp
->nfs_resop4_u
.opgetfh
.status
!= NFS4_OK
)
4633 return (xdr_bytes(xdrs
,
4634 (char **)&objp
->nfs_resop4_u
.opgetfh
.object
.nfs_fh4_val
,
4635 (uint_t
*)&objp
->nfs_resop4_u
.opgetfh
.object
.nfs_fh4_len
,
4638 return (xdr_int(xdrs
,
4639 (int32_t *)&objp
->nfs_resop4_u
.oplookup
.status
));
4641 return (xdr_OPEN4res(xdrs
, &objp
->nfs_resop4_u
.opopen
));
4643 return (xdr_CLOSE4res(xdrs
, &objp
->nfs_resop4_u
.opclose
));
4645 return (xdr_ACCESS4res(xdrs
, &objp
->nfs_resop4_u
.opaccess
));
4647 return (xdr_READ4res(xdrs
, &objp
->nfs_resop4_u
.opread
));
4649 return (xdr_WRITE4res(xdrs
, &objp
->nfs_resop4_u
.opwrite
));
4650 case OP_DELEGRETURN
:
4651 return (xdr_int(xdrs
,
4652 (int32_t *)&objp
->nfs_resop4_u
.opdelegreturn
.status
));
4654 return (xdr_int(xdrs
,
4655 (int32_t *)&objp
->nfs_resop4_u
.oplookupp
.status
));
4657 return (xdr_READDIR4res(xdrs
, &objp
->nfs_resop4_u
.opreaddir
));
4659 return (xdr_REMOVE4res(xdrs
, &objp
->nfs_resop4_u
.opremove
));
4663 (int32_t *)&objp
->nfs_resop4_u
.opcommit
.status
))
4665 if (objp
->nfs_resop4_u
.opcommit
.status
!= NFS4_OK
)
4667 return (xdr_u_longlong_t(xdrs
,
4668 (u_longlong_t
*)&objp
->nfs_resop4_u
.opcommit
.
4671 return (xdr_CREATE4res(xdrs
, &objp
->nfs_resop4_u
.opcreate
));
4673 return (xdr_int(xdrs
,
4674 (int32_t *)&objp
->nfs_resop4_u
.opdelegpurge
.status
));
4676 return (xdr_LINK4res(xdrs
, &objp
->nfs_resop4_u
.oplink
));
4678 return (xdr_LOCK4res(xdrs
, &objp
->nfs_resop4_u
.oplock
));
4680 return (xdr_LOCKT4res(xdrs
, &objp
->nfs_resop4_u
.oplockt
));
4683 (int32_t *)&objp
->nfs_resop4_u
.oplocku
.status
))
4685 if (objp
->nfs_resop4_u
.oplocku
.status
!= NFS4_OK
)
4687 if (!xdr_u_int(xdrs
,
4688 &objp
->nfs_resop4_u
.oplocku
.lock_stateid
.seqid
))
4690 return (xdr_opaque(xdrs
,
4691 objp
->nfs_resop4_u
.oplocku
.lock_stateid
.other
,
4694 return (xdr_int(xdrs
,
4695 (int32_t *)&objp
->nfs_resop4_u
.opnverify
.status
));
4697 return (xdr_int(xdrs
,
4698 (int32_t *)&objp
->nfs_resop4_u
.opopenattr
.status
));
4699 case OP_OPEN_CONFIRM
:
4700 return (xdr_OPEN_CONFIRM4res(xdrs
,
4701 &objp
->nfs_resop4_u
.opopen_confirm
));
4702 case OP_OPEN_DOWNGRADE
:
4703 return (xdr_OPEN_DOWNGRADE4res(xdrs
,
4704 &objp
->nfs_resop4_u
.opopen_downgrade
));
4706 return (xdr_int(xdrs
,
4707 (int32_t *)&objp
->nfs_resop4_u
.opputpubfh
.status
));
4709 return (xdr_int(xdrs
,
4710 (int32_t *)&objp
->nfs_resop4_u
.opputrootfh
.status
));
4712 return (xdr_READLINK4res(xdrs
, &objp
->nfs_resop4_u
.opreadlink
));
4714 return (xdr_RENAME4res(xdrs
, &objp
->nfs_resop4_u
.oprename
));
4716 return (xdr_int(xdrs
,
4717 (int32_t *)&objp
->nfs_resop4_u
.oprenew
.status
));
4719 return (xdr_int(xdrs
,
4720 (int32_t *)&objp
->nfs_resop4_u
.oprestorefh
.status
));
4722 return (xdr_int(xdrs
,
4723 (int32_t *)&objp
->nfs_resop4_u
.opsavefh
.status
));
4725 if (!xdr_int(xdrs
, (int32_t *)&objp
->nfs_resop4_u
.opsecinfo
.
4728 if (objp
->nfs_resop4_u
.opsecinfo
.status
!= NFS4_OK
)
4730 return (xdr_array(xdrs
, (char **)&objp
->nfs_resop4_u
.opsecinfo
.
4732 (uint_t
*)&objp
->nfs_resop4_u
.opsecinfo
.
4734 NFS4_SECINFO_LIMIT
, sizeof (secinfo4
),
4735 (xdrproc_t
)xdr_secinfo4
));
4737 if (!xdr_int(xdrs
, (int32_t *)&objp
->nfs_resop4_u
.opsetattr
.
4740 return (xdr_bitmap4(xdrs
,
4741 &objp
->nfs_resop4_u
.opsetattr
.attrsset
));
4742 case OP_SETCLIENTID
:
4743 return (xdr_SETCLIENTID4res(xdrs
,
4744 &objp
->nfs_resop4_u
.opsetclientid
));
4745 case OP_SETCLIENTID_CONFIRM
:
4746 return (xdr_int(xdrs
,
4747 (int32_t *)&objp
->nfs_resop4_u
.opsetclientid_confirm
.
4750 return (xdr_int(xdrs
,
4751 (int32_t *)&objp
->nfs_resop4_u
.opverify
.status
));
4752 case OP_RELEASE_LOCKOWNER
:
4753 return (xdr_int(xdrs
,
4754 (int32_t *)&objp
->nfs_resop4_u
.oprelease_lockowner
.status
));
4756 return (xdr_int(xdrs
,
4757 (int32_t *)&objp
->nfs_resop4_u
.opillegal
.status
));
4763 xdr_snfs_resop4(XDR
*xdrs
, nfs_resop4
*objp
)
4765 if (!xdr_int(xdrs
, (int *)&objp
->resop
))
4768 switch (objp
->resop
) {
4770 if (!XDR_PUTINT32(xdrs
,
4771 (int32_t *)&objp
->nfs_resop4_u
.opgetfh
.status
))
4773 if (objp
->nfs_resop4_u
.opgetfh
.status
!= NFS4_OK
)
4775 return (xdr_encode_nfs_fh4(xdrs
,
4776 &objp
->nfs_resop4_u
.opgetfh
.object
));
4778 return (xdr_nfs_resop4(xdrs
, objp
));
4783 xdr_nfs_resop4_clnt(XDR
*xdrs
, nfs_resop4
*objp
, nfs_argop4
*aobjp
)
4785 if (!xdr_int(xdrs
, (int *)&objp
->resop
))
4788 * These should be ordered by frequency of use
4790 switch (objp
->resop
) {
4792 return (xdr_int(xdrs
,
4793 (int32_t *)&objp
->nfs_resop4_u
.opputfh
.status
));
4796 (int32_t *)&objp
->nfs_resop4_u
.opgetattr
.status
))
4798 if (objp
->nfs_resop4_u
.opgetattr
.status
!= NFS4_OK
)
4800 return (xdr_ga_res(xdrs
,
4801 (GETATTR4res
*)&objp
->nfs_resop4_u
.opgetattr
,
4802 &aobjp
->nfs_argop4_u
.opgetattr
));
4805 (int32_t *)&objp
->nfs_resop4_u
.opgetfh
.status
))
4807 if (objp
->nfs_resop4_u
.opgetfh
.status
!= NFS4_OK
)
4809 return (xdr_bytes(xdrs
,
4810 (char **)&objp
->nfs_resop4_u
.opgetfh
.object
.nfs_fh4_val
,
4811 (uint_t
*)&objp
->nfs_resop4_u
.opgetfh
.object
.nfs_fh4_len
,
4814 return (xdr_int(xdrs
,
4815 (int32_t *)&objp
->nfs_resop4_u
.oplookup
.status
));
4817 return (xdr_int(xdrs
,
4818 (int32_t *)&objp
->nfs_resop4_u
.opnverify
.status
));
4820 return (xdr_OPEN4res(xdrs
, &objp
->nfs_resop4_u
.opopen
));
4822 return (xdr_CLOSE4res(xdrs
, &objp
->nfs_resop4_u
.opclose
));
4824 return (xdr_ACCESS4res(xdrs
, &objp
->nfs_resop4_u
.opaccess
));
4826 return (xdr_READ4res_clnt(xdrs
, &objp
->nfs_resop4_u
.opread
,
4827 &aobjp
->nfs_argop4_u
.opread
));
4829 return (xdr_WRITE4res(xdrs
, &objp
->nfs_resop4_u
.opwrite
));
4830 case OP_DELEGRETURN
:
4831 return (xdr_int(xdrs
,
4832 (int32_t *)&objp
->nfs_resop4_u
.opdelegreturn
.status
));
4834 return (xdr_int(xdrs
,
4835 (int32_t *)&objp
->nfs_resop4_u
.oplookupp
.status
));
4837 return (xdr_READDIR4res_clnt(xdrs
,
4838 &objp
->nfs_resop4_u
.opreaddirclnt
,
4839 &aobjp
->nfs_argop4_u
.opreaddir
));
4841 return (xdr_REMOVE4res(xdrs
, &objp
->nfs_resop4_u
.opremove
));
4845 (int32_t *)&objp
->nfs_resop4_u
.opcommit
.status
))
4847 if (objp
->nfs_resop4_u
.opcommit
.status
!= NFS4_OK
)
4849 return (xdr_u_longlong_t(xdrs
,
4850 (u_longlong_t
*)&objp
->nfs_resop4_u
.opcommit
.
4853 return (xdr_CREATE4res(xdrs
, &objp
->nfs_resop4_u
.opcreate
));
4855 return (xdr_int(xdrs
,
4856 (int32_t *)&objp
->nfs_resop4_u
.opdelegpurge
.status
));
4858 return (xdr_LINK4res(xdrs
, &objp
->nfs_resop4_u
.oplink
));
4860 return (xdr_LOCK4res(xdrs
, &objp
->nfs_resop4_u
.oplock
));
4862 return (xdr_LOCKT4res(xdrs
, &objp
->nfs_resop4_u
.oplockt
));
4865 (int32_t *)&objp
->nfs_resop4_u
.oplocku
.status
))
4867 if (objp
->nfs_resop4_u
.oplocku
.status
!= NFS4_OK
)
4869 if (!xdr_u_int(xdrs
,
4870 &objp
->nfs_resop4_u
.oplocku
.lock_stateid
.seqid
))
4872 return (xdr_opaque(xdrs
,
4873 objp
->nfs_resop4_u
.oplocku
.lock_stateid
.other
,
4876 return (xdr_int(xdrs
,
4877 (int32_t *)&objp
->nfs_resop4_u
.opopenattr
.status
));
4878 case OP_OPEN_CONFIRM
:
4879 return (xdr_OPEN_CONFIRM4res(xdrs
,
4880 &objp
->nfs_resop4_u
.opopen_confirm
));
4881 case OP_OPEN_DOWNGRADE
:
4882 return (xdr_OPEN_DOWNGRADE4res(xdrs
,
4883 &objp
->nfs_resop4_u
.opopen_downgrade
));
4885 return (xdr_int(xdrs
,
4886 (int32_t *)&objp
->nfs_resop4_u
.opputpubfh
.status
));
4888 return (xdr_int(xdrs
,
4889 (int32_t *)&objp
->nfs_resop4_u
.opputrootfh
.status
));
4891 return (xdr_READLINK4res(xdrs
, &objp
->nfs_resop4_u
.opreadlink
));
4893 return (xdr_RENAME4res(xdrs
, &objp
->nfs_resop4_u
.oprename
));
4895 return (xdr_int(xdrs
,
4896 (int32_t *)&objp
->nfs_resop4_u
.oprenew
.status
));
4898 return (xdr_int(xdrs
,
4899 (int32_t *)&objp
->nfs_resop4_u
.oprestorefh
.status
));
4901 return (xdr_int(xdrs
,
4902 (int32_t *)&objp
->nfs_resop4_u
.opsavefh
.status
));
4904 if (!xdr_int(xdrs
, (int32_t *)&objp
->nfs_resop4_u
.opsecinfo
.
4907 if (objp
->nfs_resop4_u
.opsecinfo
.status
!= NFS4_OK
)
4909 return (xdr_array(xdrs
, (char **)&objp
->nfs_resop4_u
.opsecinfo
.
4911 (uint_t
*)&objp
->nfs_resop4_u
.opsecinfo
.
4913 ~0, sizeof (secinfo4
), (xdrproc_t
)xdr_secinfo4
));
4915 if (!xdr_int(xdrs
, (int32_t *)&objp
->nfs_resop4_u
.opsetattr
.
4918 return (xdr_bitmap4(xdrs
,
4919 &objp
->nfs_resop4_u
.opsetattr
.attrsset
));
4920 case OP_SETCLIENTID
:
4921 return (xdr_SETCLIENTID4res(xdrs
,
4922 &objp
->nfs_resop4_u
.opsetclientid
));
4923 case OP_SETCLIENTID_CONFIRM
:
4924 return (xdr_int(xdrs
,
4925 (int32_t *)&objp
->nfs_resop4_u
.opsetclientid_confirm
.
4928 return (xdr_int(xdrs
,
4929 (int32_t *)&objp
->nfs_resop4_u
.opverify
.status
));
4930 case OP_RELEASE_LOCKOWNER
:
4931 return (xdr_int(xdrs
,
4932 (int32_t *)&objp
->nfs_resop4_u
.oprelease_lockowner
.status
));
4934 return (xdr_int(xdrs
,
4935 (int32_t *)&objp
->nfs_resop4_u
.opillegal
.status
));
4941 xdr_COMPOUND4args_clnt(XDR
*xdrs
, COMPOUND4args_clnt
*objp
)
4943 static int32_t twelve
= 12;
4944 static int32_t minorversion
= NFS4_MINORVERSION
;
4947 rdma_chunkinfo_t rci
;
4948 struct xdr_ops
*xops
= xdrrdma_xops();
4953 if (xdrs
->x_op
== XDR_FREE
)
4955 if (xdrs
->x_op
== XDR_DECODE
)
4958 ctagp
= (uint32_t *)&nfs4_ctags
[objp
->ctag
].ct_tag
;
4960 if ((ptr
= XDR_INLINE(xdrs
, 5 * BYTES_PER_XDR_UNIT
)) != NULL
) {
4962 * Efficiently encode fixed length tags, could be longlongs
4963 * but 8 byte XDR alignment not assured
4965 IXDR_PUT_U_INT32(ptr
, 12);
4966 IXDR_PUT_U_INT32(ptr
, ctagp
[0]);
4967 IXDR_PUT_U_INT32(ptr
, ctagp
[1]);
4968 IXDR_PUT_U_INT32(ptr
, ctagp
[2]);
4971 * Fixed minor version for now
4973 IXDR_PUT_U_INT32(ptr
, NFS4_MINORVERSION
);
4975 if (!XDR_PUTINT32(xdrs
, &twelve
))
4977 if (!XDR_PUTINT32(xdrs
, (int32_t *)&ctagp
[0]))
4979 if (!XDR_PUTINT32(xdrs
, (int32_t *)&ctagp
[1]))
4981 if (!XDR_PUTINT32(xdrs
, (int32_t *)&ctagp
[2]))
4983 if (!XDR_PUTINT32(xdrs
, (int32_t *)&minorversion
))
4986 if (xdrs
->x_ops
== &xdrrdma_ops
|| xdrs
->x_ops
== xops
) {
4987 rci
.rci_type
= RCI_REPLY_CHUNK
;
4988 rci
.rci_len
= MAXPATHLEN
* 2;
4989 XDR_CONTROL(xdrs
, XDR_RDMA_ADD_CHUNK
, &rci
);
4992 return (xdr_array(xdrs
, (char **)&objp
->array
,
4993 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
4994 sizeof (nfs_argop4
), (xdrproc_t
)xdr_cnfs_argop4
));
4998 xdr_COMPOUND4args_srv(XDR
*xdrs
, COMPOUND4args
*objp
)
5000 if (!xdr_bytes(xdrs
, (char **)&objp
->tag
.utf8string_val
,
5001 (uint_t
*)&objp
->tag
.utf8string_len
,
5002 NFS4_MAX_UTF8STRING
))
5004 if (!xdr_u_int(xdrs
, &objp
->minorversion
))
5006 if (xdrs
->x_op
!= XDR_FREE
)
5007 return (xdr_array(xdrs
, (char **)&objp
->array
,
5008 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
5009 sizeof (nfs_argop4
), (xdrproc_t
)xdr_snfs_argop4
));
5011 return (xdr_snfs_argop4_free(xdrs
, &objp
->array
, objp
->array_len
));
5015 xdr_COMPOUND4res_clnt(XDR
*xdrs
, COMPOUND4res_clnt
*objp
)
5025 if (xdrs
->x_op
== XDR_ENCODE
)
5028 if (xdrs
->x_op
!= XDR_FREE
) {
5029 if ((ptr
= XDR_INLINE(xdrs
, 2 * BYTES_PER_XDR_UNIT
)) != NULL
) {
5030 objp
->status
= IXDR_GET_U_INT32(ptr
);
5031 len
= IXDR_GET_U_INT32(ptr
);
5033 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
5035 if (!xdr_u_int(xdrs
, (uint32_t *)&len
))
5038 if (len
> NFS4_MAX_UTF8STRING
)
5043 if (!XDR_CONTROL(xdrs
, XDR_SKIPBYTES
, &len
))
5046 if (!xdr_int(xdrs
, (int32_t *)&objp
->array_len
))
5049 if (objp
->array_len
> objp
->argsp
->array_len
)
5052 if (objp
->status
== NFS4_OK
&&
5053 objp
->array_len
!= objp
->argsp
->array_len
)
5056 /* Alloc the results array */
5057 argop
= objp
->argsp
->array
;
5058 len
= objp
->array_len
* sizeof (nfs_resop4
);
5059 objp
->decode_len
= 0;
5060 objp
->array
= resop
= kmem_zalloc(len
, KM_SLEEP
);
5062 for (len
= 0; len
< objp
->array_len
;
5063 len
++, resop
++, argop
++, objp
->decode_len
++) {
5064 if (!xdr_nfs_resop4_clnt(xdrs
, resop
, argop
)) {
5066 * Make sure to free anything that may
5067 * have been allocated along the way.
5069 xdrs
->x_op
= XDR_FREE
;
5070 (void) xdr_nfs_resop4_free(xdrs
, &objp
->array
,
5078 return (xdr_nfs_resop4_free(xdrs
, &objp
->array
,
5079 objp
->array_len
, objp
->decode_len
));
5083 xdr_COMPOUND4res_srv(XDR
*xdrs
, COMPOUND4res
*objp
)
5085 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
5087 if (!xdr_bytes(xdrs
, (char **)&objp
->tag
.utf8string_val
,
5088 (uint_t
*)&objp
->tag
.utf8string_len
,
5089 NFS4_MAX_UTF8STRING
))
5092 if (xdrs
->x_op
!= XDR_FREE
)
5093 return (xdr_array(xdrs
, (char **)&objp
->array
,
5094 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
5095 sizeof (nfs_resop4
), (xdrproc_t
)xdr_snfs_resop4
));
5097 return (xdr_snfs_resop4_free(xdrs
, &objp
->array
,
5098 objp
->array_len
, objp
->array_len
));
5102 * NFS server side callback, initiating the callback request so it
5103 * is the RPC client. Must convert from server's internal filehandle
5104 * format to wire format.
5107 xdr_snfs_cb_argop4(XDR
*xdrs
, nfs_cb_argop4
*objp
)
5109 CB_GETATTR4args
*gargs
;
5110 CB_RECALL4args
*rargs
;
5112 ASSERT(xdrs
->x_op
== XDR_ENCODE
);
5114 if (!XDR_PUTINT32(xdrs
, (int32_t *)&objp
->argop
))
5117 switch (objp
->argop
) {
5119 gargs
= &objp
->nfs_cb_argop4_u
.opcbgetattr
;
5121 if (!xdr_encode_nfs_fh4(xdrs
, &gargs
->fh
))
5123 return (xdr_bitmap4(xdrs
, &gargs
->attr_request
));
5125 rargs
= &objp
->nfs_cb_argop4_u
.opcbrecall
;
5127 if (!XDR_PUTINT32(xdrs
, (int32_t *)&rargs
->stateid
.seqid
))
5129 if (!xdr_opaque(xdrs
, rargs
->stateid
.other
, NFS4_OTHER_SIZE
))
5131 if (!XDR_PUTINT32(xdrs
, (int32_t *)&rargs
->truncate
))
5133 return (xdr_encode_nfs_fh4(xdrs
, &rargs
->fh
));
5141 * NFS client side callback, receiving the callback request so it
5142 * is the RPC server. Must treat the file handles as opaque.
5145 xdr_cnfs_cb_argop4(XDR
*xdrs
, nfs_cb_argop4
*objp
)
5147 CB_GETATTR4args
*gargs
;
5148 CB_RECALL4args
*rargs
;
5150 ASSERT(xdrs
->x_op
!= XDR_ENCODE
);
5152 if (!xdr_u_int(xdrs
, &objp
->argop
))
5154 switch (objp
->argop
) {
5156 gargs
= &objp
->nfs_cb_argop4_u
.opcbgetattr
;
5158 if (!xdr_bytes(xdrs
, (char **)&gargs
->fh
.nfs_fh4_val
,
5159 (uint_t
*)&gargs
->fh
.nfs_fh4_len
, NFS4_FHSIZE
))
5161 return (xdr_bitmap4(xdrs
, &gargs
->attr_request
));
5163 rargs
= &objp
->nfs_cb_argop4_u
.opcbrecall
;
5165 if (!xdr_u_int(xdrs
, &rargs
->stateid
.seqid
))
5167 if (!xdr_opaque(xdrs
, rargs
->stateid
.other
, NFS4_OTHER_SIZE
))
5169 if (!xdr_bool(xdrs
, &rargs
->truncate
))
5171 return (xdr_bytes(xdrs
, (char **)&rargs
->fh
.nfs_fh4_val
,
5172 (uint_t
*)&rargs
->fh
.nfs_fh4_len
, NFS4_FHSIZE
));
5180 xdr_nfs_cb_resop4(XDR
*xdrs
, nfs_cb_resop4
*objp
)
5182 if (!xdr_u_int(xdrs
, &objp
->resop
))
5184 switch (objp
->resop
) {
5187 (int32_t *)&objp
->nfs_cb_resop4_u
.opcbgetattr
.
5190 if (objp
->nfs_cb_resop4_u
.opcbgetattr
.status
!= NFS4_OK
)
5192 return (xdr_fattr4(xdrs
,
5193 &objp
->nfs_cb_resop4_u
.opcbgetattr
.
5196 return (xdr_int(xdrs
,
5197 (int32_t *)&objp
->nfs_cb_resop4_u
.opcbrecall
.status
));
5199 return (xdr_int(xdrs
,
5200 (int32_t *)&objp
->nfs_cb_resop4_u
.opcbillegal
.status
));
5206 * The NFS client side callback, RPC server
5209 xdr_CB_COMPOUND4args_clnt(XDR
*xdrs
, CB_COMPOUND4args
*objp
)
5211 if (!xdr_bytes(xdrs
, (char **)&objp
->tag
.utf8string_val
,
5212 (uint_t
*)&objp
->tag
.utf8string_len
,
5213 NFS4_MAX_UTF8STRING
))
5215 if (!xdr_u_int(xdrs
, &objp
->minorversion
))
5217 if (!xdr_u_int(xdrs
, &objp
->callback_ident
))
5219 return (xdr_array(xdrs
, (char **)&objp
->array
,
5220 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
5221 sizeof (nfs_cb_argop4
), (xdrproc_t
)xdr_cnfs_cb_argop4
));
5225 * The NFS server side callback, RPC client
5228 xdr_CB_COMPOUND4args_srv(XDR
*xdrs
, CB_COMPOUND4args
*objp
)
5230 if (!xdr_bytes(xdrs
, (char **)&objp
->tag
.utf8string_val
,
5231 (uint_t
*)&objp
->tag
.utf8string_len
,
5232 NFS4_MAX_UTF8STRING
))
5234 if (!xdr_u_int(xdrs
, &objp
->minorversion
))
5236 if (!xdr_u_int(xdrs
, &objp
->callback_ident
))
5238 return (xdr_array(xdrs
, (char **)&objp
->array
,
5239 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
5240 sizeof (nfs_cb_argop4
), (xdrproc_t
)xdr_snfs_cb_argop4
));
5244 xdr_CB_COMPOUND4res(XDR
*xdrs
, CB_COMPOUND4res
*objp
)
5246 if (!xdr_int(xdrs
, (int32_t *)&objp
->status
))
5248 if (!xdr_bytes(xdrs
, (char **)&objp
->tag
.utf8string_val
,
5249 (uint_t
*)&objp
->tag
.utf8string_len
,
5250 NFS4_MAX_UTF8STRING
))
5252 return (xdr_array(xdrs
, (char **)&objp
->array
,
5253 (uint_t
*)&objp
->array_len
, NFS4_COMPOUND_LIMIT
,
5254 sizeof (nfs_cb_resop4
), (xdrproc_t
)xdr_nfs_cb_resop4
));