Print this page
OS-20 share_nfs(1m) charset handling is unreliable
OS-22 Page fault at nfscmd_dropped_entrysize+0x1e()
OS-23 NFSv2/3/4: READDIR responses are inconsistent when charset conversion fails
OS-24 rfs3_readdir(): Issues related to nfscmd_convdirent()
Reviewed by: Jan Kryl <jan.kryl@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/nfs/nfs3_xdr.c
+++ new/usr/src/uts/common/fs/nfs/nfs3_xdr.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 27 /* All Rights Reserved */
28 28
29 29 /*
30 30 * Copyright (c) 2013 by Delphix. All rights reserved.
31 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
31 32 */
32 33
33 34 #include <sys/param.h>
34 35 #include <sys/types.h>
35 36 #include <sys/systm.h>
36 37 #include <sys/user.h>
37 38 #include <sys/vnode.h>
38 39 #include <sys/file.h>
39 40 #include <sys/dirent.h>
40 41 #include <sys/vfs.h>
41 42 #include <sys/stream.h>
42 43 #include <sys/strsubr.h>
43 44 #include <sys/debug.h>
44 45 #include <sys/t_lock.h>
45 46 #include <sys/cmn_err.h>
46 47 #include <sys/dnlc.h>
47 48 #include <sys/cred.h>
48 49 #include <sys/time.h>
49 50 #include <sys/sdt.h>
50 51
51 52 #include <rpc/types.h>
52 53 #include <rpc/xdr.h>
53 54
54 55 #include <nfs/nfs.h>
55 56 #include <nfs/rnode.h>
56 57 #include <rpc/rpc_rdma.h>
57 58
58 59 /*
59 60 * These are the XDR routines used to serialize and deserialize
60 61 * the various structures passed as parameters across the network
61 62 * between NFS clients and servers.
62 63 */
63 64
64 65 /*
65 66 * XDR null terminated ASCII strings
66 67 * xdr_string3 deals with "C strings" - arrays of bytes that are
67 68 * terminated by a NULL character. The parameter cpp references a
68 69 * pointer to storage; If the pointer is null, then the necessary
69 70 * storage is allocated. The last parameter is the max allowed length
70 71 * of the string as allowed by the system. The NFS Version 3 protocol
71 72 * does not place limits on strings, but the implementation needs to
72 73 * place a reasonable limit to avoid problems.
73 74 */
74 75 bool_t
75 76 xdr_string3(XDR *xdrs, char **cpp, uint_t maxsize)
76 77 {
77 78 char *sp;
78 79 uint_t size;
79 80 uint_t nodesize;
80 81 bool_t mem_alloced = FALSE;
81 82
82 83 /*
83 84 * first deal with the length since xdr strings are counted-strings
84 85 */
85 86 sp = *cpp;
86 87 switch (xdrs->x_op) {
87 88 case XDR_FREE:
88 89 if (sp == NULL || sp == nfs3nametoolong)
89 90 return (TRUE); /* already free */
90 91 /* FALLTHROUGH */
91 92
92 93 case XDR_ENCODE:
93 94 size = (uint_t)strlen(sp);
94 95 break;
95 96
96 97 case XDR_DECODE:
97 98 break;
98 99 }
99 100
100 101 if (!xdr_u_int(xdrs, &size))
101 102 return (FALSE);
102 103
103 104 /*
104 105 * now deal with the actual bytes
105 106 */
106 107 switch (xdrs->x_op) {
107 108 case XDR_DECODE:
108 109 if (size >= maxsize) {
109 110 *cpp = nfs3nametoolong;
110 111 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &size))
111 112 return (FALSE);
112 113 return (TRUE);
113 114 }
114 115 nodesize = size + 1;
115 116 if (nodesize == 0)
116 117 return (TRUE);
117 118 if (sp == NULL) {
118 119 sp = kmem_alloc(nodesize, KM_NOSLEEP);
119 120 *cpp = sp;
120 121 if (sp == NULL)
121 122 return (FALSE);
122 123 mem_alloced = TRUE;
123 124 }
124 125 sp[size] = 0;
125 126
126 127 if (xdr_opaque(xdrs, sp, size)) {
127 128 if (strlen(sp) != size) {
128 129 if (mem_alloced)
129 130 kmem_free(sp, nodesize);
130 131 *cpp = NULL;
131 132 return (FALSE);
132 133 }
133 134 } else {
134 135 if (mem_alloced)
135 136 kmem_free(sp, nodesize);
136 137 *cpp = NULL;
137 138 return (FALSE);
138 139 }
139 140 return (TRUE);
140 141
141 142 case XDR_ENCODE:
142 143 return (xdr_opaque(xdrs, sp, size));
143 144
144 145 case XDR_FREE:
145 146 nodesize = size + 1;
146 147 kmem_free(sp, nodesize);
147 148 *cpp = NULL;
148 149 return (TRUE);
149 150 }
150 151
151 152 return (FALSE);
152 153 }
153 154
154 155 /*
155 156 * XDR_INLINE decode a filehandle.
156 157 */
157 158 bool_t
158 159 xdr_inline_decode_nfs_fh3(uint32_t *ptr, nfs_fh3 *fhp, uint32_t fhsize)
159 160 {
160 161 uchar_t *bp = (uchar_t *)ptr;
161 162 uchar_t *cp;
162 163 uint32_t dsize;
163 164 uintptr_t resid;
164 165
165 166 /*
166 167 * Check to see if what the client sent us is bigger or smaller
167 168 * than what we can ever possibly send out. NFS_FHMAXDATA is
168 169 * unfortunately badly named as it is no longer the max and is
169 170 * really the min of what is sent over the wire.
170 171 */
171 172 if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
172 173 sizeof (ushort_t) + NFS_FHMAXDATA +
173 174 sizeof (ushort_t) + NFS_FHMAXDATA)) {
174 175 return (FALSE);
175 176 }
176 177
177 178 /*
178 179 * All internal parts of a filehandle are in native byte order.
179 180 *
180 181 * Decode what should be fh3_fsid, it is aligned.
181 182 */
182 183 fhp->fh3_fsid.val[0] = *(uint32_t *)bp;
183 184 bp += BYTES_PER_XDR_UNIT;
184 185 fhp->fh3_fsid.val[1] = *(uint32_t *)bp;
185 186 bp += BYTES_PER_XDR_UNIT;
186 187
187 188 /*
188 189 * Decode what should be fh3_len. fh3_len is two bytes, so we're
189 190 * unaligned now.
190 191 */
191 192 cp = (uchar_t *)&fhp->fh3_len;
192 193 *cp++ = *bp++;
193 194 *cp++ = *bp++;
194 195 fhsize -= 2 * BYTES_PER_XDR_UNIT + sizeof (ushort_t);
195 196
196 197 /*
197 198 * For backwards compatability, the fid length may be less than
198 199 * NFS_FHMAXDATA, but it was always encoded as NFS_FHMAXDATA bytes.
199 200 */
200 201 dsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
201 202
202 203 /*
203 204 * Make sure the client isn't sending us a bogus length for fh3x_data.
204 205 */
205 206 if (fhsize < dsize)
206 207 return (FALSE);
207 208 bcopy(bp, fhp->fh3_data, dsize);
208 209 bp += dsize;
209 210 fhsize -= dsize;
210 211
211 212 if (fhsize < sizeof (ushort_t))
212 213 return (FALSE);
213 214 cp = (uchar_t *)&fhp->fh3_xlen;
214 215 *cp++ = *bp++;
215 216 *cp++ = *bp++;
216 217 fhsize -= sizeof (ushort_t);
217 218
218 219 dsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
219 220
220 221 /*
221 222 * Make sure the client isn't sending us a bogus length for fh3x_xdata.
222 223 */
223 224 if (fhsize < dsize)
224 225 return (FALSE);
225 226 bcopy(bp, fhp->fh3_xdata, dsize);
226 227 fhsize -= dsize;
227 228 bp += dsize;
228 229
229 230 /*
230 231 * We realign things on purpose, so skip any padding
231 232 */
232 233 resid = (uintptr_t)bp % BYTES_PER_XDR_UNIT;
233 234 if (resid != 0) {
234 235 if (fhsize < (BYTES_PER_XDR_UNIT - resid))
235 236 return (FALSE);
236 237 bp += BYTES_PER_XDR_UNIT - resid;
237 238 fhsize -= BYTES_PER_XDR_UNIT - resid;
238 239 }
239 240
240 241 /*
241 242 * Make sure client didn't send extra bytes
242 243 */
243 244 if (fhsize != 0)
244 245 return (FALSE);
245 246 return (TRUE);
246 247 }
247 248
248 249 static bool_t
249 250 xdr_decode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
250 251 {
251 252 uint32_t fhsize; /* filehandle size */
252 253 uint32_t bufsize;
253 254 rpc_inline_t *ptr;
254 255 uchar_t *bp;
255 256
256 257 ASSERT(xdrs->x_op == XDR_DECODE);
257 258
258 259 /*
259 260 * Retrieve the filehandle length.
260 261 */
261 262 if (!XDR_GETINT32(xdrs, (int32_t *)&fhsize))
262 263 return (FALSE);
263 264
264 265 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
265 266 objp->fh3_length = 0;
266 267
267 268 /*
268 269 * Check to see if what the client sent us is bigger or smaller
269 270 * than what we can ever possibly send out. NFS_FHMAXDATA is
270 271 * unfortunately badly named as it is no longer the max and is
271 272 * really the min of what is sent over the wire.
272 273 */
273 274 if (fhsize > sizeof (fhandle3_t) || fhsize < (sizeof (fsid_t) +
274 275 sizeof (ushort_t) + NFS_FHMAXDATA +
275 276 sizeof (ushort_t) + NFS_FHMAXDATA)) {
276 277 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fhsize))
277 278 return (FALSE);
278 279 return (TRUE);
279 280 }
280 281
281 282 /*
282 283 * bring in fhsize plus any padding
283 284 */
284 285 bufsize = RNDUP(fhsize);
285 286 ptr = XDR_INLINE(xdrs, bufsize);
286 287 bp = (uchar_t *)ptr;
287 288 if (ptr == NULL) {
288 289 bp = kmem_alloc(bufsize, KM_SLEEP);
289 290 if (!xdr_opaque(xdrs, (char *)bp, bufsize)) {
290 291 kmem_free(bp, bufsize);
291 292 return (FALSE);
292 293 }
293 294 }
294 295
295 296 objp->fh3_length = sizeof (fhandle3_t);
296 297
297 298 if (xdr_inline_decode_nfs_fh3((uint32_t *)bp, objp, fhsize) == FALSE) {
298 299 /*
299 300 * If in the process of decoding we find the file handle
300 301 * is not correctly formed, we need to continue decoding
301 302 * and trigger an NFS layer error. Set the nfs_fh3_len to
302 303 * zero so it gets caught as a bad length.
303 304 */
304 305 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
305 306 objp->fh3_length = 0;
306 307 }
307 308
308 309 if (ptr == NULL)
309 310 kmem_free(bp, bufsize);
310 311 return (TRUE);
311 312 }
312 313
313 314 /*
314 315 * XDR_INLINE encode a filehandle.
315 316 */
316 317 bool_t
317 318 xdr_inline_encode_nfs_fh3(uint32_t **ptrp, uint32_t *ptr_redzone,
318 319 nfs_fh3 *fhp)
319 320 {
320 321 uint32_t *ptr = *ptrp;
321 322 uchar_t *cp;
322 323 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
323 324 uint32_t padword;
324 325
325 326 fsize = fhp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_len;
326 327 xsize = fhp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : fhp->fh3_xlen;
327 328
328 329 /*
329 330 * First get the initial and variable sized part of the filehandle.
330 331 */
331 332 otw_len = sizeof (fhp->fh3_fsid) +
332 333 sizeof (fhp->fh3_len) + fsize +
333 334 sizeof (fhp->fh3_xlen) + xsize;
334 335
335 336 /*
336 337 * Round out to a full word.
337 338 */
338 339 otw_len = RNDUP(otw_len);
339 340 padword = (otw_len / BYTES_PER_XDR_UNIT); /* includes fhlen */
340 341
341 342 /*
342 343 * Make sure we don't exceed our buffer.
343 344 */
344 345 if ((ptr + (otw_len / BYTES_PER_XDR_UNIT) + 1) > ptr_redzone)
345 346 return (FALSE);
346 347
347 348 /*
348 349 * Zero out the pading.
349 350 */
350 351 ptr[padword] = 0;
351 352
352 353 IXDR_PUT_U_INT32(ptr, otw_len);
353 354
354 355 /*
355 356 * The rest of the filehandle is in native byteorder
356 357 */
357 358 /* fh3_fsid */
358 359 *ptr++ = (uint32_t)fhp->fh3_fsid.val[0];
359 360 *ptr++ = (uint32_t)fhp->fh3_fsid.val[1];
360 361
361 362 /*
362 363 * Since the next pieces are unaligned, we need to
363 364 * do bytewise copies.
364 365 */
365 366 cp = (uchar_t *)ptr;
366 367
367 368 /* fh3_len + fh3_data */
368 369 bcopy(&fhp->fh3_len, cp, sizeof (fhp->fh3_len) + fsize);
369 370 cp += sizeof (fhp->fh3_len) + fsize;
370 371
371 372 /* fh3_xlen + fh3_xdata */
372 373 bcopy(&fhp->fh3_xlen, cp, sizeof (fhp->fh3_xlen) + xsize);
373 374 cp += sizeof (fhp->fh3_xlen) + xsize;
374 375
375 376 /* do necessary rounding/padding */
376 377 cp = (uchar_t *)RNDUP((uintptr_t)cp);
377 378 ptr = (uint32_t *)cp;
378 379
379 380 /*
380 381 * With the above padding, we're word aligned again.
381 382 */
382 383 ASSERT(((uintptr_t)ptr % BYTES_PER_XDR_UNIT) == 0);
383 384
384 385 *ptrp = ptr;
385 386
386 387 return (TRUE);
387 388 }
388 389
389 390 static bool_t
390 391 xdr_encode_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
391 392 {
392 393 uint_t otw_len, fsize, xsize; /* otw, file, and export sizes */
393 394 bool_t ret;
394 395 rpc_inline_t *ptr;
395 396 rpc_inline_t *buf = NULL;
396 397 uint32_t *ptr_redzone;
397 398
398 399 ASSERT(xdrs->x_op == XDR_ENCODE);
399 400
400 401 fsize = objp->fh3_len < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_len;
401 402 xsize = objp->fh3_xlen < NFS_FHMAXDATA ? NFS_FHMAXDATA : objp->fh3_xlen;
402 403
403 404 /*
404 405 * First get the over the wire size, it is the 4 bytes
405 406 * for the length, plus the combined size of the
406 407 * file handle components.
407 408 */
408 409 otw_len = BYTES_PER_XDR_UNIT + sizeof (objp->fh3_fsid) +
409 410 sizeof (objp->fh3_len) + fsize +
410 411 sizeof (objp->fh3_xlen) + xsize;
411 412 /*
412 413 * Round out to a full word.
413 414 */
414 415 otw_len = RNDUP(otw_len);
415 416
416 417 /*
417 418 * Next try to inline the XDR stream, if that fails (rare)
418 419 * allocate a buffer to encode the file handle and then
419 420 * copy it using xdr_opaque and free the buffer.
420 421 */
421 422 ptr = XDR_INLINE(xdrs, otw_len);
422 423 if (ptr == NULL)
423 424 ptr = buf = kmem_alloc(otw_len, KM_SLEEP);
424 425
425 426 ptr_redzone = (uint32_t *)(ptr + (otw_len / BYTES_PER_XDR_UNIT));
426 427 ret = xdr_inline_encode_nfs_fh3((uint32_t **)&ptr, ptr_redzone, objp);
427 428
428 429 if (buf != NULL) {
429 430 if (ret == TRUE)
430 431 ret = xdr_opaque(xdrs, (char *)buf, otw_len);
431 432 kmem_free(buf, otw_len);
432 433 }
433 434 return (ret);
434 435 }
435 436
436 437 /*
437 438 * XDR a NFSv3 filehandle the naive way.
438 439 */
439 440 bool_t
440 441 xdr_nfs_fh3(XDR *xdrs, nfs_fh3 *objp)
441 442 {
442 443 if (xdrs->x_op == XDR_FREE)
443 444 return (TRUE);
444 445
445 446 if (!xdr_u_int(xdrs, &objp->fh3_length))
446 447 return (FALSE);
447 448
448 449 if (objp->fh3_length > NFS3_FHSIZE)
449 450 return (FALSE);
450 451
451 452 return (xdr_opaque(xdrs, objp->fh3_u.data, objp->fh3_length));
452 453 }
453 454
454 455 /*
455 456 * XDR a NFSv3 filehandle with intelligence on the server.
456 457 * Encoding goes from our in-memory structure to wire format.
457 458 * Decoding goes from wire format to our in-memory structure.
458 459 */
459 460 bool_t
460 461 xdr_nfs_fh3_server(XDR *xdrs, nfs_fh3 *objp)
461 462 {
462 463 switch (xdrs->x_op) {
463 464 case XDR_ENCODE:
464 465 if (objp->fh3_flags & FH_WEBNFS)
465 466 return (xdr_nfs_fh3(xdrs, objp));
466 467 else
467 468 return (xdr_encode_nfs_fh3(xdrs, objp));
468 469 case XDR_DECODE:
469 470 return (xdr_decode_nfs_fh3(xdrs, objp));
470 471 case XDR_FREE:
471 472 if (objp->fh3_u.data != NULL)
472 473 bzero(objp->fh3_u.data, sizeof (objp->fh3_u.data));
473 474 return (TRUE);
474 475 }
475 476 return (FALSE);
476 477 }
477 478
478 479 bool_t
479 480 xdr_diropargs3(XDR *xdrs, diropargs3 *objp)
480 481 {
481 482 switch (xdrs->x_op) {
482 483 case XDR_FREE:
483 484 case XDR_ENCODE:
484 485 if (!xdr_nfs_fh3(xdrs, objp->dirp))
485 486 return (FALSE);
486 487 break;
487 488 case XDR_DECODE:
488 489 if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
489 490 return (FALSE);
490 491 break;
491 492 }
492 493 return (xdr_string3(xdrs, &objp->name, MAXNAMELEN));
493 494 }
494 495
495 496 static bool_t
496 497 xdr_fattr3(XDR *xdrs, fattr3 *na)
497 498 {
498 499 int32_t *ptr;
499 500
500 501 if (xdrs->x_op == XDR_FREE)
501 502 return (TRUE);
502 503
503 504 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
504 505 if (ptr != NULL) {
505 506 if (xdrs->x_op == XDR_DECODE) {
506 507 na->type = IXDR_GET_ENUM(ptr, enum ftype3);
507 508 na->mode = IXDR_GET_U_INT32(ptr);
508 509 na->nlink = IXDR_GET_U_INT32(ptr);
509 510 na->uid = IXDR_GET_U_INT32(ptr);
510 511 na->gid = IXDR_GET_U_INT32(ptr);
511 512 IXDR_GET_U_HYPER(ptr, na->size);
512 513 IXDR_GET_U_HYPER(ptr, na->used);
513 514 na->rdev.specdata1 = IXDR_GET_U_INT32(ptr);
514 515 na->rdev.specdata2 = IXDR_GET_U_INT32(ptr);
515 516 IXDR_GET_U_HYPER(ptr, na->fsid);
516 517 IXDR_GET_U_HYPER(ptr, na->fileid);
517 518 na->atime.seconds = IXDR_GET_U_INT32(ptr);
518 519 na->atime.nseconds = IXDR_GET_U_INT32(ptr);
519 520 na->mtime.seconds = IXDR_GET_U_INT32(ptr);
520 521 na->mtime.nseconds = IXDR_GET_U_INT32(ptr);
521 522 na->ctime.seconds = IXDR_GET_U_INT32(ptr);
522 523 na->ctime.nseconds = IXDR_GET_U_INT32(ptr);
523 524 } else {
524 525 IXDR_PUT_ENUM(ptr, na->type);
525 526 IXDR_PUT_U_INT32(ptr, na->mode);
526 527 IXDR_PUT_U_INT32(ptr, na->nlink);
527 528 IXDR_PUT_U_INT32(ptr, na->uid);
528 529 IXDR_PUT_U_INT32(ptr, na->gid);
529 530 IXDR_PUT_U_HYPER(ptr, na->size);
530 531 IXDR_PUT_U_HYPER(ptr, na->used);
531 532 IXDR_PUT_U_INT32(ptr, na->rdev.specdata1);
532 533 IXDR_PUT_U_INT32(ptr, na->rdev.specdata2);
533 534 IXDR_PUT_U_HYPER(ptr, na->fsid);
534 535 IXDR_PUT_U_HYPER(ptr, na->fileid);
535 536 IXDR_PUT_U_INT32(ptr, na->atime.seconds);
536 537 IXDR_PUT_U_INT32(ptr, na->atime.nseconds);
537 538 IXDR_PUT_U_INT32(ptr, na->mtime.seconds);
538 539 IXDR_PUT_U_INT32(ptr, na->mtime.nseconds);
539 540 IXDR_PUT_U_INT32(ptr, na->ctime.seconds);
540 541 IXDR_PUT_U_INT32(ptr, na->ctime.nseconds);
541 542 }
542 543 return (TRUE);
543 544 }
544 545 if (!(xdr_enum(xdrs, (enum_t *)&na->type) &&
545 546 xdr_u_int(xdrs, &na->mode) &&
546 547 xdr_u_int(xdrs, &na->nlink) &&
547 548 xdr_u_int(xdrs, &na->uid) &&
548 549 xdr_u_int(xdrs, &na->gid) &&
549 550 xdr_u_longlong_t(xdrs, &na->size) &&
550 551 xdr_u_longlong_t(xdrs, &na->used) &&
551 552 xdr_u_int(xdrs, &na->rdev.specdata1) &&
552 553 xdr_u_int(xdrs, &na->rdev.specdata2) &&
553 554 xdr_u_longlong_t(xdrs, &na->fsid) &&
554 555 xdr_u_longlong_t(xdrs, &na->fileid) &&
555 556 xdr_u_int(xdrs, &na->atime.seconds) &&
556 557 xdr_u_int(xdrs, &na->atime.nseconds) &&
557 558 xdr_u_int(xdrs, &na->mtime.seconds) &&
558 559 xdr_u_int(xdrs, &na->mtime.nseconds) &&
559 560 xdr_u_int(xdrs, &na->ctime.seconds) &&
560 561 xdr_u_int(xdrs, &na->ctime.nseconds)))
561 562 return (FALSE);
562 563 return (TRUE);
563 564 }
564 565
565 566 /*
566 567 * Fast decode of an fattr3 to a vattr
567 568 * Only return FALSE on decode error, all other fattr to vattr translation
568 569 * failures set status.
569 570 *
570 571 * Callers must catch the following errors:
571 572 * EFBIG - file size will not fit in va_size
572 573 * EOVERFLOW - time will not fit in va_*time
573 574 */
574 575 static bool_t
575 576 xdr_fattr3_to_vattr(XDR *xdrs, fattr3_res *objp)
576 577 {
577 578 int32_t *ptr;
578 579 size3 used;
579 580 specdata3 rdev;
580 581 uint32_t ntime;
581 582 vattr_t *vap = objp->vap;
582 583
583 584 /*
584 585 * DECODE only
585 586 */
586 587 ASSERT(xdrs->x_op == XDR_DECODE);
587 588
588 589 /* On success, all attributes will be decoded */
589 590 vap->va_mask = AT_ALL;
590 591
591 592 objp->status = 0;
592 593 ptr = XDR_INLINE(xdrs, NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT);
593 594 if (ptr != NULL) {
594 595 /*
595 596 * Common case
596 597 */
597 598 vap->va_type = IXDR_GET_ENUM(ptr, enum vtype);
598 599 if ((ftype3)vap->va_type < NF3REG ||
599 600 (ftype3)vap->va_type > NF3FIFO)
600 601 vap->va_type = VBAD;
601 602 else
602 603 vap->va_type = nf3_to_vt[vap->va_type];
603 604 vap->va_mode = IXDR_GET_U_INT32(ptr);
604 605 vap->va_nlink = IXDR_GET_U_INT32(ptr);
605 606 vap->va_uid = (uid_t)IXDR_GET_U_INT32(ptr);
606 607 if (vap->va_uid == NFS_UID_NOBODY)
607 608 vap->va_uid = UID_NOBODY;
608 609 vap->va_gid = (gid_t)IXDR_GET_U_INT32(ptr);
609 610 if (vap->va_gid == NFS_GID_NOBODY)
610 611 vap->va_gid = GID_NOBODY;
611 612 IXDR_GET_U_HYPER(ptr, vap->va_size);
612 613 /*
613 614 * If invalid size, stop decode, set status, and
614 615 * return TRUE, x_handy will be correct, caller must ignore vap.
615 616 */
616 617 if (!NFS3_SIZE_OK(vap->va_size)) {
617 618 objp->status = EFBIG;
618 619 return (TRUE);
619 620 }
620 621 IXDR_GET_U_HYPER(ptr, used);
621 622 rdev.specdata1 = IXDR_GET_U_INT32(ptr);
622 623 rdev.specdata2 = IXDR_GET_U_INT32(ptr);
623 624 /* fsid is ignored */
624 625 ptr += 2;
625 626 IXDR_GET_U_HYPER(ptr, vap->va_nodeid);
626 627
627 628 /*
628 629 * nfs protocol defines times as unsigned so don't
629 630 * extend sign, unless sysadmin set nfs_allow_preepoch_time.
630 631 * The inline macros do the equivilant of NFS_TIME_T_CONVERT
631 632 */
632 633 if (nfs_allow_preepoch_time) {
633 634 vap->va_atime.tv_sec = IXDR_GET_INT32(ptr);
634 635 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
635 636 vap->va_mtime.tv_sec = IXDR_GET_INT32(ptr);
636 637 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
637 638 vap->va_ctime.tv_sec = IXDR_GET_INT32(ptr);
638 639 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
639 640 } else {
640 641 /*
641 642 * Check if the time would overflow on 32-bit
642 643 */
643 644 ntime = IXDR_GET_U_INT32(ptr);
644 645 /*CONSTCOND*/
645 646 if (NFS3_TIME_OVERFLOW(ntime)) {
646 647 objp->status = EOVERFLOW;
647 648 return (TRUE);
648 649 }
649 650 vap->va_atime.tv_sec = ntime;
650 651 vap->va_atime.tv_nsec = IXDR_GET_U_INT32(ptr);
651 652
652 653 ntime = IXDR_GET_U_INT32(ptr);
653 654 /*CONSTCOND*/
654 655 if (NFS3_TIME_OVERFLOW(ntime)) {
655 656 objp->status = EOVERFLOW;
656 657 return (TRUE);
657 658 }
658 659 vap->va_mtime.tv_sec = ntime;
659 660 vap->va_mtime.tv_nsec = IXDR_GET_U_INT32(ptr);
660 661
661 662 ntime = IXDR_GET_U_INT32(ptr);
662 663 /*CONSTCOND*/
663 664 if (NFS3_TIME_OVERFLOW(ntime)) {
664 665 objp->status = EOVERFLOW;
665 666 return (TRUE);
666 667 }
667 668 vap->va_ctime.tv_sec = ntime;
668 669 vap->va_ctime.tv_nsec = IXDR_GET_U_INT32(ptr);
669 670 }
670 671
671 672 } else {
672 673 uint64 fsid;
673 674
674 675 /*
675 676 * Slow path
676 677 */
677 678 if (!(xdr_enum(xdrs, (enum_t *)&vap->va_type) &&
678 679 xdr_u_int(xdrs, &vap->va_mode) &&
679 680 xdr_u_int(xdrs, &vap->va_nlink) &&
680 681 xdr_u_int(xdrs, (uint_t *)&vap->va_uid) &&
681 682 xdr_u_int(xdrs, (uint_t *)&vap->va_gid) &&
682 683 xdr_u_longlong_t(xdrs, &vap->va_size) &&
683 684 xdr_u_longlong_t(xdrs, &used) &&
684 685 xdr_u_int(xdrs, &rdev.specdata1) &&
685 686 xdr_u_int(xdrs, &rdev.specdata2) &&
686 687 xdr_u_longlong_t(xdrs, &fsid) && /* ignored */
687 688 xdr_u_longlong_t(xdrs, &vap->va_nodeid)))
688 689 return (FALSE);
689 690
690 691 if (nfs_allow_preepoch_time) {
691 692 if (!xdr_u_int(xdrs, &ntime))
692 693 return (FALSE);
693 694 vap->va_atime.tv_sec = (int32_t)ntime;
694 695 if (!xdr_u_int(xdrs, &ntime))
695 696 return (FALSE);
696 697 vap->va_atime.tv_nsec = ntime;
697 698
698 699 if (!xdr_u_int(xdrs, &ntime))
699 700 return (FALSE);
700 701 vap->va_mtime.tv_sec = (int32_t)ntime;
701 702 if (!xdr_u_int(xdrs, &ntime))
702 703 return (FALSE);
703 704 vap->va_mtime.tv_nsec = ntime;
704 705
705 706 if (!xdr_u_int(xdrs, &ntime))
706 707 return (FALSE);
707 708 vap->va_ctime.tv_sec = (int32_t)ntime;
708 709 if (!xdr_u_int(xdrs, &ntime))
709 710 return (FALSE);
710 711 vap->va_ctime.tv_nsec = ntime;
711 712 } else {
712 713 /*
713 714 * Check if the time would overflow on 32-bit
714 715 * Set status and keep decoding stream.
715 716 */
716 717 if (!xdr_u_int(xdrs, &ntime))
717 718 return (FALSE);
718 719 /*CONSTCOND*/
719 720 if (NFS3_TIME_OVERFLOW(ntime)) {
720 721 objp->status = EOVERFLOW;
721 722 }
722 723 vap->va_atime.tv_sec = ntime;
723 724 if (!xdr_u_int(xdrs, &ntime))
724 725 return (FALSE);
725 726 vap->va_atime.tv_nsec = ntime;
726 727
727 728 if (!xdr_u_int(xdrs, &ntime))
728 729 return (FALSE);
729 730 /*CONSTCOND*/
730 731 if (NFS3_TIME_OVERFLOW(ntime)) {
731 732 objp->status = EOVERFLOW;
732 733 }
733 734 vap->va_mtime.tv_sec = ntime;
734 735 if (!xdr_u_int(xdrs, &ntime))
735 736 return (FALSE);
736 737 vap->va_mtime.tv_nsec = ntime;
737 738
738 739 if (!xdr_u_int(xdrs, &ntime))
739 740 return (FALSE);
740 741 /*CONSTCOND*/
741 742 if (NFS3_TIME_OVERFLOW(ntime)) {
742 743 objp->status = EOVERFLOW;
743 744 }
744 745 vap->va_ctime.tv_sec = ntime;
745 746 if (!xdr_u_int(xdrs, &ntime))
746 747 return (FALSE);
747 748 vap->va_ctime.tv_nsec = ntime;
748 749 }
749 750
750 751 /*
751 752 * Fixup as needed
752 753 */
753 754 if ((ftype3)vap->va_type < NF3REG ||
754 755 (ftype3)vap->va_type > NF3FIFO)
755 756 vap->va_type = VBAD;
756 757 else
757 758 vap->va_type = nf3_to_vt[vap->va_type];
758 759 if (vap->va_uid == NFS_UID_NOBODY)
759 760 vap->va_uid = UID_NOBODY;
760 761 if (vap->va_gid == NFS_GID_NOBODY)
761 762 vap->va_gid = GID_NOBODY;
762 763 /*
763 764 * If invalid size, set status, and
764 765 * return TRUE, caller must ignore vap.
765 766 */
766 767 if (!NFS3_SIZE_OK(vap->va_size)) {
767 768 objp->status = EFBIG;
768 769 return (TRUE);
769 770 }
770 771 }
771 772
772 773 /*
773 774 * Fill in derived fields
774 775 */
775 776 vap->va_fsid = objp->vp->v_vfsp->vfs_dev;
776 777 vap->va_seq = 0;
777 778
778 779 /*
779 780 * Common case values
780 781 */
781 782 vap->va_rdev = 0;
782 783 vap->va_blksize = MAXBSIZE;
783 784 vap->va_nblocks = 0;
784 785
785 786 switch (vap->va_type) {
786 787 case VREG:
787 788 case VDIR:
788 789 case VLNK:
789 790 vap->va_nblocks = (u_longlong_t)
790 791 ((used + (size3)DEV_BSIZE - (size3)1) /
791 792 (size3)DEV_BSIZE);
792 793 break;
793 794 case VBLK:
794 795 vap->va_blksize = DEV_BSIZE;
795 796 /* FALLTHRU */
796 797 case VCHR:
797 798 vap->va_rdev = makedevice(rdev.specdata1, rdev.specdata2);
798 799 break;
799 800 case VSOCK:
800 801 case VFIFO:
801 802 default:
802 803 break;
803 804 }
804 805
805 806 return (TRUE);
806 807 }
807 808
808 809 static bool_t
809 810 xdr_post_op_vattr(XDR *xdrs, post_op_vattr *objp)
810 811 {
811 812 /*
812 813 * DECODE only
813 814 */
814 815 ASSERT(xdrs->x_op == XDR_DECODE);
815 816
816 817 if (!xdr_bool(xdrs, &objp->attributes))
817 818 return (FALSE);
818 819
819 820 if (objp->attributes == FALSE)
820 821 return (TRUE);
821 822
822 823 if (objp->attributes != TRUE)
823 824 return (FALSE);
824 825
825 826 if (!xdr_fattr3_to_vattr(xdrs, &objp->fres))
826 827 return (FALSE);
827 828
828 829 /*
829 830 * The file size may cause an EFBIG or the time values
830 831 * may cause EOVERFLOW, if so simply drop the attributes.
831 832 */
832 833 if (objp->fres.status != NFS3_OK)
833 834 objp->attributes = FALSE;
834 835
835 836 return (TRUE);
836 837 }
837 838
838 839 bool_t
839 840 xdr_post_op_attr(XDR *xdrs, post_op_attr *objp)
840 841 {
841 842 if (!xdr_bool(xdrs, &objp->attributes))
842 843 return (FALSE);
843 844
844 845 if (objp->attributes == FALSE)
845 846 return (TRUE);
846 847
847 848 if (objp->attributes != TRUE)
848 849 return (FALSE);
849 850
850 851 if (!xdr_fattr3(xdrs, &objp->attr))
851 852 return (FALSE);
852 853
853 854 /*
854 855 * Check that we don't get a file we can't handle through
855 856 * existing interfaces (especially stat64()).
856 857 * Decode only check since on encode the data has
857 858 * been dealt with in the above call to xdr_fattr3().
858 859 */
859 860 if (xdrs->x_op == XDR_DECODE) {
860 861 /* Set attrs to false if invalid size or time */
861 862 if (!NFS3_SIZE_OK(objp->attr.size)) {
862 863 objp->attributes = FALSE;
863 864 return (TRUE);
864 865 }
865 866 #ifndef _LP64
866 867 if (!NFS3_FATTR_TIME_OK(&objp->attr))
867 868 objp->attributes = FALSE;
868 869 #endif
869 870 }
870 871 return (TRUE);
871 872 }
872 873
873 874 static bool_t
874 875 xdr_wcc_data(XDR *xdrs, wcc_data *objp)
875 876 {
876 877 int32_t *ptr;
877 878 wcc_attr *attrp;
878 879
879 880 if (xdrs->x_op == XDR_FREE)
880 881 return (TRUE);
881 882
882 883 if (xdrs->x_op == XDR_DECODE) {
883 884 /* pre_op_attr */
884 885 if (!xdr_bool(xdrs, &objp->before.attributes))
885 886 return (FALSE);
886 887
887 888 switch (objp->before.attributes) {
888 889 case TRUE:
889 890 attrp = &objp->before.attr;
890 891 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
891 892 if (ptr != NULL) {
892 893 IXDR_GET_U_HYPER(ptr, attrp->size);
893 894 attrp->mtime.seconds = IXDR_GET_U_INT32(ptr);
894 895 attrp->mtime.nseconds = IXDR_GET_U_INT32(ptr);
895 896 attrp->ctime.seconds = IXDR_GET_U_INT32(ptr);
896 897 attrp->ctime.nseconds = IXDR_GET_U_INT32(ptr);
897 898 } else {
898 899 if (!xdr_u_longlong_t(xdrs, &attrp->size))
899 900 return (FALSE);
900 901 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
901 902 return (FALSE);
902 903 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
903 904 return (FALSE);
904 905 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
905 906 return (FALSE);
906 907 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
907 908 return (FALSE);
908 909 }
909 910
910 911 #ifndef _LP64
911 912 /*
912 913 * check time overflow.
913 914 */
914 915 if (!NFS3_TIME_OK(attrp->mtime.seconds) ||
915 916 !NFS3_TIME_OK(attrp->ctime.seconds))
916 917 objp->before.attributes = FALSE;
917 918 #endif
918 919 break;
919 920 case FALSE:
920 921 break;
921 922 default:
922 923 return (FALSE);
923 924 }
924 925 }
925 926
926 927 if (xdrs->x_op == XDR_ENCODE) {
927 928 /* pre_op_attr */
928 929 if (!xdr_bool(xdrs, &objp->before.attributes))
929 930 return (FALSE);
930 931
931 932 switch (objp->before.attributes) {
932 933 case TRUE:
933 934 attrp = &objp->before.attr;
934 935
935 936 ptr = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
936 937 if (ptr != NULL) {
937 938 IXDR_PUT_U_HYPER(ptr, attrp->size);
938 939 IXDR_PUT_U_INT32(ptr, attrp->mtime.seconds);
939 940 IXDR_PUT_U_INT32(ptr, attrp->mtime.nseconds);
940 941 IXDR_PUT_U_INT32(ptr, attrp->ctime.seconds);
941 942 IXDR_PUT_U_INT32(ptr, attrp->ctime.nseconds);
942 943 } else {
943 944 if (!xdr_u_longlong_t(xdrs, &attrp->size))
944 945 return (FALSE);
945 946 if (!xdr_u_int(xdrs, &attrp->mtime.seconds))
946 947 return (FALSE);
947 948 if (!xdr_u_int(xdrs, &attrp->mtime.nseconds))
948 949 return (FALSE);
949 950 if (!xdr_u_int(xdrs, &attrp->ctime.seconds))
950 951 return (FALSE);
951 952 if (!xdr_u_int(xdrs, &attrp->ctime.nseconds))
952 953 return (FALSE);
953 954 }
954 955 break;
955 956 case FALSE:
956 957 break;
957 958 default:
958 959 return (FALSE);
959 960 }
960 961 }
961 962 return (xdr_post_op_attr(xdrs, &objp->after));
962 963 }
963 964
964 965 bool_t
965 966 xdr_post_op_fh3(XDR *xdrs, post_op_fh3 *objp)
966 967 {
967 968 if (!xdr_bool(xdrs, &objp->handle_follows))
968 969 return (FALSE);
969 970 switch (objp->handle_follows) {
970 971 case TRUE:
971 972 switch (xdrs->x_op) {
972 973 case XDR_ENCODE:
973 974 if (!xdr_nfs_fh3_server(xdrs, &objp->handle))
974 975 return (FALSE);
975 976 break;
976 977 case XDR_FREE:
977 978 case XDR_DECODE:
978 979 if (!xdr_nfs_fh3(xdrs, &objp->handle))
979 980 return (FALSE);
980 981 break;
981 982 }
982 983 return (TRUE);
983 984 case FALSE:
984 985 return (TRUE);
985 986 default:
986 987 return (FALSE);
987 988 }
988 989 }
989 990
990 991 static bool_t
991 992 xdr_sattr3(XDR *xdrs, sattr3 *objp)
992 993 {
993 994 /* set_mode3 */
994 995 if (!xdr_bool(xdrs, &objp->mode.set_it))
995 996 return (FALSE);
996 997 if (objp->mode.set_it)
997 998 if (!xdr_u_int(xdrs, &objp->mode.mode))
998 999 return (FALSE);
999 1000 /* set_uid3 */
1000 1001 if (!xdr_bool(xdrs, &objp->uid.set_it))
1001 1002 return (FALSE);
1002 1003 if (objp->uid.set_it)
1003 1004 if (!xdr_u_int(xdrs, &objp->uid.uid))
1004 1005 return (FALSE);
1005 1006 /* set_gid3 */
1006 1007 if (!xdr_bool(xdrs, &objp->gid.set_it))
1007 1008 return (FALSE);
1008 1009 if (objp->gid.set_it)
1009 1010 if (!xdr_u_int(xdrs, &objp->gid.gid))
1010 1011 return (FALSE);
1011 1012
1012 1013 /* set_size3 */
1013 1014 if (!xdr_bool(xdrs, &objp->size.set_it))
1014 1015 return (FALSE);
1015 1016 if (objp->size.set_it)
1016 1017 if (!xdr_u_longlong_t(xdrs, &objp->size.size))
1017 1018 return (FALSE);
1018 1019
1019 1020 /* set_atime */
1020 1021 if (!xdr_enum(xdrs, (enum_t *)&objp->atime.set_it))
1021 1022 return (FALSE);
1022 1023 if (objp->atime.set_it == SET_TO_CLIENT_TIME) {
1023 1024 if (!xdr_u_int(xdrs, &objp->atime.atime.seconds))
1024 1025 return (FALSE);
1025 1026 if (!xdr_u_int(xdrs, &objp->atime.atime.nseconds))
1026 1027 return (FALSE);
1027 1028 }
1028 1029
1029 1030 /* set_mtime */
1030 1031 if (!xdr_enum(xdrs, (enum_t *)&objp->mtime.set_it))
1031 1032 return (FALSE);
1032 1033 if (objp->mtime.set_it == SET_TO_CLIENT_TIME) {
1033 1034 if (!xdr_u_int(xdrs, &objp->mtime.mtime.seconds))
1034 1035 return (FALSE);
1035 1036 if (!xdr_u_int(xdrs, &objp->mtime.mtime.nseconds))
1036 1037 return (FALSE);
1037 1038 }
1038 1039
1039 1040 return (TRUE);
1040 1041 }
1041 1042
1042 1043 bool_t
1043 1044 xdr_GETATTR3res(XDR *xdrs, GETATTR3res *objp)
1044 1045 {
1045 1046 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1046 1047 return (FALSE);
1047 1048 if (objp->status != NFS3_OK)
1048 1049 return (TRUE);
1049 1050 /* xdr_GETATTR3resok */
1050 1051 return (xdr_fattr3(xdrs, &objp->resok.obj_attributes));
1051 1052 }
1052 1053
1053 1054 bool_t
1054 1055 xdr_GETATTR3vres(XDR *xdrs, GETATTR3vres *objp)
1055 1056 {
1056 1057 /*
1057 1058 * DECODE or FREE only
1058 1059 */
1059 1060 if (xdrs->x_op == XDR_FREE)
1060 1061 return (TRUE);
1061 1062
1062 1063 if (xdrs->x_op != XDR_DECODE)
1063 1064 return (FALSE);
1064 1065
1065 1066 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1066 1067 return (FALSE);
1067 1068
1068 1069 if (objp->status != NFS3_OK)
1069 1070 return (TRUE);
1070 1071
1071 1072 return (xdr_fattr3_to_vattr(xdrs, &objp->fres));
1072 1073 }
1073 1074
1074 1075
1075 1076 bool_t
1076 1077 xdr_SETATTR3args(XDR *xdrs, SETATTR3args *objp)
1077 1078 {
1078 1079 switch (xdrs->x_op) {
1079 1080 case XDR_FREE:
1080 1081 case XDR_ENCODE:
1081 1082 if (!xdr_nfs_fh3(xdrs, &objp->object))
1082 1083 return (FALSE);
1083 1084 break;
1084 1085 case XDR_DECODE:
1085 1086 if (!xdr_nfs_fh3_server(xdrs, &objp->object))
1086 1087 return (FALSE);
1087 1088 break;
1088 1089 }
1089 1090 if (!xdr_sattr3(xdrs, &objp->new_attributes))
1090 1091 return (FALSE);
1091 1092
1092 1093 /* sattrguard3 */
1093 1094 if (!xdr_bool(xdrs, &objp->guard.check))
1094 1095 return (FALSE);
1095 1096 switch (objp->guard.check) {
1096 1097 case TRUE:
1097 1098 if (!xdr_u_int(xdrs, &objp->guard.obj_ctime.seconds))
1098 1099 return (FALSE);
1099 1100 return (xdr_u_int(xdrs, &objp->guard.obj_ctime.nseconds));
1100 1101 case FALSE:
1101 1102 return (TRUE);
1102 1103 default:
1103 1104 return (FALSE);
1104 1105 }
1105 1106 }
1106 1107
1107 1108 bool_t
1108 1109 xdr_SETATTR3res(XDR *xdrs, SETATTR3res *objp)
1109 1110 {
1110 1111 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1111 1112 return (FALSE);
1112 1113 switch (objp->status) {
1113 1114 case NFS3_OK:
1114 1115 return (xdr_wcc_data(xdrs, &objp->resok.obj_wcc));
1115 1116 default:
1116 1117 return (xdr_wcc_data(xdrs, &objp->resfail.obj_wcc));
1117 1118 }
1118 1119 }
1119 1120
1120 1121 bool_t
1121 1122 xdr_LOOKUP3res(XDR *xdrs, LOOKUP3res *objp)
1122 1123 {
1123 1124 LOOKUP3resok *resokp;
1124 1125
1125 1126 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1126 1127 return (FALSE);
1127 1128
1128 1129 if (objp->status != NFS3_OK)
1129 1130 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
1130 1131
1131 1132 /* xdr_LOOKUP3resok */
1132 1133 resokp = &objp->resok;
1133 1134 switch (xdrs->x_op) {
1134 1135 case XDR_ENCODE:
1135 1136 if (!xdr_nfs_fh3_server(xdrs, &resokp->object))
1136 1137 return (FALSE);
1137 1138 break;
1138 1139 case XDR_FREE:
1139 1140 case XDR_DECODE:
1140 1141 if (!xdr_nfs_fh3(xdrs, &resokp->object))
1141 1142 return (FALSE);
1142 1143 break;
1143 1144 }
1144 1145 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1145 1146 return (FALSE);
1146 1147 return (xdr_post_op_attr(xdrs, &resokp->dir_attributes));
1147 1148 }
1148 1149
1149 1150 bool_t
1150 1151 xdr_LOOKUP3vres(XDR *xdrs, LOOKUP3vres *objp)
1151 1152 {
1152 1153 /*
1153 1154 * DECODE or FREE only
1154 1155 */
1155 1156 if (xdrs->x_op == XDR_FREE)
1156 1157 return (TRUE);
1157 1158
1158 1159 if (xdrs->x_op != XDR_DECODE)
1159 1160 return (FALSE);
1160 1161
1161 1162 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1162 1163 return (FALSE);
1163 1164
1164 1165 if (objp->status != NFS3_OK)
1165 1166 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1166 1167
1167 1168 if (!xdr_nfs_fh3(xdrs, &objp->object))
1168 1169 return (FALSE);
1169 1170 if (!xdr_post_op_vattr(xdrs, &objp->obj_attributes))
1170 1171 return (FALSE);
1171 1172 return (xdr_post_op_vattr(xdrs, &objp->dir_attributes));
1172 1173 }
1173 1174
1174 1175 bool_t
1175 1176 xdr_ACCESS3args(XDR *xdrs, ACCESS3args *objp)
1176 1177 {
1177 1178 switch (xdrs->x_op) {
1178 1179 case XDR_FREE:
1179 1180 case XDR_ENCODE:
1180 1181 if (!xdr_nfs_fh3(xdrs, &objp->object))
1181 1182 return (FALSE);
1182 1183 break;
1183 1184 case XDR_DECODE:
1184 1185 if (!xdr_nfs_fh3_server(xdrs, &objp->object))
1185 1186 return (FALSE);
1186 1187 break;
1187 1188 }
1188 1189 return (xdr_u_int(xdrs, &objp->access));
1189 1190 }
1190 1191
1191 1192
1192 1193 bool_t
1193 1194 xdr_ACCESS3res(XDR *xdrs, ACCESS3res *objp)
1194 1195 {
1195 1196 ACCESS3resok *resokp;
1196 1197
1197 1198 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1198 1199 return (FALSE);
1199 1200 if (objp->status != NFS3_OK)
1200 1201 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
1201 1202
1202 1203 /* xdr_ACCESS3resok */
1203 1204 resokp = &objp->resok;
1204 1205 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1205 1206 return (FALSE);
1206 1207 return (xdr_u_int(xdrs, &resokp->access));
1207 1208 }
1208 1209
1209 1210 bool_t
1210 1211 xdr_READLINK3args(XDR *xdrs, READLINK3args *objp)
1211 1212 {
1212 1213 rdma_chunkinfo_t rci;
1213 1214 struct xdr_ops *xops = xdrrdma_xops();
1214 1215
1215 1216 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
1216 1217 xdrs->x_op == XDR_ENCODE) {
1217 1218 rci.rci_type = RCI_REPLY_CHUNK;
1218 1219 rci.rci_len = MAXPATHLEN;
1219 1220 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
1220 1221 }
1221 1222 if (!xdr_nfs_fh3(xdrs, (nfs_fh3 *)objp))
1222 1223 return (FALSE);
1223 1224 return (TRUE);
1224 1225 }
1225 1226
1226 1227 bool_t
1227 1228 xdr_READLINK3res(XDR *xdrs, READLINK3res *objp)
1228 1229 {
1229 1230
1230 1231 READLINK3resok *resokp;
1231 1232
1232 1233 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1233 1234 return (FALSE);
1234 1235 if (objp->status != NFS3_OK)
1235 1236 return (xdr_post_op_attr(xdrs,
1236 1237 &objp->resfail.symlink_attributes));
1237 1238
1238 1239 /* xdr_READLINK3resok */
1239 1240 resokp = &objp->resok;
1240 1241 if (!xdr_post_op_attr(xdrs, &resokp->symlink_attributes))
1241 1242 return (FALSE);
1242 1243 return (xdr_string3(xdrs, &resokp->data, MAXPATHLEN));
1243 1244 }
1244 1245
1245 1246 bool_t
1246 1247 xdr_READ3args(XDR *xdrs, READ3args *objp)
1247 1248 {
1248 1249 rdma_chunkinfo_t rci;
1249 1250 rdma_wlist_conn_info_t rwci;
1250 1251 struct xdr_ops *xops = xdrrdma_xops();
1251 1252
1252 1253 switch (xdrs->x_op) {
1253 1254 case XDR_FREE:
1254 1255 case XDR_ENCODE:
1255 1256 if (!xdr_nfs_fh3(xdrs, &objp->file))
1256 1257 return (FALSE);
1257 1258 break;
1258 1259 case XDR_DECODE:
1259 1260 if (!xdr_nfs_fh3_server(xdrs, &objp->file))
1260 1261 return (FALSE);
1261 1262 break;
1262 1263 }
1263 1264 if (!xdr_u_longlong_t(xdrs, &objp->offset))
1264 1265 return (FALSE);
1265 1266 if (!xdr_u_int(xdrs, &objp->count))
1266 1267 return (FALSE);
1267 1268
1268 1269 DTRACE_PROBE1(xdr__i__read3_buf_len, int, objp->count);
1269 1270
1270 1271 objp->wlist = NULL;
1271 1272
1272 1273 /* if xdrrdma_sizeof in progress, then store the size */
1273 1274 if (xdrs->x_ops == xops && xdrs->x_op == XDR_ENCODE) {
1274 1275 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
1275 1276 rci.rci_len = objp->count;
1276 1277 (void) XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
1277 1278 }
1278 1279
1279 1280 if (xdrs->x_ops != &xdrrdma_ops || xdrs->x_op == XDR_FREE)
1280 1281 return (TRUE);
1281 1282
1282 1283 if (xdrs->x_op == XDR_ENCODE) {
1283 1284
1284 1285 if (objp->res_uiop != NULL) {
1285 1286 rci.rci_type = RCI_WRITE_UIO_CHUNK;
1286 1287 rci.rci_a.rci_uiop = objp->res_uiop;
1287 1288 rci.rci_len = objp->count;
1288 1289 rci.rci_clpp = &objp->wlist;
1289 1290 } else {
1290 1291 rci.rci_type = RCI_WRITE_ADDR_CHUNK;
1291 1292 rci.rci_a.rci_addr = objp->res_data_val_alt;
1292 1293 rci.rci_len = objp->count;
1293 1294 rci.rci_clpp = &objp->wlist;
1294 1295 }
1295 1296
1296 1297 return (XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci));
1297 1298 }
1298 1299
1299 1300 /* XDR_DECODE case */
1300 1301 (void) XDR_CONTROL(xdrs, XDR_RDMA_GET_WCINFO, &rwci);
1301 1302 objp->wlist = rwci.rwci_wlist;
1302 1303 objp->conn = rwci.rwci_conn;
1303 1304
1304 1305 return (TRUE);
1305 1306 }
1306 1307
1307 1308 bool_t
1308 1309 xdr_READ3res(XDR *xdrs, READ3res *objp)
1309 1310 {
1310 1311 READ3resok *resokp;
1311 1312 bool_t ret;
1312 1313 mblk_t *mp;
1313 1314
1314 1315 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1315 1316 return (FALSE);
1316 1317
1317 1318 if (objp->status != NFS3_OK)
1318 1319 return (xdr_post_op_attr(xdrs, &objp->resfail.file_attributes));
1319 1320
1320 1321 resokp = &objp->resok;
1321 1322
1322 1323 if (xdr_post_op_attr(xdrs, &resokp->file_attributes) == FALSE ||
1323 1324 xdr_u_int(xdrs, &resokp->count) == FALSE ||
1324 1325 xdr_bool(xdrs, &resokp->eof) == FALSE) {
1325 1326 return (FALSE);
1326 1327 }
1327 1328
1328 1329 if (xdrs->x_op == XDR_ENCODE) {
1329 1330
1330 1331 mp = resokp->data.mp;
1331 1332 if (mp != NULL) {
1332 1333 if (xdrs->x_ops == &xdrmblk_ops) {
1333 1334 if (xdrmblk_putmblk(xdrs, mp, resokp->count)) {
1334 1335 resokp->data.mp = NULL;
1335 1336 return (TRUE);
1336 1337 } else {
1337 1338 return (FALSE);
1338 1339 }
1339 1340 } else if (mp->b_cont != NULL) {
1340 1341 /*
1341 1342 * We have read results in an mblk chain, but
1342 1343 * the encoding operations don't handle mblks
1343 1344 * (they'll operate on data.data_val rather
1344 1345 * than data.mp). Because data_val can only
1345 1346 * point at a single data buffer, we need to
1346 1347 * pullup the read results into a single data
1347 1348 * block and reset data_val to point to it.
1348 1349 *
1349 1350 * This happens with RPC GSS where the wrapping
1350 1351 * function does XDR serialization into a
1351 1352 * temporary buffer prior to applying GSS.
1352 1353 * Because we're not in a performance sensitive
1353 1354 * path, the pullupmsg() here shouldn't hurt us
1354 1355 * too badly.
1355 1356 */
1356 1357 if (pullupmsg(mp, -1) == 0)
1357 1358 return (FALSE);
1358 1359 resokp->data.data_val = (caddr_t)mp->b_rptr;
1359 1360 }
1360 1361 } else {
1361 1362 if (xdr_u_int(xdrs, &resokp->count) == FALSE) {
1362 1363 return (FALSE);
1363 1364 }
1364 1365 /*
1365 1366 * If read data sent by wlist (RDMA_WRITE), don't do
1366 1367 * xdr_bytes() below. RDMA_WRITE transfers the data.
1367 1368 * Note: this is encode-only because the client code
1368 1369 * uses xdr_READ3vres/xdr_READ3uiores to decode results.
1369 1370 */
1370 1371 if (resokp->wlist) {
1371 1372 if (resokp->count != 0) {
1372 1373 return (xdrrdma_send_read_data(
1373 1374 xdrs, resokp->count,
1374 1375 resokp->wlist));
1375 1376 }
1376 1377 return (TRUE);
1377 1378 }
1378 1379 }
1379 1380 /*
1380 1381 * Fall thru for the xdr_bytes()
1381 1382 *
1382 1383 * note: the mblk will be freed in
1383 1384 * rfs3_read_free.
1384 1385 */
1385 1386 }
1386 1387
1387 1388 /* no RDMA_WRITE transfer -- send data inline */
1388 1389
1389 1390 ret = xdr_bytes(xdrs, (char **)&resokp->data.data_val,
1390 1391 &resokp->data.data_len, nfs3tsize());
1391 1392
1392 1393 return (ret);
1393 1394 }
1394 1395
1395 1396 bool_t
1396 1397 xdr_READ3vres(XDR *xdrs, READ3vres *objp)
1397 1398 {
1398 1399 count3 ocount;
1399 1400 /*
1400 1401 * DECODE or FREE only
1401 1402 */
1402 1403 if (xdrs->x_op == XDR_FREE)
1403 1404 return (TRUE);
1404 1405
1405 1406 if (xdrs->x_op != XDR_DECODE)
1406 1407 return (FALSE);
1407 1408
1408 1409 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1409 1410 return (FALSE);
1410 1411
1411 1412 if (!xdr_post_op_vattr(xdrs, &objp->pov))
1412 1413 return (FALSE);
1413 1414
1414 1415 if (objp->status != NFS3_OK)
1415 1416 return (TRUE);
1416 1417
1417 1418 if (!xdr_u_int(xdrs, &objp->count))
1418 1419 return (FALSE);
1419 1420
1420 1421 if (!xdr_bool(xdrs, &objp->eof))
1421 1422 return (FALSE);
1422 1423
1423 1424 /*
1424 1425 * If read data received via RDMA_WRITE, don't do xdr_bytes().
1425 1426 * RDMA_WRITE already moved the data so decode length of RDMA_WRITE.
1426 1427 */
1427 1428 if (xdrs->x_ops == &xdrrdma_ops) {
1428 1429 struct clist *cl;
1429 1430
1430 1431 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
1431 1432
1432 1433 if (cl) {
1433 1434 if (!xdr_u_int(xdrs, &ocount)) {
1434 1435 return (FALSE);
1435 1436 }
1436 1437 if (ocount != objp->count) {
1437 1438 DTRACE_PROBE2(xdr__e__read3vres_fail,
1438 1439 int, ocount, int, objp->count);
1439 1440 objp->wlist = NULL;
1440 1441 return (FALSE);
1441 1442 }
1442 1443
1443 1444 objp->wlist_len = clist_len(cl);
1444 1445 objp->data.data_len = ocount;
1445 1446
1446 1447 if (objp->wlist_len !=
1447 1448 roundup(objp->data.data_len, BYTES_PER_XDR_UNIT)) {
1448 1449 DTRACE_PROBE2(
1449 1450 xdr__e__read3vres_fail,
1450 1451 int, ocount,
1451 1452 int, objp->data.data_len);
1452 1453 objp->wlist = NULL;
1453 1454 return (FALSE);
1454 1455 }
1455 1456 return (TRUE);
1456 1457 }
1457 1458 }
1458 1459
1459 1460 return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1460 1461 &objp->data.data_len, nfs3tsize()));
1461 1462 }
1462 1463
1463 1464 bool_t
1464 1465 xdr_READ3uiores(XDR *xdrs, READ3uiores *objp)
1465 1466 {
1466 1467 count3 ocount;
1467 1468 bool_t attributes;
1468 1469 mblk_t *mp;
1469 1470 size_t n;
1470 1471 int error;
1471 1472 int size = (int)objp->size;
1472 1473 struct uio *uiop = objp->uiop;
1473 1474 int32_t fattr3_len = NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
1474 1475 int32_t *ptr;
1475 1476
1476 1477 /*
1477 1478 * DECODE or FREE only
1478 1479 */
1479 1480 if (xdrs->x_op == XDR_FREE)
1480 1481 return (TRUE);
1481 1482
1482 1483 if (xdrs->x_op != XDR_DECODE)
1483 1484 return (FALSE);
1484 1485
1485 1486 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
1486 1487 return (FALSE);
1487 1488
1488 1489 if (!XDR_GETINT32(xdrs, (int32_t *)&attributes))
1489 1490 return (FALSE);
1490 1491
1491 1492 /*
1492 1493 * For directio we just skip over attributes if present
1493 1494 */
1494 1495 switch (attributes) {
1495 1496 case TRUE:
1496 1497 if (!XDR_CONTROL(xdrs, XDR_SKIPBYTES, &fattr3_len))
1497 1498 return (FALSE);
1498 1499 break;
1499 1500 case FALSE:
1500 1501 break;
1501 1502 default:
1502 1503 return (FALSE);
1503 1504 }
1504 1505
1505 1506 if (objp->status != NFS3_OK)
1506 1507 return (TRUE);
1507 1508
1508 1509 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->count))
1509 1510 return (FALSE);
1510 1511
1511 1512 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
1512 1513 return (FALSE);
1513 1514
1514 1515 if (xdrs->x_ops == &xdrmblk_ops) {
1515 1516 if (!xdrmblk_getmblk(xdrs, &mp, &objp->size))
1516 1517 return (FALSE);
1517 1518
1518 1519 if (objp->size == 0)
1519 1520 return (TRUE);
1520 1521
1521 1522 if (objp->size > size)
1522 1523 return (FALSE);
1523 1524
1524 1525 size = (int)objp->size;
1525 1526 do {
1526 1527 n = MIN(size, mp->b_wptr - mp->b_rptr);
1527 1528 if ((n = MIN(uiop->uio_resid, n)) != 0) {
1528 1529
1529 1530 error = uiomove((char *)mp->b_rptr, n, UIO_READ,
1530 1531 uiop);
1531 1532 if (error)
1532 1533 return (FALSE);
1533 1534 mp->b_rptr += n;
1534 1535 size -= n;
1535 1536 }
1536 1537
1537 1538 while (mp && (mp->b_rptr >= mp->b_wptr))
1538 1539 mp = mp->b_cont;
1539 1540 } while (mp && size > 0 && uiop->uio_resid > 0);
1540 1541
1541 1542 return (TRUE);
1542 1543 }
1543 1544
1544 1545 if (xdrs->x_ops == &xdrrdma_ops) {
1545 1546 struct clist *cl;
1546 1547
1547 1548 XDR_CONTROL(xdrs, XDR_RDMA_GET_WLIST, &cl);
1548 1549
1549 1550 objp->wlist = cl;
1550 1551
1551 1552 if (objp->wlist) {
1552 1553 if (!xdr_u_int(xdrs, &ocount)) {
1553 1554 objp->wlist = NULL;
1554 1555 return (FALSE);
1555 1556 }
1556 1557
1557 1558 if (ocount != objp->count) {
1558 1559 DTRACE_PROBE2(xdr__e__read3uiores_fail,
1559 1560 int, ocount, int, objp->count);
1560 1561 objp->wlist = NULL;
1561 1562 return (FALSE);
1562 1563 }
1563 1564
1564 1565 objp->wlist_len = clist_len(cl);
1565 1566
1566 1567 uiop->uio_resid -= objp->count;
1567 1568 uiop->uio_iov->iov_len -= objp->count;
1568 1569 uiop->uio_iov->iov_base += objp->count;
1569 1570 uiop->uio_loffset += objp->count;
1570 1571
1571 1572 /*
1572 1573 * XXX: Assume 1 iov, needs to be changed.
1573 1574 */
1574 1575 objp->size = objp->count;
1575 1576
1576 1577 return (TRUE);
1577 1578 }
1578 1579 }
1579 1580
1580 1581 /*
1581 1582 * This isn't an xdrmblk stream nor RDMA.
1582 1583 * Handle the likely case that it can be
1583 1584 * inlined (ex. xdrmem).
1584 1585 */
1585 1586 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->size))
1586 1587 return (FALSE);
1587 1588
1588 1589 if (objp->size == 0)
1589 1590 return (TRUE);
1590 1591
1591 1592 if (objp->size > size)
1592 1593 return (FALSE);
1593 1594
1594 1595 size = (int)objp->size;
1595 1596 if ((ptr = XDR_INLINE(xdrs, size)) != NULL)
1596 1597 return (uiomove(ptr, size, UIO_READ, uiop) ? FALSE : TRUE);
1597 1598
1598 1599 /*
1599 1600 * Handle some other (unlikely) stream type that will need a copy.
1600 1601 */
1601 1602 if ((ptr = kmem_alloc(size, KM_NOSLEEP)) == NULL)
1602 1603 return (FALSE);
1603 1604
1604 1605 if (!XDR_GETBYTES(xdrs, (caddr_t)ptr, size)) {
1605 1606 kmem_free(ptr, size);
1606 1607 return (FALSE);
1607 1608 }
1608 1609 error = uiomove(ptr, size, UIO_READ, uiop);
1609 1610 kmem_free(ptr, size);
1610 1611
1611 1612 return (error ? FALSE : TRUE);
1612 1613 }
1613 1614
1614 1615 bool_t
1615 1616 xdr_WRITE3args(XDR *xdrs, WRITE3args *objp)
1616 1617 {
1617 1618 switch (xdrs->x_op) {
1618 1619 case XDR_FREE:
1619 1620 case XDR_ENCODE:
1620 1621 if (!xdr_nfs_fh3(xdrs, &objp->file))
1621 1622 return (FALSE);
1622 1623 break;
1623 1624 case XDR_DECODE:
1624 1625 if (!xdr_nfs_fh3_server(xdrs, &objp->file))
1625 1626 return (FALSE);
1626 1627 break;
1627 1628 }
1628 1629 if (!xdr_u_longlong_t(xdrs, &objp->offset))
1629 1630 return (FALSE);
1630 1631 if (!xdr_u_int(xdrs, &objp->count))
1631 1632 return (FALSE);
1632 1633 if (!xdr_enum(xdrs, (enum_t *)&objp->stable))
1633 1634 return (FALSE);
1634 1635
1635 1636 if (xdrs->x_op == XDR_DECODE) {
1636 1637 if (xdrs->x_ops == &xdrmblk_ops) {
1637 1638 if (xdrmblk_getmblk(xdrs, &objp->mblk,
1638 1639 &objp->data.data_len) == TRUE) {
1639 1640 objp->data.data_val = NULL;
1640 1641 return (TRUE);
1641 1642 }
1642 1643 }
1643 1644 objp->mblk = NULL;
1644 1645
1645 1646 if (xdrs->x_ops == &xdrrdmablk_ops) {
1646 1647 if (xdrrdma_getrdmablk(xdrs, &objp->rlist,
1647 1648 &objp->data.data_len,
1648 1649 &objp->conn, nfs3tsize()) == TRUE) {
1649 1650 objp->data.data_val = NULL;
1650 1651 if (xdrrdma_read_from_client(
1651 1652 objp->rlist,
1652 1653 &objp->conn,
1653 1654 objp->count) == FALSE) {
1654 1655 return (FALSE);
1655 1656 }
1656 1657 return (TRUE);
1657 1658 }
1658 1659 }
1659 1660 objp->rlist = NULL;
1660 1661
1661 1662 /* Else fall thru for the xdr_bytes(). */
1662 1663 }
1663 1664
1664 1665 if (xdrs->x_op == XDR_FREE) {
1665 1666 if (objp->rlist != NULL) {
1666 1667 (void) xdrrdma_free_clist(objp->conn, objp->rlist);
1667 1668 objp->rlist = NULL;
1668 1669 objp->data.data_val = NULL;
1669 1670 return (TRUE);
1670 1671 }
1671 1672 }
1672 1673
1673 1674 DTRACE_PROBE1(xdr__i__write3_buf_len,
1674 1675 int, objp->data.data_len);
1675 1676
1676 1677 return (xdr_bytes(xdrs, (char **)&objp->data.data_val,
1677 1678 &objp->data.data_len, nfs3tsize()));
1678 1679 }
1679 1680
1680 1681 bool_t
1681 1682 xdr_WRITE3res(XDR *xdrs, WRITE3res *objp)
1682 1683 {
1683 1684 WRITE3resok *resokp;
1684 1685
1685 1686 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1686 1687 return (FALSE);
1687 1688 if (objp->status != NFS3_OK) /* xdr_WRITE3resfail */
1688 1689 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
1689 1690
1690 1691 /* xdr_WRITE3resok */
1691 1692 resokp = &objp->resok;
1692 1693 if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
1693 1694 return (FALSE);
1694 1695 if (!xdr_u_int(xdrs, &resokp->count))
1695 1696 return (FALSE);
1696 1697 if (!xdr_enum(xdrs, (enum_t *)&resokp->committed))
1697 1698 return (FALSE);
1698 1699 /*
1699 1700 * writeverf3 is really an opaque 8 byte
1700 1701 * quantity, but we will treat it as a
1701 1702 * hyper for efficiency, the cost of
1702 1703 * a byteswap here saves bcopys elsewhere
1703 1704 */
1704 1705 return (xdr_u_longlong_t(xdrs, &resokp->verf));
1705 1706 }
1706 1707
1707 1708 bool_t
1708 1709 xdr_CREATE3args(XDR *xdrs, CREATE3args *objp)
1709 1710 {
1710 1711 createhow3 *howp;
1711 1712
1712 1713 if (!xdr_diropargs3(xdrs, &objp->where))
1713 1714 return (FALSE);
1714 1715
1715 1716 /* xdr_createhow3 */
1716 1717 howp = &objp->how;
1717 1718
1718 1719 if (!xdr_enum(xdrs, (enum_t *)&howp->mode))
1719 1720 return (FALSE);
1720 1721 switch (howp->mode) {
1721 1722 case UNCHECKED:
1722 1723 case GUARDED:
1723 1724 return (xdr_sattr3(xdrs, &howp->createhow3_u.obj_attributes));
1724 1725 case EXCLUSIVE:
1725 1726 /*
1726 1727 * createverf3 is really an opaque 8 byte
1727 1728 * quantity, but we will treat it as a
1728 1729 * hyper for efficiency, the cost of
1729 1730 * a byteswap here saves bcopys elsewhere
1730 1731 */
1731 1732 return (xdr_u_longlong_t(xdrs, &howp->createhow3_u.verf));
1732 1733 default:
1733 1734 return (FALSE);
1734 1735 }
1735 1736 }
1736 1737
1737 1738 bool_t
1738 1739 xdr_CREATE3res(XDR *xdrs, CREATE3res *objp)
1739 1740 {
1740 1741 CREATE3resok *resokp;
1741 1742
1742 1743 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1743 1744 return (FALSE);
1744 1745 switch (objp->status) {
1745 1746 case NFS3_OK:
1746 1747 /* xdr_CREATE3resok */
1747 1748 resokp = &objp->resok;
1748 1749
1749 1750 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1750 1751 return (FALSE);
1751 1752 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1752 1753 return (FALSE);
1753 1754 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1754 1755 default:
1755 1756 /* xdr_CREATE3resfail */
1756 1757 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1757 1758 }
1758 1759 }
1759 1760
1760 1761 bool_t
1761 1762 xdr_MKDIR3args(XDR *xdrs, MKDIR3args *objp)
1762 1763 {
1763 1764 if (!xdr_diropargs3(xdrs, &objp->where))
1764 1765 return (FALSE);
1765 1766 return (xdr_sattr3(xdrs, &objp->attributes));
1766 1767 }
1767 1768
1768 1769 bool_t
1769 1770 xdr_MKDIR3res(XDR *xdrs, MKDIR3res *objp)
1770 1771 {
1771 1772 MKDIR3resok *resokp;
1772 1773
1773 1774 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1774 1775 return (FALSE);
1775 1776 switch (objp->status) {
1776 1777 case NFS3_OK:
1777 1778 /* xdr_MKDIR3resok */
1778 1779 resokp = &objp->resok;
1779 1780
1780 1781 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1781 1782 return (FALSE);
1782 1783 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1783 1784 return (FALSE);
1784 1785 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1785 1786 default:
1786 1787 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1787 1788 }
1788 1789 }
1789 1790
1790 1791 bool_t
1791 1792 xdr_SYMLINK3args(XDR *xdrs, SYMLINK3args *objp)
1792 1793 {
1793 1794 if (!xdr_diropargs3(xdrs, &objp->where))
1794 1795 return (FALSE);
1795 1796 if (!xdr_sattr3(xdrs, &objp->symlink.symlink_attributes))
1796 1797 return (FALSE);
1797 1798 return (xdr_string3(xdrs, &objp->symlink.symlink_data, MAXPATHLEN));
1798 1799 }
1799 1800
1800 1801 bool_t
1801 1802 xdr_SYMLINK3res(XDR *xdrs, SYMLINK3res *objp)
1802 1803 {
1803 1804 SYMLINK3resok *resokp;
1804 1805
1805 1806 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1806 1807 return (FALSE);
1807 1808 switch (objp->status) {
1808 1809 case NFS3_OK:
1809 1810 resokp = &objp->resok;
1810 1811 /* xdr_SYMLINK3resok */
1811 1812 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1812 1813 return (FALSE);
1813 1814 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1814 1815 return (FALSE);
1815 1816 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1816 1817 default:
1817 1818 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1818 1819 }
1819 1820 }
1820 1821
1821 1822 bool_t
1822 1823 xdr_MKNOD3args(XDR *xdrs, MKNOD3args *objp)
1823 1824 {
1824 1825 mknoddata3 *whatp;
1825 1826 devicedata3 *nod_objp;
1826 1827
1827 1828 if (!xdr_diropargs3(xdrs, &objp->where))
1828 1829 return (FALSE);
1829 1830
1830 1831 whatp = &objp->what;
1831 1832 if (!xdr_enum(xdrs, (enum_t *)&whatp->type))
1832 1833 return (FALSE);
1833 1834 switch (whatp->type) {
1834 1835 case NF3CHR:
1835 1836 case NF3BLK:
1836 1837 /* xdr_devicedata3 */
1837 1838 nod_objp = &whatp->mknoddata3_u.device;
1838 1839 if (!xdr_sattr3(xdrs, &nod_objp->dev_attributes))
1839 1840 return (FALSE);
1840 1841 if (!xdr_u_int(xdrs, &nod_objp->spec.specdata1))
1841 1842 return (FALSE);
1842 1843 return (xdr_u_int(xdrs, &nod_objp->spec.specdata2));
1843 1844 case NF3SOCK:
1844 1845 case NF3FIFO:
1845 1846 return (xdr_sattr3(xdrs, &whatp->mknoddata3_u.pipe_attributes));
1846 1847 default:
1847 1848 break;
1848 1849 }
1849 1850 return (TRUE);
1850 1851 }
1851 1852
1852 1853 bool_t
1853 1854 xdr_MKNOD3res(XDR *xdrs, MKNOD3res *objp)
1854 1855 {
1855 1856 MKNOD3resok *resokp;
1856 1857
1857 1858 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1858 1859 return (FALSE);
1859 1860 switch (objp->status) {
1860 1861 case NFS3_OK:
1861 1862 /* xdr_MKNOD3resok */
1862 1863 resokp = &objp->resok;
1863 1864 if (!xdr_post_op_fh3(xdrs, &resokp->obj))
1864 1865 return (FALSE);
1865 1866 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
1866 1867 return (FALSE);
1867 1868 return (xdr_wcc_data(xdrs, &resokp->dir_wcc));
1868 1869 default:
1869 1870 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1870 1871 }
1871 1872 }
1872 1873
1873 1874 bool_t
1874 1875 xdr_REMOVE3res(XDR *xdrs, REMOVE3res *objp)
1875 1876 {
1876 1877 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1877 1878 return (FALSE);
1878 1879 switch (objp->status) {
1879 1880 case NFS3_OK:
1880 1881 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1881 1882 default:
1882 1883 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1883 1884 }
1884 1885 }
1885 1886
1886 1887 bool_t
1887 1888 xdr_RMDIR3res(XDR *xdrs, RMDIR3res *objp)
1888 1889 {
1889 1890 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1890 1891 return (FALSE);
1891 1892 switch (objp->status) {
1892 1893 case NFS3_OK:
1893 1894 return (xdr_wcc_data(xdrs, &objp->resok.dir_wcc));
1894 1895 default:
1895 1896 return (xdr_wcc_data(xdrs, &objp->resfail.dir_wcc));
1896 1897 }
1897 1898 }
1898 1899
1899 1900 bool_t
1900 1901 xdr_RENAME3args(XDR *xdrs, RENAME3args *objp)
1901 1902 {
1902 1903 if (!xdr_diropargs3(xdrs, &objp->from))
1903 1904 return (FALSE);
1904 1905 return (xdr_diropargs3(xdrs, &objp->to));
1905 1906 }
1906 1907
1907 1908 bool_t
1908 1909 xdr_RENAME3res(XDR *xdrs, RENAME3res *objp)
1909 1910 {
1910 1911 RENAME3resok *resokp;
1911 1912 RENAME3resfail *resfailp;
1912 1913
1913 1914 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1914 1915 return (FALSE);
1915 1916 switch (objp->status) {
1916 1917 case NFS3_OK:
1917 1918 /* xdr_RENAME3resok */
1918 1919 resokp = &objp->resok;
1919 1920
1920 1921 if (!xdr_wcc_data(xdrs, &resokp->fromdir_wcc))
1921 1922 return (FALSE);
1922 1923 return (xdr_wcc_data(xdrs, &resokp->todir_wcc));
1923 1924 default:
1924 1925 /* xdr_RENAME3resfail */
1925 1926 resfailp = &objp->resfail;
1926 1927 if (!xdr_wcc_data(xdrs, &resfailp->fromdir_wcc))
1927 1928 return (FALSE);
1928 1929 return (xdr_wcc_data(xdrs, &resfailp->todir_wcc));
1929 1930 }
1930 1931 }
1931 1932
1932 1933 bool_t
1933 1934 xdr_LINK3args(XDR *xdrs, LINK3args *objp)
1934 1935 {
1935 1936 switch (xdrs->x_op) {
1936 1937 case XDR_FREE:
1937 1938 case XDR_ENCODE:
1938 1939 if (!xdr_nfs_fh3(xdrs, &objp->file))
1939 1940 return (FALSE);
1940 1941 break;
1941 1942 case XDR_DECODE:
1942 1943 if (!xdr_nfs_fh3_server(xdrs, &objp->file))
1943 1944 return (FALSE);
1944 1945 break;
1945 1946 }
1946 1947 return (xdr_diropargs3(xdrs, &objp->link));
1947 1948 }
1948 1949
1949 1950 bool_t
1950 1951 xdr_LINK3res(XDR *xdrs, LINK3res *objp)
1951 1952 {
1952 1953 LINK3resok *resokp;
1953 1954 LINK3resfail *resfailp;
1954 1955
1955 1956 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
1956 1957 return (FALSE);
1957 1958 switch (objp->status) {
1958 1959 case NFS3_OK:
1959 1960 /* xdr_LINK3resok */
1960 1961 resokp = &objp->resok;
1961 1962 if (!xdr_post_op_attr(xdrs, &resokp->file_attributes))
1962 1963 return (FALSE);
1963 1964 return (xdr_wcc_data(xdrs, &resokp->linkdir_wcc));
1964 1965 default:
1965 1966 /* xdr_LINK3resfail */
1966 1967 resfailp = &objp->resfail;
1967 1968 if (!xdr_post_op_attr(xdrs, &resfailp->file_attributes))
1968 1969 return (FALSE);
1969 1970 return (xdr_wcc_data(xdrs, &resfailp->linkdir_wcc));
1970 1971 }
1971 1972 }
1972 1973
1973 1974 bool_t
1974 1975 xdr_READDIR3args(XDR *xdrs, READDIR3args *objp)
1975 1976 {
1976 1977 rdma_chunkinfo_t rci;
1977 1978 struct xdr_ops *xops = xdrrdma_xops();
1978 1979
1979 1980 if (xdrs->x_op == XDR_FREE)
1980 1981 return (TRUE);
1981 1982
1982 1983 switch (xdrs->x_op) {
1983 1984 case XDR_FREE:
1984 1985 case XDR_ENCODE:
1985 1986 if (!xdr_nfs_fh3(xdrs, &objp->dir))
1986 1987 return (FALSE);
1987 1988 break;
1988 1989 case XDR_DECODE:
1989 1990 if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
1990 1991 return (FALSE);
1991 1992 break;
1992 1993 }
1993 1994 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
1994 1995 xdrs->x_op == XDR_ENCODE) {
1995 1996 rci.rci_type = RCI_REPLY_CHUNK;
1996 1997 rci.rci_len = objp->count;
1997 1998 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
1998 1999 }
1999 2000
2000 2001 if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2001 2002 return (FALSE);
2002 2003 /*
|
↓ open down ↓ |
1962 lines elided |
↑ open up ↑ |
2003 2004 * cookieverf is really an opaque 8 byte
2004 2005 * quantity, but we will treat it as a
2005 2006 * hyper for efficiency, the cost of
2006 2007 * a byteswap here saves bcopys elsewhere
2007 2008 */
2008 2009 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2009 2010 return (FALSE);
2010 2011 return (xdr_u_int(xdrs, &objp->count));
2011 2012 }
2012 2013
2013 -#ifdef nextdp
2014 -#undef nextdp
2015 -#endif
2016 -#define nextdp(dp) ((struct dirent64 *)((char *)(dp) + (dp)->d_reclen))
2017 -#ifdef roundup
2018 -#undef roundup
2019 -#endif
2020 -#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
2021 -
2022 2014 /*
2023 2015 * ENCODE ONLY
2024 2016 */
2025 2017 static bool_t
2026 2018 xdr_putdirlist(XDR *xdrs, READDIR3resok *objp)
2027 2019 {
2028 - struct dirent64 *dp;
2029 - char *name;
2030 - int size;
2031 - int bufsize;
2032 - uint_t namlen;
2033 2020 bool_t true = TRUE;
2034 2021 bool_t false = FALSE;
2035 - int entrysz;
2036 - int tofit;
2037 - fileid3 fileid;
2038 - cookie3 cookie;
2022 + entry3 *entry;
2039 2023
2040 2024 if (xdrs->x_op != XDR_ENCODE)
2041 2025 return (FALSE);
2042 2026
2043 - /*
2044 - * bufsize is used to keep track of the size of the response.
2045 - * It is primed with:
2046 - * 1 for the status +
2047 - * 1 for the dir_attributes.attributes boolean +
2048 - * 2 for the cookie verifier
2049 - * all times BYTES_PER_XDR_UNIT to convert from XDR units
2050 - * to bytes. If there are directory attributes to be
2051 - * returned, then:
2052 - * NFS3_SIZEOF_FATTR3 for the dir_attributes.attr fattr3
2053 - * time BYTES_PER_XDR_UNIT is added to account for them.
2054 - */
2055 - bufsize = (1 + 1 + 2) * BYTES_PER_XDR_UNIT;
2056 - if (objp->dir_attributes.attributes)
2057 - bufsize += NFS3_SIZEOF_FATTR3 * BYTES_PER_XDR_UNIT;
2058 - for (size = objp->size, dp = (struct dirent64 *)objp->reply.entries;
2059 - size > 0;
2060 - size -= dp->d_reclen, dp = nextdp(dp)) {
2061 - if (dp->d_reclen == 0)
2062 - return (FALSE);
2063 - if (dp->d_ino == 0)
2064 - continue;
2065 - name = dp->d_name;
2066 - namlen = (uint_t)strlen(dp->d_name);
2067 - /*
2068 - * An entry is composed of:
2069 - * 1 for the true/false list indicator +
2070 - * 2 for the fileid +
2071 - * 1 for the length of the name +
2072 - * 2 for the cookie +
2073 - * all times BYTES_PER_XDR_UNIT to convert from
2074 - * XDR units to bytes, plus the length of the name
2075 - * rounded up to the nearest BYTES_PER_XDR_UNIT.
2076 - */
2077 - entrysz = (1 + 2 + 1 + 2) * BYTES_PER_XDR_UNIT +
2078 - roundup(namlen, BYTES_PER_XDR_UNIT);
2079 - /*
2080 - * We need to check to see if the number of bytes left
2081 - * to go into the buffer will actually fit into the
2082 - * buffer. This is calculated as the size of this
2083 - * entry plus:
2084 - * 1 for the true/false list indicator +
2085 - * 1 for the eof indicator
2086 - * times BYTES_PER_XDR_UNIT to convert from from
2087 - * XDR units to bytes.
2088 - */
2089 - tofit = entrysz + (1 + 1) * BYTES_PER_XDR_UNIT;
2090 - if (bufsize + tofit > objp->count) {
2091 - objp->reply.eof = FALSE;
2092 - break;
2093 - }
2094 - fileid = (fileid3)(dp->d_ino);
2095 - cookie = (cookie3)(dp->d_off);
2027 + for (entry = objp->reply.entries; entry != NULL;
2028 + entry = entry->nextentry) {
2096 2029 if (!xdr_bool(xdrs, &true) ||
2097 - !xdr_u_longlong_t(xdrs, &fileid) ||
2098 - !xdr_bytes(xdrs, &name, &namlen, ~0) ||
2099 - !xdr_u_longlong_t(xdrs, &cookie)) {
2030 + !xdr_u_longlong_t(xdrs, &entry->fileid) ||
2031 + !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
2032 + !xdr_u_longlong_t(xdrs, &entry->cookie)) {
2100 2033 return (FALSE);
2101 2034 }
2102 - bufsize += entrysz;
2103 2035 }
2036 +
2104 2037 if (!xdr_bool(xdrs, &false))
2105 2038 return (FALSE);
2106 2039 if (!xdr_bool(xdrs, &objp->reply.eof))
2107 2040 return (FALSE);
2108 2041 return (TRUE);
2109 2042 }
2110 2043
2111 2044 bool_t
2112 2045 xdr_READDIR3res(XDR *xdrs, READDIR3res *objp)
2113 2046 {
2114 2047 READDIR3resok *resokp;
2115 2048
2116 2049 /*
2117 2050 * ENCODE or FREE only
2118 2051 */
2119 2052 if (xdrs->x_op == XDR_DECODE)
2120 2053 return (FALSE);
2121 2054
2122 2055 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2123 2056 return (FALSE);
2124 2057 if (objp->status != NFS3_OK)
2125 2058 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2126 2059
2127 2060 /* xdr_READDIR3resok */
2128 2061 resokp = &objp->resok;
2129 2062 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2130 2063 return (FALSE);
2131 2064 if (xdrs->x_op != XDR_ENCODE)
2132 2065 return (TRUE);
2133 2066 /*
2134 2067 * cookieverf is really an opaque 8 byte
2135 2068 * quantity, but we will treat it as a
2136 2069 * hyper for efficiency, the cost of
2137 2070 * a byteswap here saves bcopys elsewhere
2138 2071 */
2139 2072 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2140 2073 return (FALSE);
2141 2074 return (xdr_putdirlist(xdrs, resokp));
2142 2075 }
2143 2076
2144 2077 bool_t
2145 2078 xdr_READDIR3vres(XDR *xdrs, READDIR3vres *objp)
2146 2079 {
2147 2080 dirent64_t *dp;
2148 2081 uint_t entries_size;
2149 2082 int outcount = 0;
2150 2083
2151 2084 /*
2152 2085 * DECODE or FREE only
2153 2086 */
2154 2087 if (xdrs->x_op == XDR_FREE)
2155 2088 return (TRUE);
2156 2089
2157 2090 if (xdrs->x_op != XDR_DECODE)
2158 2091 return (FALSE);
2159 2092
2160 2093 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2161 2094 return (FALSE);
2162 2095
2163 2096 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2164 2097 return (FALSE);
2165 2098
2166 2099 if (objp->status != NFS3_OK)
2167 2100 return (TRUE);
2168 2101
2169 2102 /*
2170 2103 * cookieverf is really an opaque 8 byte
2171 2104 * quantity, but we will treat it as a
2172 2105 * hyper for efficiency, the cost of
2173 2106 * a byteswap here saves bcopys elsewhere
2174 2107 */
2175 2108 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2176 2109 return (FALSE);
2177 2110
2178 2111 entries_size = objp->entries_size;
2179 2112 dp = objp->entries;
2180 2113
2181 2114 for (;;) {
2182 2115 uint_t this_reclen;
2183 2116 bool_t valid;
2184 2117 uint_t namlen;
2185 2118 ino64_t fileid;
2186 2119
2187 2120 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2188 2121 return (FALSE);
2189 2122 if (!valid) {
2190 2123 /*
2191 2124 * We have run out of entries, decode eof.
2192 2125 */
2193 2126 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2194 2127 return (FALSE);
2195 2128
2196 2129 break;
2197 2130 }
2198 2131
2199 2132 /*
2200 2133 * fileid3 fileid
2201 2134 */
2202 2135 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2203 2136 return (FALSE);
2204 2137
2205 2138 /*
2206 2139 * filename3 name
2207 2140 */
2208 2141 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2209 2142 return (FALSE);
2210 2143 this_reclen = DIRENT64_RECLEN(namlen);
2211 2144
2212 2145 /*
2213 2146 * If this will overflow buffer, stop decoding
2214 2147 */
2215 2148 if ((outcount + this_reclen) > entries_size) {
2216 2149 objp->eof = FALSE;
2217 2150 break;
2218 2151 }
2219 2152 dp->d_reclen = this_reclen;
2220 2153 dp->d_ino = fileid;
2221 2154
2222 2155 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2223 2156 return (FALSE);
2224 2157 bzero(&dp->d_name[namlen],
2225 2158 DIRENT64_NAMELEN(this_reclen) - namlen);
2226 2159
2227 2160 /*
2228 2161 * cookie3 cookie
2229 2162 */
2230 2163 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2231 2164 return (FALSE);
2232 2165 objp->loff = dp->d_off;
2233 2166
2234 2167 outcount += this_reclen;
2235 2168 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2236 2169 }
2237 2170
2238 2171 objp->size = outcount;
2239 2172 return (TRUE);
2240 2173 }
2241 2174
2242 2175 bool_t
2243 2176 xdr_READDIRPLUS3args(XDR *xdrs, READDIRPLUS3args *objp)
2244 2177 {
2245 2178 rdma_chunkinfo_t rci;
2246 2179 struct xdr_ops *xops = xdrrdma_xops();
2247 2180
2248 2181 if (xdrs->x_op == XDR_FREE)
2249 2182 return (TRUE);
2250 2183
2251 2184 switch (xdrs->x_op) {
2252 2185 case XDR_FREE:
2253 2186 case XDR_ENCODE:
2254 2187 if (!xdr_nfs_fh3(xdrs, &objp->dir))
2255 2188 return (FALSE);
2256 2189 break;
2257 2190 case XDR_DECODE:
2258 2191 if (!xdr_nfs_fh3_server(xdrs, &objp->dir))
2259 2192 return (FALSE);
2260 2193 break;
2261 2194 }
2262 2195 if ((xdrs->x_ops == &xdrrdma_ops || xdrs->x_ops == xops) &&
2263 2196 xdrs->x_op == XDR_ENCODE) {
2264 2197 rci.rci_type = RCI_REPLY_CHUNK;
2265 2198 rci.rci_len = objp->maxcount;
2266 2199 XDR_CONTROL(xdrs, XDR_RDMA_ADD_CHUNK, &rci);
2267 2200 }
2268 2201
2269 2202 if (!xdr_u_longlong_t(xdrs, &objp->cookie))
2270 2203 return (FALSE);
2271 2204 /*
2272 2205 * cookieverf is really an opaque 8 byte
2273 2206 * quantity, but we will treat it as a
2274 2207 * hyper for efficiency, the cost of
2275 2208 * a byteswap here saves bcopys elsewhere
2276 2209 */
2277 2210 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2278 2211 return (FALSE);
2279 2212 if (!xdr_u_int(xdrs, &objp->dircount))
|
↓ open down ↓ |
166 lines elided |
↑ open up ↑ |
2280 2213 return (FALSE);
2281 2214 return (xdr_u_int(xdrs, &objp->maxcount));
2282 2215 }
2283 2216
2284 2217 /*
2285 2218 * ENCODE ONLY
2286 2219 */
2287 2220 static bool_t
2288 2221 xdr_putdirpluslist(XDR *xdrs, READDIRPLUS3resok *objp)
2289 2222 {
2290 - struct dirent64 *dp;
2291 - char *name;
2292 - int nents;
2293 2223 bool_t true = TRUE;
2294 2224 bool_t false = FALSE;
2295 - fileid3 fileid;
2296 - cookie3 cookie;
2297 - entryplus3_info *infop;
2225 + entryplus3 *entry;
2298 2226
2299 2227 if (xdrs->x_op != XDR_ENCODE)
2300 2228 return (FALSE);
2301 2229
2302 - dp = (struct dirent64 *)objp->reply.entries;
2303 - nents = objp->size;
2304 - infop = objp->infop;
2305 -
2306 - while (nents > 0) {
2307 - if (dp->d_reclen == 0)
2230 + for (entry = objp->reply.entries; entry != NULL;
2231 + entry = entry->nextentry) {
2232 + if (!xdr_bool(xdrs, &true) ||
2233 + !xdr_u_longlong_t(xdrs, &entry->fileid) ||
2234 + !xdr_string(xdrs, &entry->name, MAXPATHLEN) ||
2235 + !xdr_u_longlong_t(xdrs, &entry->cookie) ||
2236 + !xdr_post_op_attr(xdrs, &entry->name_attributes) ||
2237 + !xdr_post_op_fh3(xdrs, &entry->name_handle)) {
2308 2238 return (FALSE);
2309 - if (dp->d_ino != 0) {
2310 - name = dp->d_name;
2311 - fileid = (fileid3)(dp->d_ino);
2312 - cookie = (cookie3)(dp->d_off);
2313 - if (!xdr_bool(xdrs, &true) ||
2314 - !xdr_u_longlong_t(xdrs, &fileid) ||
2315 - !xdr_bytes(xdrs, &name, &infop->namelen, ~0) ||
2316 - !xdr_u_longlong_t(xdrs, &cookie) ||
2317 - !xdr_post_op_attr(xdrs, &infop->attr) ||
2318 - !xdr_post_op_fh3(xdrs, &infop->fh)) {
2319 - return (FALSE);
2320 - }
2321 2239 }
2322 - dp = nextdp(dp);
2323 - infop++;
2324 - nents--;
2325 2240 }
2326 2241
2327 2242 if (!xdr_bool(xdrs, &false))
2328 2243 return (FALSE);
2329 2244 if (!xdr_bool(xdrs, &objp->reply.eof))
2330 2245 return (FALSE);
2331 2246 return (TRUE);
2332 2247 }
2333 2248
2334 2249 bool_t
2335 2250 xdr_READDIRPLUS3res(XDR *xdrs, READDIRPLUS3res *objp)
2336 2251 {
2337 2252 READDIRPLUS3resok *resokp;
2338 2253
2339 2254 /*
2340 2255 * ENCODE or FREE only
2341 2256 */
2342 2257 if (xdrs->x_op == XDR_DECODE)
2343 2258 return (FALSE);
2344 2259
2345 2260 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2346 2261 return (FALSE);
2347 2262 switch (objp->status) {
2348 2263 case NFS3_OK:
2349 2264 /* xdr_READDIRPLUS3resok */
2350 2265 resokp = &objp->resok;
2351 2266 if (!xdr_post_op_attr(xdrs, &resokp->dir_attributes))
2352 2267 return (FALSE);
2353 2268 /*
2354 2269 * cookieverf is really an opaque 8 byte
2355 2270 * quantity, but we will treat it as a
2356 2271 * hyper for efficiency, the cost of
2357 2272 * a byteswap here saves bcopys elsewhere
2358 2273 */
2359 2274 if (!xdr_u_longlong_t(xdrs, &resokp->cookieverf))
2360 2275 return (FALSE);
2361 2276 if (xdrs->x_op == XDR_ENCODE) {
2362 2277 if (!xdr_putdirpluslist(xdrs, resokp))
2363 2278 return (FALSE);
2364 2279 }
2365 2280 break;
2366 2281 default:
2367 2282 return (xdr_post_op_attr(xdrs, &objp->resfail.dir_attributes));
2368 2283 }
2369 2284 return (TRUE);
2370 2285 }
2371 2286
2372 2287 /*
2373 2288 * Decode readdirplus directly into a dirent64_t and do the DNLC caching.
2374 2289 */
2375 2290 bool_t
2376 2291 xdr_READDIRPLUS3vres(XDR *xdrs, READDIRPLUS3vres *objp)
2377 2292 {
2378 2293 dirent64_t *dp;
2379 2294 vnode_t *dvp;
2380 2295 uint_t entries_size;
2381 2296 int outcount = 0;
2382 2297 vnode_t *nvp;
2383 2298 rnode_t *rp;
2384 2299 post_op_vattr pov;
2385 2300 vattr_t va;
2386 2301
2387 2302 /*
2388 2303 * DECODE or FREE only
2389 2304 */
2390 2305 if (xdrs->x_op == XDR_FREE)
2391 2306 return (TRUE);
2392 2307
2393 2308 if (xdrs->x_op != XDR_DECODE)
2394 2309 return (FALSE);
2395 2310
2396 2311 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->status))
2397 2312 return (FALSE);
2398 2313
2399 2314 if (!xdr_post_op_vattr(xdrs, &objp->dir_attributes))
2400 2315 return (FALSE);
2401 2316
2402 2317 if (objp->status != NFS3_OK)
2403 2318 return (TRUE);
2404 2319
2405 2320 /*
2406 2321 * cookieverf is really an opaque 8 byte
2407 2322 * quantity, but we will treat it as a
2408 2323 * hyper for efficiency, the cost of
2409 2324 * a byteswap here saves bcopys elsewhere
2410 2325 */
2411 2326 if (!xdr_u_longlong_t(xdrs, &objp->cookieverf))
2412 2327 return (FALSE);
2413 2328
2414 2329 dvp = objp->dir_attributes.fres.vp;
2415 2330 rp = VTOR(dvp);
2416 2331
2417 2332 pov.fres.vap = &va;
2418 2333 pov.fres.vp = dvp;
2419 2334
2420 2335 entries_size = objp->entries_size;
2421 2336 dp = objp->entries;
2422 2337
2423 2338 for (;;) {
2424 2339 uint_t this_reclen;
2425 2340 bool_t valid;
2426 2341 uint_t namlen;
2427 2342 nfs_fh3 fh;
2428 2343 int va_valid;
2429 2344 int fh_valid;
2430 2345 ino64_t fileid;
2431 2346
2432 2347 if (!XDR_GETINT32(xdrs, (int32_t *)&valid))
2433 2348 return (FALSE);
2434 2349 if (!valid) {
2435 2350 /*
2436 2351 * We have run out of entries, decode eof.
2437 2352 */
2438 2353 if (!XDR_GETINT32(xdrs, (int32_t *)&objp->eof))
2439 2354 return (FALSE);
2440 2355
2441 2356 break;
2442 2357 }
2443 2358
2444 2359 /*
2445 2360 * fileid3 fileid
2446 2361 */
2447 2362 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&fileid))
2448 2363 return (FALSE);
2449 2364
2450 2365 /*
2451 2366 * filename3 name
2452 2367 */
2453 2368 if (!XDR_GETINT32(xdrs, (int32_t *)&namlen))
2454 2369 return (FALSE);
2455 2370 this_reclen = DIRENT64_RECLEN(namlen);
2456 2371
2457 2372 /*
2458 2373 * If this will overflow buffer, stop decoding
2459 2374 */
2460 2375 if ((outcount + this_reclen) > entries_size) {
2461 2376 objp->eof = FALSE;
2462 2377 break;
2463 2378 }
2464 2379 dp->d_reclen = this_reclen;
2465 2380 dp->d_ino = fileid;
2466 2381
2467 2382 if (!xdr_opaque(xdrs, dp->d_name, namlen))
2468 2383 return (FALSE);
2469 2384 bzero(&dp->d_name[namlen],
2470 2385 DIRENT64_NAMELEN(this_reclen) - namlen);
2471 2386
2472 2387 /*
2473 2388 * cookie3 cookie
2474 2389 */
2475 2390 if (!xdr_u_longlong_t(xdrs, (u_longlong_t *)&dp->d_off))
2476 2391 return (FALSE);
2477 2392 objp->loff = dp->d_off;
2478 2393
2479 2394 /*
2480 2395 * post_op_attr name_attributes
2481 2396 */
2482 2397 if (!xdr_post_op_vattr(xdrs, &pov))
2483 2398 return (FALSE);
2484 2399
2485 2400 if (pov.attributes == TRUE &&
2486 2401 pov.fres.status == NFS3_OK)
2487 2402 va_valid = TRUE;
2488 2403 else
2489 2404 va_valid = FALSE;
2490 2405
2491 2406 /*
2492 2407 * post_op_fh3 name_handle
2493 2408 */
2494 2409 if (!XDR_GETINT32(xdrs, (int32_t *)&fh_valid))
2495 2410 return (FALSE);
2496 2411
2497 2412 /*
2498 2413 * By definition of the standard fh_valid can be 0 (FALSE) or
2499 2414 * 1 (TRUE), but we have to account for it being anything else
2500 2415 * in case some other system didn't follow the standard. Note
2501 2416 * that this is why the else checks if the fh_valid variable
2502 2417 * is != FALSE.
2503 2418 */
2504 2419 if (fh_valid == TRUE) {
2505 2420 if (!xdr_nfs_fh3(xdrs, &fh))
2506 2421 return (FALSE);
2507 2422 } else {
2508 2423 if (fh_valid != FALSE)
2509 2424 return (FALSE);
2510 2425 }
2511 2426
2512 2427 /*
2513 2428 * If the name is "." or there are no attributes,
2514 2429 * don't polute the DNLC with "." entries or files
2515 2430 * we cannot determine the type for.
2516 2431 */
2517 2432 if (!(namlen == 1 && dp->d_name[0] == '.') &&
2518 2433 va_valid && fh_valid) {
2519 2434
2520 2435 /*
2521 2436 * Do the DNLC caching
2522 2437 */
2523 2438 nvp = makenfs3node_va(&fh, &va, dvp->v_vfsp,
2524 2439 objp->time, objp->credentials,
2525 2440 rp->r_path, dp->d_name);
2526 2441 dnlc_update(dvp, dp->d_name, nvp);
2527 2442 VN_RELE(nvp);
2528 2443 }
2529 2444
2530 2445 outcount += this_reclen;
2531 2446 dp = (dirent64_t *)((intptr_t)dp + this_reclen);
2532 2447 }
2533 2448
2534 2449 objp->size = outcount;
2535 2450 return (TRUE);
2536 2451 }
2537 2452
2538 2453 bool_t
2539 2454 xdr_FSSTAT3res(XDR *xdrs, FSSTAT3res *objp)
2540 2455 {
2541 2456 FSSTAT3resok *resokp;
2542 2457
2543 2458 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2544 2459 return (FALSE);
2545 2460 if (objp->status != NFS3_OK)
2546 2461 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2547 2462
2548 2463 /* xdr_FSSTAT3resok */
2549 2464 resokp = &objp->resok;
2550 2465 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2551 2466 return (FALSE);
2552 2467 if (!xdr_u_longlong_t(xdrs, &resokp->tbytes))
2553 2468 return (FALSE);
2554 2469 if (!xdr_u_longlong_t(xdrs, &resokp->fbytes))
2555 2470 return (FALSE);
2556 2471 if (!xdr_u_longlong_t(xdrs, &resokp->abytes))
2557 2472 return (FALSE);
2558 2473 if (!xdr_u_longlong_t(xdrs, &resokp->tfiles))
2559 2474 return (FALSE);
2560 2475 if (!xdr_u_longlong_t(xdrs, &resokp->ffiles))
2561 2476 return (FALSE);
2562 2477 if (!xdr_u_longlong_t(xdrs, &resokp->afiles))
2563 2478 return (FALSE);
2564 2479 return (xdr_u_int(xdrs, &resokp->invarsec));
2565 2480 }
2566 2481
2567 2482 bool_t
2568 2483 xdr_FSINFO3res(XDR *xdrs, FSINFO3res *objp)
2569 2484 {
2570 2485 FSINFO3resok *resokp;
2571 2486
2572 2487 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2573 2488 return (FALSE);
2574 2489 if (objp->status != NFS3_OK) /* xdr_FSSTAT3resfail */
2575 2490 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2576 2491
2577 2492 /* xdr_FSINFO3resok */
2578 2493 resokp = &objp->resok;
2579 2494 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2580 2495 return (FALSE);
2581 2496 if (!xdr_u_int(xdrs, &resokp->rtmax))
2582 2497 return (FALSE);
2583 2498 if (!xdr_u_int(xdrs, &resokp->rtpref))
2584 2499 return (FALSE);
2585 2500 if (!xdr_u_int(xdrs, &resokp->rtmult))
2586 2501 return (FALSE);
2587 2502 if (!xdr_u_int(xdrs, &resokp->wtmax))
2588 2503 return (FALSE);
2589 2504 if (!xdr_u_int(xdrs, &resokp->wtpref))
2590 2505 return (FALSE);
2591 2506 if (!xdr_u_int(xdrs, &resokp->wtmult))
2592 2507 return (FALSE);
2593 2508 if (!xdr_u_int(xdrs, &resokp->dtpref))
2594 2509 return (FALSE);
2595 2510 if (!xdr_u_longlong_t(xdrs, &resokp->maxfilesize))
2596 2511 return (FALSE);
2597 2512 if (!xdr_u_int(xdrs, &resokp->time_delta.seconds))
2598 2513 return (FALSE);
2599 2514 if (!xdr_u_int(xdrs, &resokp->time_delta.nseconds))
2600 2515 return (FALSE);
2601 2516 return (xdr_u_int(xdrs, &resokp->properties));
2602 2517 }
2603 2518
2604 2519 bool_t
2605 2520 xdr_PATHCONF3res(XDR *xdrs, PATHCONF3res *objp)
2606 2521 {
2607 2522 PATHCONF3resok *resokp;
2608 2523
2609 2524 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2610 2525 return (FALSE);
2611 2526 if (objp->status != NFS3_OK)
2612 2527 return (xdr_post_op_attr(xdrs, &objp->resfail.obj_attributes));
2613 2528
2614 2529 /* xdr_PATHCONF3resok */
2615 2530 resokp = &objp->resok;
2616 2531 if (!xdr_post_op_attr(xdrs, &resokp->obj_attributes))
2617 2532 return (FALSE);
2618 2533 if (!xdr_u_int(xdrs, &resokp->info.link_max))
2619 2534 return (FALSE);
2620 2535 if (!xdr_u_int(xdrs, &resokp->info.name_max))
2621 2536 return (FALSE);
2622 2537 if (!xdr_bool(xdrs, &resokp->info.no_trunc))
2623 2538 return (FALSE);
2624 2539 if (!xdr_bool(xdrs, &resokp->info.chown_restricted))
2625 2540 return (FALSE);
2626 2541 if (!xdr_bool(xdrs, &resokp->info.case_insensitive))
2627 2542 return (FALSE);
2628 2543 return (xdr_bool(xdrs, &resokp->info.case_preserving));
2629 2544 }
2630 2545
2631 2546 bool_t
2632 2547 xdr_COMMIT3args(XDR *xdrs, COMMIT3args *objp)
2633 2548 {
2634 2549 if (xdrs->x_op == XDR_FREE)
2635 2550 return (TRUE);
2636 2551
2637 2552 switch (xdrs->x_op) {
2638 2553 case XDR_FREE:
2639 2554 case XDR_ENCODE:
2640 2555 if (!xdr_nfs_fh3(xdrs, &objp->file))
2641 2556 return (FALSE);
2642 2557 break;
2643 2558 case XDR_DECODE:
2644 2559 if (!xdr_nfs_fh3_server(xdrs, &objp->file))
2645 2560 return (FALSE);
2646 2561 break;
2647 2562 }
2648 2563 if (!xdr_u_longlong_t(xdrs, &objp->offset))
2649 2564 return (FALSE);
2650 2565 return (xdr_u_int(xdrs, &objp->count));
2651 2566 }
2652 2567
2653 2568 bool_t
2654 2569 xdr_COMMIT3res(XDR *xdrs, COMMIT3res *objp)
2655 2570 {
2656 2571 COMMIT3resok *resokp;
2657 2572
2658 2573 if (!xdr_enum(xdrs, (enum_t *)&objp->status))
2659 2574 return (FALSE);
2660 2575 if (objp->status != NFS3_OK)
2661 2576 return (xdr_wcc_data(xdrs, &objp->resfail.file_wcc));
2662 2577
2663 2578 /* xdr_COMMIT3resok */
2664 2579 resokp = &objp->resok;
2665 2580 if (!xdr_wcc_data(xdrs, &resokp->file_wcc))
2666 2581 return (FALSE);
2667 2582 /*
2668 2583 * writeverf3 is really an opaque 8 byte
2669 2584 * quantity, but we will treat it as a
2670 2585 * hyper for efficiency, the cost of
2671 2586 * a byteswap here saves bcopys elsewhere
2672 2587 */
2673 2588 return (xdr_u_longlong_t(xdrs, &resokp->verf));
2674 2589 }
|
↓ open down ↓ |
340 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX