2 * linux/fs/nfs/nfs3xdr.c
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
6 * Copyright (C) 1996, 1997 Olaf Kirch
9 #include <linux/param.h>
10 #include <linux/time.h>
12 #include <linux/errno.h>
13 #include <linux/string.h>
15 #include <linux/pagemap.h>
16 #include <linux/proc_fs.h>
17 #include <linux/kdev_t.h>
18 #include <linux/sunrpc/clnt.h>
19 #include <linux/nfs.h>
20 #include <linux/nfs3.h>
21 #include <linux/nfs_fs.h>
22 #include <linux/nfsacl.h>
25 #define NFSDBG_FACILITY NFSDBG_XDR
27 /* Mapping from NFS error code to "errno" error code. */
28 #define errno_NFSERR_IO EIO
31 * Declare the space requirements for NFS arguments and replies as
32 * number of 32bit-words
34 #define NFS3_fhandle_sz (1+16)
35 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
36 #define NFS3_sattr_sz (15)
37 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
38 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
39 #define NFS3_fattr_sz (21)
40 #define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
41 #define NFS3_wcc_attr_sz (6)
42 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
44 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
45 #define NFS3_fsstat_sz
46 #define NFS3_fsinfo_sz
47 #define NFS3_pathconf_sz
48 #define NFS3_entry_sz (NFS3_filename_sz+3)
49 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
51 #define NFS3_getattrargs_sz (NFS3_fh_sz)
52 #define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
53 #define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz)
54 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
55 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
56 #define NFS3_readargs_sz (NFS3_fh_sz+3)
57 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
58 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
60 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
61 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
63 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
64 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
65 #define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
66 #define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
67 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
69 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
70 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
71 #define NFS3_removeres_sz (NFS3_wccstat_sz)
72 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
73 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
74 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
75 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
76 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
77 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
79 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
80 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
81 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
82 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
83 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
84 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
86 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
87 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
88 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
89 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
90 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
91 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
94 * Map file type to S_IFMT bits
96 static const umode_t nfs_type2fmt[] = {
103 [NF3SOCK] = S_IFSOCK,
107 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
109 dprintk("nfs: %s: prematurely hit end of receive buffer. "
110 "Remaining buffer length is %tu words.\n",
111 func, xdr->end - xdr->p);
115 * While encoding arguments, set up the reply buffer in advance to
116 * receive reply data directly into the page cache.
118 static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
119 unsigned int base, unsigned int len,
120 unsigned int bufsize)
122 struct rpc_auth *auth = req->rq_cred->cr_auth;
125 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
126 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
131 * Common NFS XDR functions as inlines
133 static inline __be32 *
134 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
136 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
137 memcpy(fh->data, p, fh->size);
138 return p + XDR_QUADLEN(fh->size);
143 static inline __be32 *
144 xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
147 p = xdr_inline_decode(xdr, 4);
150 fh->size = ntohl(*p++);
152 if (fh->size <= NFS3_FHSIZE) {
153 p = xdr_inline_decode(xdr, fh->size);
156 memcpy(fh->data, p, fh->size);
157 return p + XDR_QUADLEN(fh->size);
162 print_overflow_msg(__func__, xdr);
163 return ERR_PTR(-EIO);
167 * Encode/decode time.
169 static inline __be32 *
170 xdr_decode_time3(__be32 *p, struct timespec *timep)
172 timep->tv_sec = ntohl(*p++);
173 timep->tv_nsec = ntohl(*p++);
178 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
180 unsigned int type, major, minor;
186 fmode = nfs_type2fmt[type];
187 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
188 fattr->nlink = ntohl(*p++);
189 fattr->uid = ntohl(*p++);
190 fattr->gid = ntohl(*p++);
191 p = xdr_decode_hyper(p, &fattr->size);
192 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
194 /* Turn remote device info into Linux-specific dev_t */
197 fattr->rdev = MKDEV(major, minor);
198 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
201 p = xdr_decode_hyper(p, &fattr->fsid.major);
202 fattr->fsid.minor = 0;
203 p = xdr_decode_hyper(p, &fattr->fileid);
204 p = xdr_decode_time3(p, &fattr->atime);
205 p = xdr_decode_time3(p, &fattr->mtime);
206 p = xdr_decode_time3(p, &fattr->ctime);
208 /* Update the mode bits */
209 fattr->valid |= NFS_ATTR_FATTR_V3;
213 static inline __be32 *
214 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
216 p = xdr_decode_hyper(p, &fattr->pre_size);
217 p = xdr_decode_time3(p, &fattr->pre_mtime);
218 p = xdr_decode_time3(p, &fattr->pre_ctime);
219 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
220 | NFS_ATTR_FATTR_PREMTIME
221 | NFS_ATTR_FATTR_PRECTIME;
225 static inline __be32 *
226 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
229 p = xdr_decode_fattr(p, fattr);
233 static inline __be32 *
234 xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
238 p = xdr_inline_decode(xdr, 4);
242 p = xdr_inline_decode(xdr, 84);
245 p = xdr_decode_fattr(p, fattr);
249 print_overflow_msg(__func__, xdr);
250 return ERR_PTR(-EIO);
253 static inline __be32 *
254 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
257 return xdr_decode_wcc_attr(p, fattr);
262 static inline __be32 *
263 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
265 p = xdr_decode_pre_op_attr(p, fattr);
266 return xdr_decode_post_op_attr(p, fattr);
271 * Encode/decode NFSv3 basic data types
273 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
274 * "NFS Version 3 Protocol Specification".
276 * Not all basic data types have their own encoding and decoding
277 * functions. For run-time efficiency, some data types are encoded
281 static void encode_uint32(struct xdr_stream *xdr, u32 value)
283 __be32 *p = xdr_reserve_space(xdr, 4);
284 *p = cpu_to_be32(value);
290 * typedef string filename3<>;
292 static void encode_filename3(struct xdr_stream *xdr,
293 const char *name, u32 length)
297 BUG_ON(length > NFS3_MAXNAMLEN);
298 p = xdr_reserve_space(xdr, 4 + length);
299 xdr_encode_opaque(p, name, length);
305 * typedef string nfspath3<>;
307 static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
310 BUG_ON(length > NFS3_MAXPATHLEN);
311 encode_uint32(xdr, length);
312 xdr_write_pages(xdr, pages, 0, length);
318 * typedef uint64 cookie3
320 static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
322 return xdr_encode_hyper(p, cookie);
328 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
330 static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
332 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
333 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
339 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
341 static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
345 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
346 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
362 static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
364 BUG_ON(type > NF3FIFO);
365 encode_uint32(xdr, type);
376 static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
380 p = xdr_reserve_space(xdr, 8);
381 *p++ = cpu_to_be32(MAJOR(rdev));
382 *p = cpu_to_be32(MINOR(rdev));
389 * opaque data<NFS3_FHSIZE>;
392 static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
396 BUG_ON(fh->size > NFS3_FHSIZE);
397 p = xdr_reserve_space(xdr, 4 + fh->size);
398 xdr_encode_opaque(p, fh->data, fh->size);
409 static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
411 *p++ = cpu_to_be32(timep->tv_sec);
412 *p++ = cpu_to_be32(timep->tv_nsec);
421 * SET_TO_SERVER_TIME = 1,
422 * SET_TO_CLIENT_TIME = 2
425 * union set_mode3 switch (bool set_it) {
432 * union set_uid3 switch (bool set_it) {
439 * union set_gid3 switch (bool set_it) {
446 * union set_size3 switch (bool set_it) {
453 * union set_atime switch (time_how set_it) {
454 * case SET_TO_CLIENT_TIME:
460 * union set_mtime switch (time_how set_it) {
461 * case SET_TO_CLIENT_TIME:
476 static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
482 * In order to make only a single xdr_reserve_space() call,
483 * pre-compute the total number of bytes to be reserved.
484 * Six boolean values, one for each set_foo field, are always
485 * present in the encoded result, so start there.
488 if (attr->ia_valid & ATTR_MODE)
490 if (attr->ia_valid & ATTR_UID)
492 if (attr->ia_valid & ATTR_GID)
494 if (attr->ia_valid & ATTR_SIZE)
496 if (attr->ia_valid & ATTR_ATIME_SET)
498 if (attr->ia_valid & ATTR_MTIME_SET)
500 p = xdr_reserve_space(xdr, nbytes);
502 if (attr->ia_valid & ATTR_MODE) {
504 *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
508 if (attr->ia_valid & ATTR_UID) {
510 *p++ = cpu_to_be32(attr->ia_uid);
514 if (attr->ia_valid & ATTR_GID) {
516 *p++ = cpu_to_be32(attr->ia_gid);
520 if (attr->ia_valid & ATTR_SIZE) {
522 p = xdr_encode_hyper(p, (u64)attr->ia_size);
526 if (attr->ia_valid & ATTR_ATIME_SET) {
528 p = xdr_encode_nfstime3(p, &attr->ia_atime);
529 } else if (attr->ia_valid & ATTR_ATIME) {
534 if (attr->ia_valid & ATTR_MTIME_SET) {
536 xdr_encode_nfstime3(p, &attr->ia_mtime);
537 } else if (attr->ia_valid & ATTR_MTIME) {
546 * struct diropargs3 {
551 static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
552 const char *name, u32 length)
554 encode_nfs_fh3(xdr, fh);
555 encode_filename3(xdr, name, length);
560 * NFSv3 XDR encode functions
562 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
563 * "NFS Version 3 Protocol Specification".
569 * struct GETATTR3args {
573 static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
574 const struct nfs_fh *fh)
576 struct xdr_stream xdr;
578 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
579 encode_nfs_fh3(&xdr, fh);
586 * union sattrguard3 switch (bool check) {
588 * nfstime3 obj_ctime;
593 * struct SETATTR3args {
595 * sattr3 new_attributes;
599 static void encode_sattrguard3(struct xdr_stream *xdr,
600 const struct nfs3_sattrargs *args)
605 p = xdr_reserve_space(xdr, 4 + 8);
607 xdr_encode_nfstime3(p, &args->guardtime);
609 p = xdr_reserve_space(xdr, 4);
614 static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
615 const struct nfs3_sattrargs *args)
617 struct xdr_stream xdr;
619 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
620 encode_nfs_fh3(&xdr, args->fh);
621 encode_sattr3(&xdr, args->sattr);
622 encode_sattrguard3(&xdr, args);
629 * struct LOOKUP3args {
633 static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
634 const struct nfs3_diropargs *args)
636 struct xdr_stream xdr;
638 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
639 encode_diropargs3(&xdr, args->fh, args->name, args->len);
646 * struct ACCESS3args {
651 static void encode_access3args(struct xdr_stream *xdr,
652 const struct nfs3_accessargs *args)
654 encode_nfs_fh3(xdr, args->fh);
655 encode_uint32(xdr, args->access);
658 static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
659 const struct nfs3_accessargs *args)
661 struct xdr_stream xdr;
663 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
664 encode_access3args(&xdr, args);
669 * 3.3.5 READLINK3args
671 * struct READLINK3args {
675 static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
676 const struct nfs3_readlinkargs *args)
678 struct xdr_stream xdr;
680 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
681 encode_nfs_fh3(&xdr, args->fh);
682 prepare_reply_buffer(req, args->pages, args->pgbase,
683 args->pglen, NFS3_readlinkres_sz);
696 static void encode_read3args(struct xdr_stream *xdr,
697 const struct nfs_readargs *args)
701 encode_nfs_fh3(xdr, args->fh);
703 p = xdr_reserve_space(xdr, 8 + 4);
704 p = xdr_encode_hyper(p, args->offset);
705 *p = cpu_to_be32(args->count);
708 static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
709 const struct nfs_readargs *args)
711 struct xdr_stream xdr;
713 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
714 encode_read3args(&xdr, args);
715 prepare_reply_buffer(req, args->pages, args->pgbase,
716 args->count, NFS3_readres_sz);
717 req->rq_rcv_buf.flags |= XDRBUF_READ;
730 * struct WRITE3args {
738 static void encode_write3args(struct xdr_stream *xdr,
739 const struct nfs_writeargs *args)
743 encode_nfs_fh3(xdr, args->fh);
745 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
746 p = xdr_encode_hyper(p, args->offset);
747 *p++ = cpu_to_be32(args->count);
749 BUG_ON(args->stable > NFS_FILE_SYNC);
750 *p++ = cpu_to_be32(args->stable);
752 *p = cpu_to_be32(args->count);
753 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
756 static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
757 const struct nfs_writeargs *args)
759 struct xdr_stream xdr;
761 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
762 encode_write3args(&xdr, args);
763 xdr.buf->flags |= XDRBUF_WRITE;
776 * union createhow3 switch (createmode3 mode) {
779 * sattr3 obj_attributes;
784 * struct CREATE3args {
789 static void encode_createhow3(struct xdr_stream *xdr,
790 const struct nfs3_createargs *args)
792 encode_uint32(xdr, args->createmode);
793 switch (args->createmode) {
794 case NFS3_CREATE_UNCHECKED:
795 case NFS3_CREATE_GUARDED:
796 encode_sattr3(xdr, args->sattr);
798 case NFS3_CREATE_EXCLUSIVE:
799 encode_createverf3(xdr, args->verifier);
806 static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
807 const struct nfs3_createargs *args)
809 struct xdr_stream xdr;
811 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
812 encode_diropargs3(&xdr, args->fh, args->name, args->len);
813 encode_createhow3(&xdr, args);
820 * struct MKDIR3args {
825 static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
826 const struct nfs3_mkdirargs *args)
828 struct xdr_stream xdr;
830 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
831 encode_diropargs3(&xdr, args->fh, args->name, args->len);
832 encode_sattr3(&xdr, args->sattr);
837 * 3.3.10 SYMLINK3args
839 * struct symlinkdata3 {
840 * sattr3 symlink_attributes;
841 * nfspath3 symlink_data;
844 * struct SYMLINK3args {
846 * symlinkdata3 symlink;
849 static void encode_symlinkdata3(struct xdr_stream *xdr,
850 const struct nfs3_symlinkargs *args)
852 encode_sattr3(xdr, args->sattr);
853 encode_nfspath3(xdr, args->pages, args->pathlen);
856 static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
857 const struct nfs3_symlinkargs *args)
859 struct xdr_stream xdr;
861 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
862 encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
863 encode_symlinkdata3(&xdr, args);
870 * struct devicedata3 {
871 * sattr3 dev_attributes;
875 * union mknoddata3 switch (ftype3 type) {
878 * devicedata3 device;
881 * sattr3 pipe_attributes;
886 * struct MKNOD3args {
891 static void encode_devicedata3(struct xdr_stream *xdr,
892 const struct nfs3_mknodargs *args)
894 encode_sattr3(xdr, args->sattr);
895 encode_specdata3(xdr, args->rdev);
898 static void encode_mknoddata3(struct xdr_stream *xdr,
899 const struct nfs3_mknodargs *args)
901 encode_ftype3(xdr, args->type);
902 switch (args->type) {
905 encode_devicedata3(xdr, args);
909 encode_sattr3(xdr, args->sattr);
919 static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
920 const struct nfs3_mknodargs *args)
922 struct xdr_stream xdr;
924 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
925 encode_diropargs3(&xdr, args->fh, args->name, args->len);
926 encode_mknoddata3(&xdr, args);
933 * struct REMOVE3args {
937 static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
938 const struct nfs_removeargs *args)
940 struct xdr_stream xdr;
942 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
943 encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
950 * struct RENAME3args {
955 static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
956 const struct nfs_renameargs *args)
958 const struct qstr *old = args->old_name;
959 const struct qstr *new = args->new_name;
960 struct xdr_stream xdr;
962 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
963 encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
964 encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
976 static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
977 const struct nfs3_linkargs *args)
979 struct xdr_stream xdr;
981 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
982 encode_nfs_fh3(&xdr, args->fromfh);
983 encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
988 * 3.3.16 READDIR3args
990 * struct READDIR3args {
993 * cookieverf3 cookieverf;
997 static void encode_readdir3args(struct xdr_stream *xdr,
998 const struct nfs3_readdirargs *args)
1002 encode_nfs_fh3(xdr, args->fh);
1004 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1005 p = xdr_encode_cookie3(p, args->cookie);
1006 p = xdr_encode_cookieverf3(p, args->verf);
1007 *p = cpu_to_be32(args->count);
1010 static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1011 const struct nfs3_readdirargs *args)
1013 struct xdr_stream xdr;
1015 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1016 encode_readdir3args(&xdr, args);
1017 prepare_reply_buffer(req, args->pages, 0,
1018 args->count, NFS3_readdirres_sz);
1023 * 3.3.17 READDIRPLUS3args
1025 * struct READDIRPLUS3args {
1028 * cookieverf3 cookieverf;
1033 static void encode_readdirplus3args(struct xdr_stream *xdr,
1034 const struct nfs3_readdirargs *args)
1038 encode_nfs_fh3(xdr, args->fh);
1040 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1041 p = xdr_encode_cookie3(p, args->cookie);
1042 p = xdr_encode_cookieverf3(p, args->verf);
1045 * readdirplus: need dircount + buffer size.
1046 * We just make sure we make dircount big enough
1048 *p++ = cpu_to_be32(args->count >> 3);
1050 *p = cpu_to_be32(args->count);
1053 static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1054 const struct nfs3_readdirargs *args)
1056 struct xdr_stream xdr;
1058 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1059 encode_readdirplus3args(&xdr, args);
1060 prepare_reply_buffer(req, args->pages, 0,
1061 args->count, NFS3_readdirres_sz);
1066 * Decode the result of a readdir call.
1067 * We just check for syntactical correctness.
1070 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1072 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1073 struct kvec *iov = rcvbuf->head;
1079 status = ntohl(*p++);
1080 /* Decode post_op_attrs */
1081 p = xdr_decode_post_op_attr(p, res->dir_attr);
1083 return nfs_stat_to_errno(status);
1084 /* Decode verifier cookie */
1086 res->verf[0] = *p++;
1087 res->verf[1] = *p++;
1092 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1093 if (iov->iov_len < hdrlen) {
1094 dprintk("NFS: READDIR reply header overflowed:"
1095 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1096 return -errno_NFSERR_IO;
1097 } else if (iov->iov_len != hdrlen) {
1098 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
1099 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1102 pglen = rcvbuf->page_len;
1103 recvd = rcvbuf->len - hdrlen;
1106 page = rcvbuf->pages;
1112 nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
1115 struct nfs_entry old = *entry;
1117 p = xdr_inline_decode(xdr, 4);
1121 p = xdr_inline_decode(xdr, 4);
1125 return ERR_PTR(-EAGAIN);
1127 return ERR_PTR(-EBADCOOKIE);
1130 p = xdr_inline_decode(xdr, 12);
1133 p = xdr_decode_hyper(p, &entry->ino);
1134 entry->len = ntohl(*p++);
1136 p = xdr_inline_decode(xdr, entry->len + 8);
1139 entry->name = (const char *) p;
1140 p += XDR_QUADLEN(entry->len);
1141 entry->prev_cookie = entry->cookie;
1142 p = xdr_decode_hyper(p, &entry->cookie);
1144 entry->d_type = DT_UNKNOWN;
1146 entry->fattr->valid = 0;
1147 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
1149 goto out_overflow_exit;
1150 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1151 /* In fact, a post_op_fh3: */
1152 p = xdr_inline_decode(xdr, 4);
1156 p = xdr_decode_fhandle_stream(xdr, entry->fh);
1158 goto out_overflow_exit;
1159 /* Ugh -- server reply was truncated */
1161 dprintk("NFS: FH truncated\n");
1163 return ERR_PTR(-EAGAIN);
1166 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
1169 p = xdr_inline_peek(xdr, 8);
1171 entry->eof = !p[0] && p[1];
1178 print_overflow_msg(__func__, xdr);
1180 return ERR_PTR(-EAGAIN);
1184 * 3.3.21 COMMIT3args
1186 * struct COMMIT3args {
1192 static void encode_commit3args(struct xdr_stream *xdr,
1193 const struct nfs_writeargs *args)
1197 encode_nfs_fh3(xdr, args->fh);
1199 p = xdr_reserve_space(xdr, 8 + 4);
1200 p = xdr_encode_hyper(p, args->offset);
1201 *p = cpu_to_be32(args->count);
1204 static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1205 const struct nfs_writeargs *args)
1207 struct xdr_stream xdr;
1209 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1210 encode_commit3args(&xdr, args);
1214 #ifdef CONFIG_NFS_V3_ACL
1216 static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1217 const struct nfs3_getaclargs *args)
1219 struct xdr_stream xdr;
1221 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1222 encode_nfs_fh3(&xdr, args->fh);
1223 encode_uint32(&xdr, args->mask);
1224 if (args->mask & (NFS_ACL | NFS_DFACL))
1225 prepare_reply_buffer(req, args->pages, 0,
1226 NFSACL_MAXPAGES << PAGE_SHIFT,
1231 static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1232 const struct nfs3_setaclargs *args)
1234 struct xdr_stream xdr;
1238 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1239 encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1240 encode_uint32(&xdr, args->mask);
1241 if (args->npages != 0)
1242 xdr_write_pages(&xdr, args->pages, 0, args->len);
1244 base = req->rq_slen;
1245 error = nfsacl_encode(xdr.buf, base, args->inode,
1246 (args->mask & NFS_ACL) ?
1247 args->acl_access : NULL, 1, 0);
1249 error = nfsacl_encode(xdr.buf, base + error, args->inode,
1250 (args->mask & NFS_DFACL) ?
1251 args->acl_default : NULL, 1,
1257 #endif /* CONFIG_NFS_V3_ACL */
1260 * NFS XDR decode functions
1264 * Decode attrstat reply.
1267 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1271 if ((status = ntohl(*p++)))
1272 return nfs_stat_to_errno(status);
1273 xdr_decode_fattr(p, fattr);
1278 * Decode status+wcc_data reply
1279 * SATTR, REMOVE, RMDIR
1282 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1286 if ((status = ntohl(*p++)))
1287 status = nfs_stat_to_errno(status);
1288 xdr_decode_wcc_data(p, fattr);
1293 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1295 return nfs3_xdr_wccstat(req, p, res->dir_attr);
1299 * Decode LOOKUP reply
1302 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1306 if ((status = ntohl(*p++))) {
1307 status = nfs_stat_to_errno(status);
1309 if (!(p = xdr_decode_fhandle(p, res->fh)))
1310 return -errno_NFSERR_IO;
1311 p = xdr_decode_post_op_attr(p, res->fattr);
1313 xdr_decode_post_op_attr(p, res->dir_attr);
1318 * Decode ACCESS reply
1321 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1323 int status = ntohl(*p++);
1325 p = xdr_decode_post_op_attr(p, res->fattr);
1327 return nfs_stat_to_errno(status);
1328 res->access = ntohl(*p++);
1333 * Decode READLINK reply
1336 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1338 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1339 struct kvec *iov = rcvbuf->head;
1344 status = ntohl(*p++);
1345 p = xdr_decode_post_op_attr(p, fattr);
1348 return nfs_stat_to_errno(status);
1350 /* Convert length of symlink */
1352 if (len >= rcvbuf->page_len) {
1353 dprintk("nfs: server returned giant symlink!\n");
1354 return -ENAMETOOLONG;
1357 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1358 if (iov->iov_len < hdrlen) {
1359 dprintk("NFS: READLINK reply header overflowed:"
1360 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1361 return -errno_NFSERR_IO;
1362 } else if (iov->iov_len != hdrlen) {
1363 dprintk("NFS: READLINK header is short. "
1364 "iovec will be shifted.\n");
1365 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1367 recvd = req->rq_rcv_buf.len - hdrlen;
1369 dprintk("NFS: server cheating in readlink reply: "
1370 "count %u > recvd %u\n", len, recvd);
1374 xdr_terminate_string(rcvbuf, len);
1382 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1384 struct kvec *iov = req->rq_rcv_buf.head;
1386 u32 count, ocount, recvd;
1389 status = ntohl(*p++);
1390 p = xdr_decode_post_op_attr(p, res->fattr);
1393 return nfs_stat_to_errno(status);
1395 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1396 * in that it puts the count both in the res struct and in the
1397 * opaque data count. */
1398 count = ntohl(*p++);
1399 res->eof = ntohl(*p++);
1400 ocount = ntohl(*p++);
1402 if (ocount != count) {
1403 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1404 return -errno_NFSERR_IO;
1407 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1408 if (iov->iov_len < hdrlen) {
1409 dprintk("NFS: READ reply header overflowed:"
1410 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1411 return -errno_NFSERR_IO;
1412 } else if (iov->iov_len != hdrlen) {
1413 dprintk("NFS: READ header is short. iovec will be shifted.\n");
1414 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
1417 recvd = req->rq_rcv_buf.len - hdrlen;
1418 if (count > recvd) {
1419 dprintk("NFS: server cheating in read reply: "
1420 "count %u > recvd %u\n", count, recvd);
1425 if (count < res->count)
1432 * Decode WRITE response
1435 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1439 status = ntohl(*p++);
1440 p = xdr_decode_wcc_data(p, res->fattr);
1443 return nfs_stat_to_errno(status);
1445 res->count = ntohl(*p++);
1446 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
1447 res->verf->verifier[0] = *p++;
1448 res->verf->verifier[1] = *p++;
1454 * Decode a CREATE response
1457 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1461 status = ntohl(*p++);
1464 if (!(p = xdr_decode_fhandle(p, res->fh)))
1465 return -errno_NFSERR_IO;
1466 p = xdr_decode_post_op_attr(p, res->fattr);
1468 memset(res->fh, 0, sizeof(*res->fh));
1469 /* Do decode post_op_attr but set it to NULL */
1470 p = xdr_decode_post_op_attr(p, res->fattr);
1471 res->fattr->valid = 0;
1474 status = nfs_stat_to_errno(status);
1476 p = xdr_decode_wcc_data(p, res->dir_attr);
1481 * Decode RENAME reply
1484 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
1488 if ((status = ntohl(*p++)) != 0)
1489 status = nfs_stat_to_errno(status);
1490 p = xdr_decode_wcc_data(p, res->old_fattr);
1491 p = xdr_decode_wcc_data(p, res->new_fattr);
1499 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1503 if ((status = ntohl(*p++)) != 0)
1504 status = nfs_stat_to_errno(status);
1505 p = xdr_decode_post_op_attr(p, res->fattr);
1506 p = xdr_decode_wcc_data(p, res->dir_attr);
1511 * Decode FSSTAT reply
1514 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1518 status = ntohl(*p++);
1520 p = xdr_decode_post_op_attr(p, res->fattr);
1522 return nfs_stat_to_errno(status);
1524 p = xdr_decode_hyper(p, &res->tbytes);
1525 p = xdr_decode_hyper(p, &res->fbytes);
1526 p = xdr_decode_hyper(p, &res->abytes);
1527 p = xdr_decode_hyper(p, &res->tfiles);
1528 p = xdr_decode_hyper(p, &res->ffiles);
1529 p = xdr_decode_hyper(p, &res->afiles);
1531 /* ignore invarsec */
1536 * Decode FSINFO reply
1539 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1543 status = ntohl(*p++);
1545 p = xdr_decode_post_op_attr(p, res->fattr);
1547 return nfs_stat_to_errno(status);
1549 res->rtmax = ntohl(*p++);
1550 res->rtpref = ntohl(*p++);
1551 res->rtmult = ntohl(*p++);
1552 res->wtmax = ntohl(*p++);
1553 res->wtpref = ntohl(*p++);
1554 res->wtmult = ntohl(*p++);
1555 res->dtpref = ntohl(*p++);
1556 p = xdr_decode_hyper(p, &res->maxfilesize);
1557 p = xdr_decode_time3(p, &res->time_delta);
1559 /* ignore properties */
1560 res->lease_time = 0;
1565 * Decode PATHCONF reply
1568 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1572 status = ntohl(*p++);
1574 p = xdr_decode_post_op_attr(p, res->fattr);
1576 return nfs_stat_to_errno(status);
1577 res->max_link = ntohl(*p++);
1578 res->max_namelen = ntohl(*p++);
1580 /* ignore remaining fields */
1585 * Decode COMMIT reply
1588 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1592 status = ntohl(*p++);
1593 p = xdr_decode_wcc_data(p, res->fattr);
1595 return nfs_stat_to_errno(status);
1597 res->verf->verifier[0] = *p++;
1598 res->verf->verifier[1] = *p++;
1602 #ifdef CONFIG_NFS_V3_ACL
1604 * Decode GETACL reply
1607 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1608 struct nfs3_getaclres *res)
1610 struct xdr_buf *buf = &req->rq_rcv_buf;
1611 int status = ntohl(*p++);
1612 struct posix_acl **acl;
1613 unsigned int *aclcnt;
1617 return nfs_stat_to_errno(status);
1618 p = xdr_decode_post_op_attr(p, res->fattr);
1619 res->mask = ntohl(*p++);
1620 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1622 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1624 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1625 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1626 err = nfsacl_decode(buf, base, aclcnt, acl);
1628 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1629 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1631 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1632 return (err > 0) ? 0 : err;
1636 * Decode setacl reply.
1639 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1641 int status = ntohl(*p++);
1644 return nfs_stat_to_errno(status);
1645 xdr_decode_post_op_attr(p, fattr);
1648 #endif /* CONFIG_NFS_V3_ACL */
1650 #define PROC(proc, argtype, restype, timer) \
1651 [NFS3PROC_##proc] = { \
1652 .p_proc = NFS3PROC_##proc, \
1653 .p_encode = (kxdrproc_t)nfs3_xdr_enc_##argtype##3args, \
1654 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1655 .p_arglen = NFS3_##argtype##args_sz, \
1656 .p_replen = NFS3_##restype##_sz, \
1658 .p_statidx = NFS3PROC_##proc, \
1662 struct rpc_procinfo nfs3_procedures[] = {
1663 PROC(GETATTR, getattr, attrstat, 1),
1664 PROC(SETATTR, setattr, wccstat, 0),
1665 PROC(LOOKUP, lookup, lookupres, 2),
1666 PROC(ACCESS, access, accessres, 1),
1667 PROC(READLINK, readlink, readlinkres, 3),
1668 PROC(READ, read, readres, 3),
1669 PROC(WRITE, write, writeres, 4),
1670 PROC(CREATE, create, createres, 0),
1671 PROC(MKDIR, mkdir, createres, 0),
1672 PROC(SYMLINK, symlink, createres, 0),
1673 PROC(MKNOD, mknod, createres, 0),
1674 PROC(REMOVE, remove, removeres, 0),
1675 PROC(RMDIR, lookup, wccstat, 0),
1676 PROC(RENAME, rename, renameres, 0),
1677 PROC(LINK, link, linkres, 0),
1678 PROC(READDIR, readdir, readdirres, 3),
1679 PROC(READDIRPLUS, readdirplus, readdirres, 3),
1680 PROC(FSSTAT, getattr, fsstatres, 0),
1681 PROC(FSINFO, getattr, fsinfores, 0),
1682 PROC(PATHCONF, getattr, pathconfres, 0),
1683 PROC(COMMIT, commit, commitres, 5),
1686 struct rpc_version nfs_version3 = {
1688 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1689 .procs = nfs3_procedures
1692 #ifdef CONFIG_NFS_V3_ACL
1693 static struct rpc_procinfo nfs3_acl_procedures[] = {
1694 [ACLPROC3_GETACL] = {
1695 .p_proc = ACLPROC3_GETACL,
1696 .p_encode = (kxdrproc_t)nfs3_xdr_enc_getacl3args,
1697 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1698 .p_arglen = ACL3_getaclargs_sz,
1699 .p_replen = ACL3_getaclres_sz,
1703 [ACLPROC3_SETACL] = {
1704 .p_proc = ACLPROC3_SETACL,
1705 .p_encode = (kxdrproc_t)nfs3_xdr_enc_setacl3args,
1706 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1707 .p_arglen = ACL3_setaclargs_sz,
1708 .p_replen = ACL3_setaclres_sz,
1714 struct rpc_version nfsacl_version3 = {
1716 .nrprocs = sizeof(nfs3_acl_procedures)/
1717 sizeof(nfs3_acl_procedures[0]),
1718 .procs = nfs3_acl_procedures,
1720 #endif /* CONFIG_NFS_V3_ACL */