aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2010-12-14 09:55:50 -0500
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-12-16 12:37:22 -0500
commitd9c407b138926132e1f93c01fb2dee50eb0bb615 (patch)
tree7157c9f0500357ff6affb14352d0c2bd7c958dae
parent2b061f9ef216b6d229b06267f188167fd6ab3d9b (diff)
NFS: Introduce new-style XDR encoding functions for NFSv3
We're interested in taking advantage of the safety benefits of xdr_streams. These data structures allow more careful checking for buffer overflow while encoding. More careful type checking is also introduced in the new functions. For efficiency, we also eventually want to be able to pass xdr_streams from call_encode() to all XDR encoding functions, rather than building an xdr_stream in every XDR encoding function in the kernel. To do this means all encoders must be ready to handle a passed-in xdr_stream. The new encoders follow the modern paradigm for XDR encoders: BUG on error, and always return a zero status code. Static helper functions are left without the "inline" directive. This allows the compiler to choose automatically how to optimize these for size or speed. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Tested-by: J. Bruce Fields <bfields@redhat.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--fs/nfs/nfs3xdr.c833
-rw-r--r--include/linux/nfs3.h2
2 files changed, 832 insertions, 3 deletions
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index f6cc60f06dac..3d1043f7667c 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 */
116static 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 */
113static inline __be32 * 131static inline __be32 *
@@ -153,7 +171,7 @@ out_overflow:
153 * Encode/decode time. 171 * Encode/decode time.
154 */ 172 */
155static inline __be32 * 173static inline __be32 *
156xdr_encode_time3(__be32 *p, struct timespec *timep) 174xdr_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
207static inline __be32 * 225static inline __be32 *
208xdr_encode_sattr(__be32 *p, struct iattr *attr) 226xdr_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
339static 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 */
350static 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 */
365static 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 */
378static __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 */
388static __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 */
399static 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 */
420static 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 */
434static 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 */
450static 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 */
519static 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 */
556static 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 */
586static 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 */
327static int 599static 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 */
627static 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
642static 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 */
342static int 657static 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 */
673static 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 */
354static int 686static 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 */
715static 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
722static 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 */
739static 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 */
785static 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
797static 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 */
403static int 813static 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 */
849static 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
867static 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 */
425static int 881static 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 */
920static 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
937static 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 */
445static int 951static 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 */
969static 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 */
458static int 983static 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 */
1010static 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
1017static 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 */
475static int 1031static 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 */
1071static 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
1078static 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
1099static 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 */
1117static 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 */
494static int 1130static 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 */
1149static 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 */
508static int 1165static 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 */
1183static 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 */
521static int 1197static 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 */
1232static 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
1245static 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 */
1268static 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
1288static 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 */
1440static 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
1452static 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
1487static 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
1535static 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/*
diff --git a/include/linux/nfs3.h b/include/linux/nfs3.h
index ac33806ec7f9..e2ee14fd0083 100644
--- a/include/linux/nfs3.h
+++ b/include/linux/nfs3.h
@@ -11,6 +11,8 @@
11#define NFS3_MAXGROUPS 16 11#define NFS3_MAXGROUPS 16
12#define NFS3_FHSIZE 64 12#define NFS3_FHSIZE 64
13#define NFS3_COOKIESIZE 4 13#define NFS3_COOKIESIZE 4
14#define NFS3_CREATEVERFSIZE 8
15#define NFS3_COOKIEVERFSIZE 8
14#define NFS3_FIFO_DEV (-1) 16#define NFS3_FIFO_DEV (-1)
15#define NFS3MODE_FMT 0170000 17#define NFS3MODE_FMT 0170000
16#define NFS3MODE_DIR 0040000 18#define NFS3MODE_DIR 0040000