diff options
Diffstat (limited to 'fs/nfs/nfs3xdr.c')
-rw-r--r-- | fs/nfs/nfs3xdr.c | 833 |
1 files changed, 830 insertions, 3 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c index f6cc60f06da..3d1043f7667 100644 --- a/fs/nfs/nfs3xdr.c +++ b/fs/nfs/nfs3xdr.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) | 37 | #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) |
38 | #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) | 38 | #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) |
39 | #define NFS3_fattr_sz (21) | 39 | #define NFS3_fattr_sz (21) |
40 | #define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2) | ||
40 | #define NFS3_wcc_attr_sz (6) | 41 | #define NFS3_wcc_attr_sz (6) |
41 | #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) | 42 | #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) |
42 | #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) | 43 | #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) |
@@ -59,7 +60,8 @@ | |||
59 | #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) | 60 | #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) |
60 | #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) | 61 | #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) |
61 | #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) | 62 | #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) |
62 | #define NFS3_readdirargs_sz (NFS3_fh_sz+2) | 63 | #define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3) |
64 | #define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4) | ||
63 | #define NFS3_commitargs_sz (NFS3_fh_sz+3) | 65 | #define NFS3_commitargs_sz (NFS3_fh_sz+3) |
64 | 66 | ||
65 | #define NFS3_attrstat_sz (1+NFS3_fattr_sz) | 67 | #define NFS3_attrstat_sz (1+NFS3_fattr_sz) |
@@ -108,6 +110,22 @@ static void print_overflow_msg(const char *func, const struct xdr_stream *xdr) | |||
108 | } | 110 | } |
109 | 111 | ||
110 | /* | 112 | /* |
113 | * While encoding arguments, set up the reply buffer in advance to | ||
114 | * receive reply data directly into the page cache. | ||
115 | */ | ||
116 | static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages, | ||
117 | unsigned int base, unsigned int len, | ||
118 | unsigned int bufsize) | ||
119 | { | ||
120 | struct rpc_auth *auth = req->rq_cred->cr_auth; | ||
121 | unsigned int replen; | ||
122 | |||
123 | replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize; | ||
124 | xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len); | ||
125 | } | ||
126 | |||
127 | |||
128 | /* | ||
111 | * Common NFS XDR functions as inlines | 129 | * Common NFS XDR functions as inlines |
112 | */ | 130 | */ |
113 | static inline __be32 * | 131 | static inline __be32 * |
@@ -153,7 +171,7 @@ out_overflow: | |||
153 | * Encode/decode time. | 171 | * Encode/decode time. |
154 | */ | 172 | */ |
155 | static inline __be32 * | 173 | static inline __be32 * |
156 | xdr_encode_time3(__be32 *p, struct timespec *timep) | 174 | xdr_encode_time3(__be32 *p, const struct timespec *timep) |
157 | { | 175 | { |
158 | *p++ = htonl(timep->tv_sec); | 176 | *p++ = htonl(timep->tv_sec); |
159 | *p++ = htonl(timep->tv_nsec); | 177 | *p++ = htonl(timep->tv_nsec); |
@@ -205,7 +223,7 @@ xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) | |||
205 | } | 223 | } |
206 | 224 | ||
207 | static inline __be32 * | 225 | static inline __be32 * |
208 | xdr_encode_sattr(__be32 *p, struct iattr *attr) | 226 | xdr_encode_sattr(__be32 *p, const struct iattr *attr) |
209 | { | 227 | { |
210 | if (attr->ia_valid & ATTR_MODE) { | 228 | if (attr->ia_valid & ATTR_MODE) { |
211 | *p++ = xdr_one; | 229 | *p++ = xdr_one; |
@@ -306,6 +324,243 @@ xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr) | |||
306 | return xdr_decode_post_op_attr(p, fattr); | 324 | return xdr_decode_post_op_attr(p, fattr); |
307 | } | 325 | } |
308 | 326 | ||
327 | |||
328 | /* | ||
329 | * Encode/decode NFSv3 basic data types | ||
330 | * | ||
331 | * Basic NFSv3 data types are defined in section 2.5 of RFC 1813: | ||
332 | * "NFS Version 3 Protocol Specification". | ||
333 | * | ||
334 | * Not all basic data types have their own encoding and decoding | ||
335 | * functions. For run-time efficiency, some data types are encoded | ||
336 | * or decoded inline. | ||
337 | */ | ||
338 | |||
339 | static void encode_uint32(struct xdr_stream *xdr, u32 value) | ||
340 | { | ||
341 | __be32 *p = xdr_reserve_space(xdr, 4); | ||
342 | *p = cpu_to_be32(value); | ||
343 | } | ||
344 | |||
345 | /* | ||
346 | * filename3 | ||
347 | * | ||
348 | * typedef string filename3<>; | ||
349 | */ | ||
350 | static void encode_filename3(struct xdr_stream *xdr, | ||
351 | const char *name, u32 length) | ||
352 | { | ||
353 | __be32 *p; | ||
354 | |||
355 | BUG_ON(length > NFS3_MAXNAMLEN); | ||
356 | p = xdr_reserve_space(xdr, 4 + length); | ||
357 | xdr_encode_opaque(p, name, length); | ||
358 | } | ||
359 | |||
360 | /* | ||
361 | * nfspath3 | ||
362 | * | ||
363 | * typedef string nfspath3<>; | ||
364 | */ | ||
365 | static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages, | ||
366 | const u32 length) | ||
367 | { | ||
368 | BUG_ON(length > NFS3_MAXPATHLEN); | ||
369 | encode_uint32(xdr, length); | ||
370 | xdr_write_pages(xdr, pages, 0, length); | ||
371 | } | ||
372 | |||
373 | /* | ||
374 | * cookie3 | ||
375 | * | ||
376 | * typedef uint64 cookie3 | ||
377 | */ | ||
378 | static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie) | ||
379 | { | ||
380 | return xdr_encode_hyper(p, cookie); | ||
381 | } | ||
382 | |||
383 | /* | ||
384 | * cookieverf3 | ||
385 | * | ||
386 | * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE]; | ||
387 | */ | ||
388 | static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier) | ||
389 | { | ||
390 | memcpy(p, verifier, NFS3_COOKIEVERFSIZE); | ||
391 | return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE); | ||
392 | } | ||
393 | |||
394 | /* | ||
395 | * createverf3 | ||
396 | * | ||
397 | * typedef opaque createverf3[NFS3_CREATEVERFSIZE]; | ||
398 | */ | ||
399 | static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier) | ||
400 | { | ||
401 | __be32 *p; | ||
402 | |||
403 | p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE); | ||
404 | memcpy(p, verifier, NFS3_CREATEVERFSIZE); | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * ftype3 | ||
409 | * | ||
410 | * enum ftype3 { | ||
411 | * NF3REG = 1, | ||
412 | * NF3DIR = 2, | ||
413 | * NF3BLK = 3, | ||
414 | * NF3CHR = 4, | ||
415 | * NF3LNK = 5, | ||
416 | * NF3SOCK = 6, | ||
417 | * NF3FIFO = 7 | ||
418 | * }; | ||
419 | */ | ||
420 | static void encode_ftype3(struct xdr_stream *xdr, const u32 type) | ||
421 | { | ||
422 | BUG_ON(type > NF3FIFO); | ||
423 | encode_uint32(xdr, type); | ||
424 | } | ||
425 | |||
426 | /* | ||
427 | * specdata3 | ||
428 | * | ||
429 | * struct specdata3 { | ||
430 | * uint32 specdata1; | ||
431 | * uint32 specdata2; | ||
432 | * }; | ||
433 | */ | ||
434 | static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev) | ||
435 | { | ||
436 | __be32 *p; | ||
437 | |||
438 | p = xdr_reserve_space(xdr, 8); | ||
439 | *p++ = cpu_to_be32(MAJOR(rdev)); | ||
440 | *p = cpu_to_be32(MINOR(rdev)); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * nfs_fh3 | ||
445 | * | ||
446 | * struct nfs_fh3 { | ||
447 | * opaque data<NFS3_FHSIZE>; | ||
448 | * }; | ||
449 | */ | ||
450 | static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh) | ||
451 | { | ||
452 | __be32 *p; | ||
453 | |||
454 | BUG_ON(fh->size > NFS3_FHSIZE); | ||
455 | p = xdr_reserve_space(xdr, 4 + fh->size); | ||
456 | xdr_encode_opaque(p, fh->data, fh->size); | ||
457 | } | ||
458 | |||
459 | /* | ||
460 | * sattr3 | ||
461 | * | ||
462 | * enum time_how { | ||
463 | * DONT_CHANGE = 0, | ||
464 | * SET_TO_SERVER_TIME = 1, | ||
465 | * SET_TO_CLIENT_TIME = 2 | ||
466 | * }; | ||
467 | * | ||
468 | * union set_mode3 switch (bool set_it) { | ||
469 | * case TRUE: | ||
470 | * mode3 mode; | ||
471 | * default: | ||
472 | * void; | ||
473 | * }; | ||
474 | * | ||
475 | * union set_uid3 switch (bool set_it) { | ||
476 | * case TRUE: | ||
477 | * uid3 uid; | ||
478 | * default: | ||
479 | * void; | ||
480 | * }; | ||
481 | * | ||
482 | * union set_gid3 switch (bool set_it) { | ||
483 | * case TRUE: | ||
484 | * gid3 gid; | ||
485 | * default: | ||
486 | * void; | ||
487 | * }; | ||
488 | * | ||
489 | * union set_size3 switch (bool set_it) { | ||
490 | * case TRUE: | ||
491 | * size3 size; | ||
492 | * default: | ||
493 | * void; | ||
494 | * }; | ||
495 | * | ||
496 | * union set_atime switch (time_how set_it) { | ||
497 | * case SET_TO_CLIENT_TIME: | ||
498 | * nfstime3 atime; | ||
499 | * default: | ||
500 | * void; | ||
501 | * }; | ||
502 | * | ||
503 | * union set_mtime switch (time_how set_it) { | ||
504 | * case SET_TO_CLIENT_TIME: | ||
505 | * nfstime3 mtime; | ||
506 | * default: | ||
507 | * void; | ||
508 | * }; | ||
509 | * | ||
510 | * struct sattr3 { | ||
511 | * set_mode3 mode; | ||
512 | * set_uid3 uid; | ||
513 | * set_gid3 gid; | ||
514 | * set_size3 size; | ||
515 | * set_atime atime; | ||
516 | * set_mtime mtime; | ||
517 | * }; | ||
518 | */ | ||
519 | static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr) | ||
520 | { | ||
521 | u32 nbytes; | ||
522 | __be32 *p; | ||
523 | |||
524 | /* | ||
525 | * In order to make only a single xdr_reserve_space() call, | ||
526 | * pre-compute the total number of bytes to be reserved. | ||
527 | * Six boolean values, one for each set_foo field, are always | ||
528 | * present in the encoded result, so start there. | ||
529 | */ | ||
530 | nbytes = 6 * 4; | ||
531 | if (attr->ia_valid & ATTR_MODE) | ||
532 | nbytes += 4; | ||
533 | if (attr->ia_valid & ATTR_UID) | ||
534 | nbytes += 4; | ||
535 | if (attr->ia_valid & ATTR_GID) | ||
536 | nbytes += 4; | ||
537 | if (attr->ia_valid & ATTR_SIZE) | ||
538 | nbytes += 8; | ||
539 | if (attr->ia_valid & ATTR_ATIME_SET) | ||
540 | nbytes += 8; | ||
541 | if (attr->ia_valid & ATTR_MTIME_SET) | ||
542 | nbytes += 8; | ||
543 | p = xdr_reserve_space(xdr, nbytes); | ||
544 | |||
545 | xdr_encode_sattr(p, attr); | ||
546 | } | ||
547 | |||
548 | /* | ||
549 | * diropargs3 | ||
550 | * | ||
551 | * struct diropargs3 { | ||
552 | * nfs_fh3 dir; | ||
553 | * filename3 name; | ||
554 | * }; | ||
555 | */ | ||
556 | static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh, | ||
557 | const char *name, u32 length) | ||
558 | { | ||
559 | encode_nfs_fh3(xdr, fh); | ||
560 | encode_filename3(xdr, name, length); | ||
561 | } | ||
562 | |||
563 | |||
309 | /* | 564 | /* |
310 | * NFS encode functions | 565 | * NFS encode functions |
311 | */ | 566 | */ |
@@ -322,6 +577,23 @@ nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) | |||
322 | } | 577 | } |
323 | 578 | ||
324 | /* | 579 | /* |
580 | * 3.3.1 GETATTR3args | ||
581 | * | ||
582 | * struct GETATTR3args { | ||
583 | * nfs_fh3 object; | ||
584 | * }; | ||
585 | */ | ||
586 | static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p, | ||
587 | const struct nfs_fh *fh) | ||
588 | { | ||
589 | struct xdr_stream xdr; | ||
590 | |||
591 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
592 | encode_nfs_fh3(&xdr, fh); | ||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | /* | ||
325 | * Encode SETATTR arguments | 597 | * Encode SETATTR arguments |
326 | */ | 598 | */ |
327 | static int | 599 | static int |
@@ -337,6 +609,49 @@ nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) | |||
337 | } | 609 | } |
338 | 610 | ||
339 | /* | 611 | /* |
612 | * 3.3.2 SETATTR3args | ||
613 | * | ||
614 | * union sattrguard3 switch (bool check) { | ||
615 | * case TRUE: | ||
616 | * nfstime3 obj_ctime; | ||
617 | * case FALSE: | ||
618 | * void; | ||
619 | * }; | ||
620 | * | ||
621 | * struct SETATTR3args { | ||
622 | * nfs_fh3 object; | ||
623 | * sattr3 new_attributes; | ||
624 | * sattrguard3 guard; | ||
625 | * }; | ||
626 | */ | ||
627 | static void encode_sattrguard3(struct xdr_stream *xdr, | ||
628 | const struct nfs3_sattrargs *args) | ||
629 | { | ||
630 | __be32 *p; | ||
631 | |||
632 | if (args->guard) { | ||
633 | p = xdr_reserve_space(xdr, 4 + 8); | ||
634 | *p++ = xdr_one; | ||
635 | xdr_encode_time3(p, &args->guardtime); | ||
636 | } else { | ||
637 | p = xdr_reserve_space(xdr, 4); | ||
638 | *p = xdr_zero; | ||
639 | } | ||
640 | } | ||
641 | |||
642 | static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p, | ||
643 | const struct nfs3_sattrargs *args) | ||
644 | { | ||
645 | struct xdr_stream xdr; | ||
646 | |||
647 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
648 | encode_nfs_fh3(&xdr, args->fh); | ||
649 | encode_sattr3(&xdr, args->sattr); | ||
650 | encode_sattrguard3(&xdr, args); | ||
651 | return 0; | ||
652 | } | ||
653 | |||
654 | /* | ||
340 | * Encode directory ops argument | 655 | * Encode directory ops argument |
341 | */ | 656 | */ |
342 | static int | 657 | static int |
@@ -349,6 +664,23 @@ nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args) | |||
349 | } | 664 | } |
350 | 665 | ||
351 | /* | 666 | /* |
667 | * 3.3.3 LOOKUP3args | ||
668 | * | ||
669 | * struct LOOKUP3args { | ||
670 | * diropargs3 what; | ||
671 | * }; | ||
672 | */ | ||
673 | static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p, | ||
674 | const struct nfs3_diropargs *args) | ||
675 | { | ||
676 | struct xdr_stream xdr; | ||
677 | |||
678 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
679 | encode_diropargs3(&xdr, args->fh, args->name, args->len); | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | /* | ||
352 | * Encode REMOVE argument | 684 | * Encode REMOVE argument |
353 | */ | 685 | */ |
354 | static int | 686 | static int |
@@ -373,6 +705,50 @@ nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *arg | |||
373 | } | 705 | } |
374 | 706 | ||
375 | /* | 707 | /* |
708 | * 3.3.4 ACCESS3args | ||
709 | * | ||
710 | * struct ACCESS3args { | ||
711 | * nfs_fh3 object; | ||
712 | * uint32 access; | ||
713 | * }; | ||
714 | */ | ||
715 | static void encode_access3args(struct xdr_stream *xdr, | ||
716 | const struct nfs3_accessargs *args) | ||
717 | { | ||
718 | encode_nfs_fh3(xdr, args->fh); | ||
719 | encode_uint32(xdr, args->access); | ||
720 | } | ||
721 | |||
722 | static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p, | ||
723 | const struct nfs3_accessargs *args) | ||
724 | { | ||
725 | struct xdr_stream xdr; | ||
726 | |||
727 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
728 | encode_access3args(&xdr, args); | ||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | /* | ||
733 | * 3.3.5 READLINK3args | ||
734 | * | ||
735 | * struct READLINK3args { | ||
736 | * nfs_fh3 symlink; | ||
737 | * }; | ||
738 | */ | ||
739 | static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p, | ||
740 | const struct nfs3_readlinkargs *args) | ||
741 | { | ||
742 | struct xdr_stream xdr; | ||
743 | |||
744 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
745 | encode_nfs_fh3(&xdr, args->fh); | ||
746 | prepare_reply_buffer(req, args->pages, args->pgbase, | ||
747 | args->pglen, NFS3_readlinkres_sz); | ||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | /* | ||
376 | * Arguments to a READ call. Since we read data directly into the page | 752 | * Arguments to a READ call. Since we read data directly into the page |
377 | * cache, we also set up the reply iovec here so that iov[1] points | 753 | * cache, we also set up the reply iovec here so that iov[1] points |
378 | * exactly to the page we want to fetch. | 754 | * exactly to the page we want to fetch. |
@@ -398,6 +774,40 @@ nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) | |||
398 | } | 774 | } |
399 | 775 | ||
400 | /* | 776 | /* |
777 | * 3.3.6 READ3args | ||
778 | * | ||
779 | * struct READ3args { | ||
780 | * nfs_fh3 file; | ||
781 | * offset3 offset; | ||
782 | * count3 count; | ||
783 | * }; | ||
784 | */ | ||
785 | static void encode_read3args(struct xdr_stream *xdr, | ||
786 | const struct nfs_readargs *args) | ||
787 | { | ||
788 | __be32 *p; | ||
789 | |||
790 | encode_nfs_fh3(xdr, args->fh); | ||
791 | |||
792 | p = xdr_reserve_space(xdr, 8 + 4); | ||
793 | p = xdr_encode_hyper(p, args->offset); | ||
794 | *p = cpu_to_be32(args->count); | ||
795 | } | ||
796 | |||
797 | static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p, | ||
798 | const struct nfs_readargs *args) | ||
799 | { | ||
800 | struct xdr_stream xdr; | ||
801 | |||
802 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
803 | encode_read3args(&xdr, args); | ||
804 | prepare_reply_buffer(req, args->pages, args->pgbase, | ||
805 | args->count, NFS3_readres_sz); | ||
806 | req->rq_rcv_buf.flags |= XDRBUF_READ; | ||
807 | return 0; | ||
808 | } | ||
809 | |||
810 | /* | ||
401 | * Write arguments. Splice the buffer to be written into the iovec. | 811 | * Write arguments. Splice the buffer to be written into the iovec. |
402 | */ | 812 | */ |
403 | static int | 813 | static int |
@@ -420,6 +830,52 @@ nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) | |||
420 | } | 830 | } |
421 | 831 | ||
422 | /* | 832 | /* |
833 | * 3.3.7 WRITE3args | ||
834 | * | ||
835 | * enum stable_how { | ||
836 | * UNSTABLE = 0, | ||
837 | * DATA_SYNC = 1, | ||
838 | * FILE_SYNC = 2 | ||
839 | * }; | ||
840 | * | ||
841 | * struct WRITE3args { | ||
842 | * nfs_fh3 file; | ||
843 | * offset3 offset; | ||
844 | * count3 count; | ||
845 | * stable_how stable; | ||
846 | * opaque data<>; | ||
847 | * }; | ||
848 | */ | ||
849 | static void encode_write3args(struct xdr_stream *xdr, | ||
850 | const struct nfs_writeargs *args) | ||
851 | { | ||
852 | __be32 *p; | ||
853 | |||
854 | encode_nfs_fh3(xdr, args->fh); | ||
855 | |||
856 | p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4); | ||
857 | p = xdr_encode_hyper(p, args->offset); | ||
858 | *p++ = cpu_to_be32(args->count); | ||
859 | |||
860 | BUG_ON(args->stable > NFS_FILE_SYNC); | ||
861 | *p++ = cpu_to_be32(args->stable); | ||
862 | |||
863 | *p = cpu_to_be32(args->count); | ||
864 | xdr_write_pages(xdr, args->pages, args->pgbase, args->count); | ||
865 | } | ||
866 | |||
867 | static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p, | ||
868 | const struct nfs_writeargs *args) | ||
869 | { | ||
870 | struct xdr_stream xdr; | ||
871 | |||
872 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
873 | encode_write3args(&xdr, args); | ||
874 | xdr.buf->flags |= XDRBUF_WRITE; | ||
875 | return 0; | ||
876 | } | ||
877 | |||
878 | /* | ||
423 | * Encode CREATE arguments | 879 | * Encode CREATE arguments |
424 | */ | 880 | */ |
425 | static int | 881 | static int |
@@ -440,6 +896,56 @@ nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *arg | |||
440 | } | 896 | } |
441 | 897 | ||
442 | /* | 898 | /* |
899 | * 3.3.8 CREATE3args | ||
900 | * | ||
901 | * enum createmode3 { | ||
902 | * UNCHECKED = 0, | ||
903 | * GUARDED = 1, | ||
904 | * EXCLUSIVE = 2 | ||
905 | * }; | ||
906 | * | ||
907 | * union createhow3 switch (createmode3 mode) { | ||
908 | * case UNCHECKED: | ||
909 | * case GUARDED: | ||
910 | * sattr3 obj_attributes; | ||
911 | * case EXCLUSIVE: | ||
912 | * createverf3 verf; | ||
913 | * }; | ||
914 | * | ||
915 | * struct CREATE3args { | ||
916 | * diropargs3 where; | ||
917 | * createhow3 how; | ||
918 | * }; | ||
919 | */ | ||
920 | static void encode_createhow3(struct xdr_stream *xdr, | ||
921 | const struct nfs3_createargs *args) | ||
922 | { | ||
923 | encode_uint32(xdr, args->createmode); | ||
924 | switch (args->createmode) { | ||
925 | case NFS3_CREATE_UNCHECKED: | ||
926 | case NFS3_CREATE_GUARDED: | ||
927 | encode_sattr3(xdr, args->sattr); | ||
928 | break; | ||
929 | case NFS3_CREATE_EXCLUSIVE: | ||
930 | encode_createverf3(xdr, args->verifier); | ||
931 | break; | ||
932 | default: | ||
933 | BUG(); | ||
934 | } | ||
935 | } | ||
936 | |||
937 | static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p, | ||
938 | const struct nfs3_createargs *args) | ||
939 | { | ||
940 | struct xdr_stream xdr; | ||
941 | |||
942 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
943 | encode_diropargs3(&xdr, args->fh, args->name, args->len); | ||
944 | encode_createhow3(&xdr, args); | ||
945 | return 0; | ||
946 | } | ||
947 | |||
948 | /* | ||
443 | * Encode MKDIR arguments | 949 | * Encode MKDIR arguments |
444 | */ | 950 | */ |
445 | static int | 951 | static int |
@@ -453,6 +959,25 @@ nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) | |||
453 | } | 959 | } |
454 | 960 | ||
455 | /* | 961 | /* |
962 | * 3.3.9 MKDIR3args | ||
963 | * | ||
964 | * struct MKDIR3args { | ||
965 | * diropargs3 where; | ||
966 | * sattr3 attributes; | ||
967 | * }; | ||
968 | */ | ||
969 | static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p, | ||
970 | const struct nfs3_mkdirargs *args) | ||
971 | { | ||
972 | struct xdr_stream xdr; | ||
973 | |||
974 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
975 | encode_diropargs3(&xdr, args->fh, args->name, args->len); | ||
976 | encode_sattr3(&xdr, args->sattr); | ||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | /* | ||
456 | * Encode SYMLINK arguments | 981 | * Encode SYMLINK arguments |
457 | */ | 982 | */ |
458 | static int | 983 | static int |
@@ -470,6 +995,37 @@ nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *a | |||
470 | } | 995 | } |
471 | 996 | ||
472 | /* | 997 | /* |
998 | * 3.3.10 SYMLINK3args | ||
999 | * | ||
1000 | * struct symlinkdata3 { | ||
1001 | * sattr3 symlink_attributes; | ||
1002 | * nfspath3 symlink_data; | ||
1003 | * }; | ||
1004 | * | ||
1005 | * struct SYMLINK3args { | ||
1006 | * diropargs3 where; | ||
1007 | * symlinkdata3 symlink; | ||
1008 | * }; | ||
1009 | */ | ||
1010 | static void encode_symlinkdata3(struct xdr_stream *xdr, | ||
1011 | const struct nfs3_symlinkargs *args) | ||
1012 | { | ||
1013 | encode_sattr3(xdr, args->sattr); | ||
1014 | encode_nfspath3(xdr, args->pages, args->pathlen); | ||
1015 | } | ||
1016 | |||
1017 | static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p, | ||
1018 | const struct nfs3_symlinkargs *args) | ||
1019 | { | ||
1020 | struct xdr_stream xdr; | ||
1021 | |||
1022 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1023 | encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen); | ||
1024 | encode_symlinkdata3(&xdr, args); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1028 | /* | ||
473 | * Encode MKNOD arguments | 1029 | * Encode MKNOD arguments |
474 | */ | 1030 | */ |
475 | static int | 1031 | static int |
@@ -489,6 +1045,86 @@ nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) | |||
489 | } | 1045 | } |
490 | 1046 | ||
491 | /* | 1047 | /* |
1048 | * 3.3.11 MKNOD3args | ||
1049 | * | ||
1050 | * struct devicedata3 { | ||
1051 | * sattr3 dev_attributes; | ||
1052 | * specdata3 spec; | ||
1053 | * }; | ||
1054 | * | ||
1055 | * union mknoddata3 switch (ftype3 type) { | ||
1056 | * case NF3CHR: | ||
1057 | * case NF3BLK: | ||
1058 | * devicedata3 device; | ||
1059 | * case NF3SOCK: | ||
1060 | * case NF3FIFO: | ||
1061 | * sattr3 pipe_attributes; | ||
1062 | * default: | ||
1063 | * void; | ||
1064 | * }; | ||
1065 | * | ||
1066 | * struct MKNOD3args { | ||
1067 | * diropargs3 where; | ||
1068 | * mknoddata3 what; | ||
1069 | * }; | ||
1070 | */ | ||
1071 | static void encode_devicedata3(struct xdr_stream *xdr, | ||
1072 | const struct nfs3_mknodargs *args) | ||
1073 | { | ||
1074 | encode_sattr3(xdr, args->sattr); | ||
1075 | encode_specdata3(xdr, args->rdev); | ||
1076 | } | ||
1077 | |||
1078 | static void encode_mknoddata3(struct xdr_stream *xdr, | ||
1079 | const struct nfs3_mknodargs *args) | ||
1080 | { | ||
1081 | encode_ftype3(xdr, args->type); | ||
1082 | switch (args->type) { | ||
1083 | case NF3CHR: | ||
1084 | case NF3BLK: | ||
1085 | encode_devicedata3(xdr, args); | ||
1086 | break; | ||
1087 | case NF3SOCK: | ||
1088 | case NF3FIFO: | ||
1089 | encode_sattr3(xdr, args->sattr); | ||
1090 | break; | ||
1091 | case NF3REG: | ||
1092 | case NF3DIR: | ||
1093 | break; | ||
1094 | default: | ||
1095 | BUG(); | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1099 | static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p, | ||
1100 | const struct nfs3_mknodargs *args) | ||
1101 | { | ||
1102 | struct xdr_stream xdr; | ||
1103 | |||
1104 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1105 | encode_diropargs3(&xdr, args->fh, args->name, args->len); | ||
1106 | encode_mknoddata3(&xdr, args); | ||
1107 | return 0; | ||
1108 | } | ||
1109 | |||
1110 | /* | ||
1111 | * 3.3.12 REMOVE3args | ||
1112 | * | ||
1113 | * struct REMOVE3args { | ||
1114 | * diropargs3 object; | ||
1115 | * }; | ||
1116 | */ | ||
1117 | static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p, | ||
1118 | const struct nfs_removeargs *args) | ||
1119 | { | ||
1120 | struct xdr_stream xdr; | ||
1121 | |||
1122 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1123 | encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len); | ||
1124 | return 0; | ||
1125 | } | ||
1126 | |||
1127 | /* | ||
492 | * Encode RENAME arguments | 1128 | * Encode RENAME arguments |
493 | */ | 1129 | */ |
494 | static int | 1130 | static int |
@@ -503,6 +1139,27 @@ nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args | |||
503 | } | 1139 | } |
504 | 1140 | ||
505 | /* | 1141 | /* |
1142 | * 3.3.14 RENAME3args | ||
1143 | * | ||
1144 | * struct RENAME3args { | ||
1145 | * diropargs3 from; | ||
1146 | * diropargs3 to; | ||
1147 | * }; | ||
1148 | */ | ||
1149 | static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p, | ||
1150 | const struct nfs_renameargs *args) | ||
1151 | { | ||
1152 | const struct qstr *old = args->old_name; | ||
1153 | const struct qstr *new = args->new_name; | ||
1154 | struct xdr_stream xdr; | ||
1155 | |||
1156 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1157 | encode_diropargs3(&xdr, args->old_dir, old->name, old->len); | ||
1158 | encode_diropargs3(&xdr, args->new_dir, new->name, new->len); | ||
1159 | return 0; | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
506 | * Encode LINK arguments | 1163 | * Encode LINK arguments |
507 | */ | 1164 | */ |
508 | static int | 1165 | static int |
@@ -516,6 +1173,25 @@ nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) | |||
516 | } | 1173 | } |
517 | 1174 | ||
518 | /* | 1175 | /* |
1176 | * 3.3.15 LINK3args | ||
1177 | * | ||
1178 | * struct LINK3args { | ||
1179 | * nfs_fh3 file; | ||
1180 | * diropargs3 link; | ||
1181 | * }; | ||
1182 | */ | ||
1183 | static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p, | ||
1184 | const struct nfs3_linkargs *args) | ||
1185 | { | ||
1186 | struct xdr_stream xdr; | ||
1187 | |||
1188 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1189 | encode_nfs_fh3(&xdr, args->fromfh); | ||
1190 | encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen); | ||
1191 | return 0; | ||
1192 | } | ||
1193 | |||
1194 | /* | ||
519 | * Encode arguments to readdir call | 1195 | * Encode arguments to readdir call |
520 | */ | 1196 | */ |
521 | static int | 1197 | static int |
@@ -544,6 +1220,84 @@ nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *a | |||
544 | } | 1220 | } |
545 | 1221 | ||
546 | /* | 1222 | /* |
1223 | * 3.3.16 READDIR3args | ||
1224 | * | ||
1225 | * struct READDIR3args { | ||
1226 | * nfs_fh3 dir; | ||
1227 | * cookie3 cookie; | ||
1228 | * cookieverf3 cookieverf; | ||
1229 | * count3 count; | ||
1230 | * }; | ||
1231 | */ | ||
1232 | static void encode_readdir3args(struct xdr_stream *xdr, | ||
1233 | const struct nfs3_readdirargs *args) | ||
1234 | { | ||
1235 | __be32 *p; | ||
1236 | |||
1237 | encode_nfs_fh3(xdr, args->fh); | ||
1238 | |||
1239 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4); | ||
1240 | p = xdr_encode_cookie3(p, args->cookie); | ||
1241 | p = xdr_encode_cookieverf3(p, args->verf); | ||
1242 | *p = cpu_to_be32(args->count); | ||
1243 | } | ||
1244 | |||
1245 | static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p, | ||
1246 | const struct nfs3_readdirargs *args) | ||
1247 | { | ||
1248 | struct xdr_stream xdr; | ||
1249 | |||
1250 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1251 | encode_readdir3args(&xdr, args); | ||
1252 | prepare_reply_buffer(req, args->pages, 0, | ||
1253 | args->count, NFS3_readdirres_sz); | ||
1254 | return 0; | ||
1255 | } | ||
1256 | |||
1257 | /* | ||
1258 | * 3.3.17 READDIRPLUS3args | ||
1259 | * | ||
1260 | * struct READDIRPLUS3args { | ||
1261 | * nfs_fh3 dir; | ||
1262 | * cookie3 cookie; | ||
1263 | * cookieverf3 cookieverf; | ||
1264 | * count3 dircount; | ||
1265 | * count3 maxcount; | ||
1266 | * }; | ||
1267 | */ | ||
1268 | static void encode_readdirplus3args(struct xdr_stream *xdr, | ||
1269 | const struct nfs3_readdirargs *args) | ||
1270 | { | ||
1271 | __be32 *p; | ||
1272 | |||
1273 | encode_nfs_fh3(xdr, args->fh); | ||
1274 | |||
1275 | p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4); | ||
1276 | p = xdr_encode_cookie3(p, args->cookie); | ||
1277 | p = xdr_encode_cookieverf3(p, args->verf); | ||
1278 | |||
1279 | /* | ||
1280 | * readdirplus: need dircount + buffer size. | ||
1281 | * We just make sure we make dircount big enough | ||
1282 | */ | ||
1283 | *p++ = cpu_to_be32(args->count >> 3); | ||
1284 | |||
1285 | *p = cpu_to_be32(args->count); | ||
1286 | } | ||
1287 | |||
1288 | static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p, | ||
1289 | const struct nfs3_readdirargs *args) | ||
1290 | { | ||
1291 | struct xdr_stream xdr; | ||
1292 | |||
1293 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1294 | encode_readdirplus3args(&xdr, args); | ||
1295 | prepare_reply_buffer(req, args->pages, 0, | ||
1296 | args->count, NFS3_readdirres_sz); | ||
1297 | return 0; | ||
1298 | } | ||
1299 | |||
1300 | /* | ||
547 | * Decode the result of a readdir call. | 1301 | * Decode the result of a readdir call. |
548 | * We just check for syntactical correctness. | 1302 | * We just check for syntactical correctness. |
549 | */ | 1303 | */ |
@@ -674,6 +1428,37 @@ nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) | |||
674 | return 0; | 1428 | return 0; |
675 | } | 1429 | } |
676 | 1430 | ||
1431 | /* | ||
1432 | * 3.3.21 COMMIT3args | ||
1433 | * | ||
1434 | * struct COMMIT3args { | ||
1435 | * nfs_fh3 file; | ||
1436 | * offset3 offset; | ||
1437 | * count3 count; | ||
1438 | * }; | ||
1439 | */ | ||
1440 | static void encode_commit3args(struct xdr_stream *xdr, | ||
1441 | const struct nfs_writeargs *args) | ||
1442 | { | ||
1443 | __be32 *p; | ||
1444 | |||
1445 | encode_nfs_fh3(xdr, args->fh); | ||
1446 | |||
1447 | p = xdr_reserve_space(xdr, 8 + 4); | ||
1448 | p = xdr_encode_hyper(p, args->offset); | ||
1449 | *p = cpu_to_be32(args->count); | ||
1450 | } | ||
1451 | |||
1452 | static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p, | ||
1453 | const struct nfs_writeargs *args) | ||
1454 | { | ||
1455 | struct xdr_stream xdr; | ||
1456 | |||
1457 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1458 | encode_commit3args(&xdr, args); | ||
1459 | return 0; | ||
1460 | } | ||
1461 | |||
677 | #ifdef CONFIG_NFS_V3_ACL | 1462 | #ifdef CONFIG_NFS_V3_ACL |
678 | /* | 1463 | /* |
679 | * Encode GETACL arguments | 1464 | * Encode GETACL arguments |
@@ -699,6 +1484,21 @@ nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, | |||
699 | return 0; | 1484 | return 0; |
700 | } | 1485 | } |
701 | 1486 | ||
1487 | static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p, | ||
1488 | const struct nfs3_getaclargs *args) | ||
1489 | { | ||
1490 | struct xdr_stream xdr; | ||
1491 | |||
1492 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1493 | encode_nfs_fh3(&xdr, args->fh); | ||
1494 | encode_uint32(&xdr, args->mask); | ||
1495 | if (args->mask & (NFS_ACL | NFS_DFACL)) | ||
1496 | prepare_reply_buffer(req, args->pages, 0, | ||
1497 | NFSACL_MAXPAGES << PAGE_SHIFT, | ||
1498 | ACL3_getaclres_sz); | ||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
702 | /* | 1502 | /* |
703 | * Encode SETACL arguments | 1503 | * Encode SETACL arguments |
704 | */ | 1504 | */ |
@@ -731,6 +1531,33 @@ nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, | |||
731 | NFS_ACL_DEFAULT); | 1531 | NFS_ACL_DEFAULT); |
732 | return (err > 0) ? 0 : err; | 1532 | return (err > 0) ? 0 : err; |
733 | } | 1533 | } |
1534 | |||
1535 | static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p, | ||
1536 | const struct nfs3_setaclargs *args) | ||
1537 | { | ||
1538 | struct xdr_stream xdr; | ||
1539 | unsigned int base; | ||
1540 | int error; | ||
1541 | |||
1542 | xdr_init_encode(&xdr, &req->rq_snd_buf, p); | ||
1543 | encode_nfs_fh3(&xdr, NFS_FH(args->inode)); | ||
1544 | encode_uint32(&xdr, args->mask); | ||
1545 | if (args->npages != 0) | ||
1546 | xdr_write_pages(&xdr, args->pages, 0, args->len); | ||
1547 | |||
1548 | base = req->rq_slen; | ||
1549 | error = nfsacl_encode(xdr.buf, base, args->inode, | ||
1550 | (args->mask & NFS_ACL) ? | ||
1551 | args->acl_access : NULL, 1, 0); | ||
1552 | BUG_ON(error < 0); | ||
1553 | error = nfsacl_encode(xdr.buf, base + error, args->inode, | ||
1554 | (args->mask & NFS_DFACL) ? | ||
1555 | args->acl_default : NULL, 1, | ||
1556 | NFS_ACL_DEFAULT); | ||
1557 | BUG_ON(error < 0); | ||
1558 | return 0; | ||
1559 | } | ||
1560 | |||
734 | #endif /* CONFIG_NFS_V3_ACL */ | 1561 | #endif /* CONFIG_NFS_V3_ACL */ |
735 | 1562 | ||
736 | /* | 1563 | /* |