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_wcc_attr_sz (6)
41 #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_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
44 #define NFS3_fsstat_sz
45 #define NFS3_fsinfo_sz
46 #define NFS3_pathconf_sz
47 #define NFS3_entry_sz (NFS3_filename_sz+3)
49 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
50 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
51 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
52 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
53 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
54 #define NFS3_readargs_sz (NFS3_fh_sz+3)
55 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
56 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
57 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
59 #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_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
62 #define NFS3_readdirargs_sz (NFS3_fh_sz+2)
63 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
65 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
66 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
67 #define NFS3_removeres_sz (NFS3_wccstat_sz)
68 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
70 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
71 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
72 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
73 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
74 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
75 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
77 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
78 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
79 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
80 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
82 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
83 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
84 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
85 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
87 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
90 * Map file type to S_IFMT bits
92 static const umode_t nfs_type2fmt
[] = {
103 static void print_overflow_msg(const char *func
, const struct xdr_stream
*xdr
)
105 dprintk("nfs: %s: prematurely hit end of receive buffer. "
106 "Remaining buffer length is %tu words.\n",
107 func
, xdr
->end
- xdr
->p
);
111 * Common NFS XDR functions as inlines
113 static inline __be32
*
114 xdr_encode_fhandle(__be32
*p
, const struct nfs_fh
*fh
)
116 return xdr_encode_array(p
, fh
->data
, fh
->size
);
119 static inline __be32
*
120 xdr_decode_fhandle(__be32
*p
, struct nfs_fh
*fh
)
122 if ((fh
->size
= ntohl(*p
++)) <= NFS3_FHSIZE
) {
123 memcpy(fh
->data
, p
, fh
->size
);
124 return p
+ XDR_QUADLEN(fh
->size
);
129 static inline __be32
*
130 xdr_decode_fhandle_stream(struct xdr_stream
*xdr
, struct nfs_fh
*fh
)
133 p
= xdr_inline_decode(xdr
, 4);
136 fh
->size
= ntohl(*p
++);
138 if (fh
->size
<= NFS3_FHSIZE
) {
139 p
= xdr_inline_decode(xdr
, fh
->size
);
142 memcpy(fh
->data
, p
, fh
->size
);
143 return p
+ XDR_QUADLEN(fh
->size
);
148 print_overflow_msg(__func__
, xdr
);
149 return ERR_PTR(-EIO
);
153 * Encode/decode time.
155 static inline __be32
*
156 xdr_encode_time3(__be32
*p
, struct timespec
*timep
)
158 *p
++ = htonl(timep
->tv_sec
);
159 *p
++ = htonl(timep
->tv_nsec
);
163 static inline __be32
*
164 xdr_decode_time3(__be32
*p
, struct timespec
*timep
)
166 timep
->tv_sec
= ntohl(*p
++);
167 timep
->tv_nsec
= ntohl(*p
++);
172 xdr_decode_fattr(__be32
*p
, struct nfs_fattr
*fattr
)
174 unsigned int type
, major
, minor
;
180 fmode
= nfs_type2fmt
[type
];
181 fattr
->mode
= (ntohl(*p
++) & ~S_IFMT
) | fmode
;
182 fattr
->nlink
= ntohl(*p
++);
183 fattr
->uid
= ntohl(*p
++);
184 fattr
->gid
= ntohl(*p
++);
185 p
= xdr_decode_hyper(p
, &fattr
->size
);
186 p
= xdr_decode_hyper(p
, &fattr
->du
.nfs3
.used
);
188 /* Turn remote device info into Linux-specific dev_t */
191 fattr
->rdev
= MKDEV(major
, minor
);
192 if (MAJOR(fattr
->rdev
) != major
|| MINOR(fattr
->rdev
) != minor
)
195 p
= xdr_decode_hyper(p
, &fattr
->fsid
.major
);
196 fattr
->fsid
.minor
= 0;
197 p
= xdr_decode_hyper(p
, &fattr
->fileid
);
198 p
= xdr_decode_time3(p
, &fattr
->atime
);
199 p
= xdr_decode_time3(p
, &fattr
->mtime
);
200 p
= xdr_decode_time3(p
, &fattr
->ctime
);
202 /* Update the mode bits */
203 fattr
->valid
|= NFS_ATTR_FATTR_V3
;
207 static inline __be32
*
208 xdr_encode_sattr(__be32
*p
, struct iattr
*attr
)
210 if (attr
->ia_valid
& ATTR_MODE
) {
212 *p
++ = htonl(attr
->ia_mode
& S_IALLUGO
);
216 if (attr
->ia_valid
& ATTR_UID
) {
218 *p
++ = htonl(attr
->ia_uid
);
222 if (attr
->ia_valid
& ATTR_GID
) {
224 *p
++ = htonl(attr
->ia_gid
);
228 if (attr
->ia_valid
& ATTR_SIZE
) {
230 p
= xdr_encode_hyper(p
, (__u64
) attr
->ia_size
);
234 if (attr
->ia_valid
& ATTR_ATIME_SET
) {
236 p
= xdr_encode_time3(p
, &attr
->ia_atime
);
237 } else if (attr
->ia_valid
& ATTR_ATIME
) {
242 if (attr
->ia_valid
& ATTR_MTIME_SET
) {
244 p
= xdr_encode_time3(p
, &attr
->ia_mtime
);
245 } else if (attr
->ia_valid
& ATTR_MTIME
) {
253 static inline __be32
*
254 xdr_decode_wcc_attr(__be32
*p
, struct nfs_fattr
*fattr
)
256 p
= xdr_decode_hyper(p
, &fattr
->pre_size
);
257 p
= xdr_decode_time3(p
, &fattr
->pre_mtime
);
258 p
= xdr_decode_time3(p
, &fattr
->pre_ctime
);
259 fattr
->valid
|= NFS_ATTR_FATTR_PRESIZE
260 | NFS_ATTR_FATTR_PREMTIME
261 | NFS_ATTR_FATTR_PRECTIME
;
265 static inline __be32
*
266 xdr_decode_post_op_attr(__be32
*p
, struct nfs_fattr
*fattr
)
269 p
= xdr_decode_fattr(p
, fattr
);
273 static inline __be32
*
274 xdr_decode_post_op_attr_stream(struct xdr_stream
*xdr
, struct nfs_fattr
*fattr
)
278 p
= xdr_inline_decode(xdr
, 4);
282 p
= xdr_inline_decode(xdr
, 84);
285 p
= xdr_decode_fattr(p
, fattr
);
289 print_overflow_msg(__func__
, xdr
);
290 return ERR_PTR(-EIO
);
293 static inline __be32
*
294 xdr_decode_pre_op_attr(__be32
*p
, struct nfs_fattr
*fattr
)
297 return xdr_decode_wcc_attr(p
, fattr
);
302 static inline __be32
*
303 xdr_decode_wcc_data(__be32
*p
, struct nfs_fattr
*fattr
)
305 p
= xdr_decode_pre_op_attr(p
, fattr
);
306 return xdr_decode_post_op_attr(p
, fattr
);
310 * NFS encode functions
314 * Encode file handle argument
317 nfs3_xdr_fhandle(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fh
*fh
)
319 p
= xdr_encode_fhandle(p
, fh
);
320 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
325 * Encode SETATTR arguments
328 nfs3_xdr_sattrargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_sattrargs
*args
)
330 p
= xdr_encode_fhandle(p
, args
->fh
);
331 p
= xdr_encode_sattr(p
, args
->sattr
);
332 *p
++ = htonl(args
->guard
);
334 p
= xdr_encode_time3(p
, &args
->guardtime
);
335 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
340 * Encode directory ops argument
343 nfs3_xdr_diropargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_diropargs
*args
)
345 p
= xdr_encode_fhandle(p
, args
->fh
);
346 p
= xdr_encode_array(p
, args
->name
, args
->len
);
347 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
352 * Encode REMOVE argument
355 nfs3_xdr_removeargs(struct rpc_rqst
*req
, __be32
*p
, const struct nfs_removeargs
*args
)
357 p
= xdr_encode_fhandle(p
, args
->fh
);
358 p
= xdr_encode_array(p
, args
->name
.name
, args
->name
.len
);
359 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
364 * Encode access() argument
367 nfs3_xdr_accessargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_accessargs
*args
)
369 p
= xdr_encode_fhandle(p
, args
->fh
);
370 *p
++ = htonl(args
->access
);
371 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
376 * 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
378 * exactly to the page we want to fetch.
381 nfs3_xdr_readargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readargs
*args
)
383 struct rpc_auth
*auth
= req
->rq_cred
->cr_auth
;
385 u32 count
= args
->count
;
387 p
= xdr_encode_fhandle(p
, args
->fh
);
388 p
= xdr_encode_hyper(p
, args
->offset
);
390 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
392 /* Inline the page array */
393 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readres_sz
) << 2;
394 xdr_inline_pages(&req
->rq_rcv_buf
, replen
,
395 args
->pages
, args
->pgbase
, count
);
396 req
->rq_rcv_buf
.flags
|= XDRBUF_READ
;
401 * Write arguments. Splice the buffer to be written into the iovec.
404 nfs3_xdr_writeargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeargs
*args
)
406 struct xdr_buf
*sndbuf
= &req
->rq_snd_buf
;
407 u32 count
= args
->count
;
409 p
= xdr_encode_fhandle(p
, args
->fh
);
410 p
= xdr_encode_hyper(p
, args
->offset
);
412 *p
++ = htonl(args
->stable
);
414 sndbuf
->len
= xdr_adjust_iovec(sndbuf
->head
, p
);
416 /* Copy the page array */
417 xdr_encode_pages(sndbuf
, args
->pages
, args
->pgbase
, count
);
418 sndbuf
->flags
|= XDRBUF_WRITE
;
423 * Encode CREATE arguments
426 nfs3_xdr_createargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_createargs
*args
)
428 p
= xdr_encode_fhandle(p
, args
->fh
);
429 p
= xdr_encode_array(p
, args
->name
, args
->len
);
431 *p
++ = htonl(args
->createmode
);
432 if (args
->createmode
== NFS3_CREATE_EXCLUSIVE
) {
433 *p
++ = args
->verifier
[0];
434 *p
++ = args
->verifier
[1];
436 p
= xdr_encode_sattr(p
, args
->sattr
);
438 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
443 * Encode MKDIR arguments
446 nfs3_xdr_mkdirargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_mkdirargs
*args
)
448 p
= xdr_encode_fhandle(p
, args
->fh
);
449 p
= xdr_encode_array(p
, args
->name
, args
->len
);
450 p
= xdr_encode_sattr(p
, args
->sattr
);
451 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
456 * Encode SYMLINK arguments
459 nfs3_xdr_symlinkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_symlinkargs
*args
)
461 p
= xdr_encode_fhandle(p
, args
->fromfh
);
462 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
463 p
= xdr_encode_sattr(p
, args
->sattr
);
464 *p
++ = htonl(args
->pathlen
);
465 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
468 xdr_encode_pages(&req
->rq_snd_buf
, args
->pages
, 0, args
->pathlen
);
473 * Encode MKNOD arguments
476 nfs3_xdr_mknodargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_mknodargs
*args
)
478 p
= xdr_encode_fhandle(p
, args
->fh
);
479 p
= xdr_encode_array(p
, args
->name
, args
->len
);
480 *p
++ = htonl(args
->type
);
481 p
= xdr_encode_sattr(p
, args
->sattr
);
482 if (args
->type
== NF3CHR
|| args
->type
== NF3BLK
) {
483 *p
++ = htonl(MAJOR(args
->rdev
));
484 *p
++ = htonl(MINOR(args
->rdev
));
487 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
492 * Encode RENAME arguments
495 nfs3_xdr_renameargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_renameargs
*args
)
497 p
= xdr_encode_fhandle(p
, args
->old_dir
);
498 p
= xdr_encode_array(p
, args
->old_name
->name
, args
->old_name
->len
);
499 p
= xdr_encode_fhandle(p
, args
->new_dir
);
500 p
= xdr_encode_array(p
, args
->new_name
->name
, args
->new_name
->len
);
501 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
506 * Encode LINK arguments
509 nfs3_xdr_linkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_linkargs
*args
)
511 p
= xdr_encode_fhandle(p
, args
->fromfh
);
512 p
= xdr_encode_fhandle(p
, args
->tofh
);
513 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
514 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
519 * Encode arguments to readdir call
522 nfs3_xdr_readdirargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_readdirargs
*args
)
524 struct rpc_auth
*auth
= req
->rq_cred
->cr_auth
;
526 u32 count
= args
->count
;
528 p
= xdr_encode_fhandle(p
, args
->fh
);
529 p
= xdr_encode_hyper(p
, args
->cookie
);
530 *p
++ = args
->verf
[0];
531 *p
++ = args
->verf
[1];
533 /* readdirplus: need dircount + buffer size.
534 * We just make sure we make dircount big enough */
535 *p
++ = htonl(count
>> 3);
538 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
540 /* Inline the page array */
541 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readdirres_sz
) << 2;
542 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0, count
);
547 * Decode the result of a readdir call.
548 * We just check for syntactical correctness.
551 nfs3_xdr_readdirres(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_readdirres
*res
)
553 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
554 struct kvec
*iov
= rcvbuf
->head
;
560 status
= ntohl(*p
++);
561 /* Decode post_op_attrs */
562 p
= xdr_decode_post_op_attr(p
, res
->dir_attr
);
564 return nfs_stat_to_errno(status
);
565 /* Decode verifier cookie */
573 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
574 if (iov
->iov_len
< hdrlen
) {
575 dprintk("NFS: READDIR reply header overflowed:"
576 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
577 return -errno_NFSERR_IO
;
578 } else if (iov
->iov_len
!= hdrlen
) {
579 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
580 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
583 pglen
= rcvbuf
->page_len
;
584 recvd
= rcvbuf
->len
- hdrlen
;
587 page
= rcvbuf
->pages
;
593 nfs3_decode_dirent(struct xdr_stream
*xdr
, struct nfs_entry
*entry
, struct nfs_server
*server
, int plus
)
596 struct nfs_entry old
= *entry
;
598 p
= xdr_inline_decode(xdr
, 4);
602 p
= xdr_inline_decode(xdr
, 4);
606 return ERR_PTR(-EAGAIN
);
608 return ERR_PTR(-EBADCOOKIE
);
611 p
= xdr_inline_decode(xdr
, 12);
614 p
= xdr_decode_hyper(p
, &entry
->ino
);
615 entry
->len
= ntohl(*p
++);
617 p
= xdr_inline_decode(xdr
, entry
->len
+ 8);
620 entry
->name
= (const char *) p
;
621 p
+= XDR_QUADLEN(entry
->len
);
622 entry
->prev_cookie
= entry
->cookie
;
623 p
= xdr_decode_hyper(p
, &entry
->cookie
);
625 entry
->d_type
= DT_UNKNOWN
;
627 entry
->fattr
->valid
= 0;
628 p
= xdr_decode_post_op_attr_stream(xdr
, entry
->fattr
);
630 goto out_overflow_exit
;
631 entry
->d_type
= nfs_umode_to_dtype(entry
->fattr
->mode
);
632 /* In fact, a post_op_fh3: */
633 p
= xdr_inline_decode(xdr
, 4);
637 p
= xdr_decode_fhandle_stream(xdr
, entry
->fh
);
639 goto out_overflow_exit
;
640 /* Ugh -- server reply was truncated */
642 dprintk("NFS: FH truncated\n");
644 return ERR_PTR(-EAGAIN
);
647 memset((u8
*)(entry
->fh
), 0, sizeof(*entry
->fh
));
650 p
= xdr_inline_peek(xdr
, 8);
652 entry
->eof
= !p
[0] && p
[1];
659 print_overflow_msg(__func__
, xdr
);
661 return ERR_PTR(-EAGAIN
);
665 * Encode COMMIT arguments
668 nfs3_xdr_commitargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeargs
*args
)
670 p
= xdr_encode_fhandle(p
, args
->fh
);
671 p
= xdr_encode_hyper(p
, args
->offset
);
672 *p
++ = htonl(args
->count
);
673 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
677 #ifdef CONFIG_NFS_V3_ACL
679 * Encode GETACL arguments
682 nfs3_xdr_getaclargs(struct rpc_rqst
*req
, __be32
*p
,
683 struct nfs3_getaclargs
*args
)
685 struct rpc_auth
*auth
= req
->rq_cred
->cr_auth
;
688 p
= xdr_encode_fhandle(p
, args
->fh
);
689 *p
++ = htonl(args
->mask
);
690 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
692 if (args
->mask
& (NFS_ACL
| NFS_DFACL
)) {
693 /* Inline the page array */
694 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+
695 ACL3_getaclres_sz
) << 2;
696 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0,
697 NFSACL_MAXPAGES
<< PAGE_SHIFT
);
703 * Encode SETACL arguments
706 nfs3_xdr_setaclargs(struct rpc_rqst
*req
, __be32
*p
,
707 struct nfs3_setaclargs
*args
)
709 struct xdr_buf
*buf
= &req
->rq_snd_buf
;
713 p
= xdr_encode_fhandle(p
, NFS_FH(args
->inode
));
714 *p
++ = htonl(args
->mask
);
715 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
718 if (args
->npages
!= 0)
719 xdr_encode_pages(buf
, args
->pages
, 0, args
->len
);
721 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
,
722 p
+ XDR_QUADLEN(args
->len
));
724 err
= nfsacl_encode(buf
, base
, args
->inode
,
725 (args
->mask
& NFS_ACL
) ?
726 args
->acl_access
: NULL
, 1, 0);
728 err
= nfsacl_encode(buf
, base
+ err
, args
->inode
,
729 (args
->mask
& NFS_DFACL
) ?
730 args
->acl_default
: NULL
, 1,
732 return (err
> 0) ? 0 : err
;
734 #endif /* CONFIG_NFS_V3_ACL */
737 * NFS XDR decode functions
741 * Decode attrstat reply.
744 nfs3_xdr_attrstat(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fattr
*fattr
)
748 if ((status
= ntohl(*p
++)))
749 return nfs_stat_to_errno(status
);
750 xdr_decode_fattr(p
, fattr
);
755 * Decode status+wcc_data reply
756 * SATTR, REMOVE, RMDIR
759 nfs3_xdr_wccstat(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fattr
*fattr
)
763 if ((status
= ntohl(*p
++)))
764 status
= nfs_stat_to_errno(status
);
765 xdr_decode_wcc_data(p
, fattr
);
770 nfs3_xdr_removeres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_removeres
*res
)
772 return nfs3_xdr_wccstat(req
, p
, res
->dir_attr
);
776 * Decode LOOKUP reply
779 nfs3_xdr_lookupres(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_diropres
*res
)
783 if ((status
= ntohl(*p
++))) {
784 status
= nfs_stat_to_errno(status
);
786 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
787 return -errno_NFSERR_IO
;
788 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
790 xdr_decode_post_op_attr(p
, res
->dir_attr
);
795 * Decode ACCESS reply
798 nfs3_xdr_accessres(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_accessres
*res
)
800 int status
= ntohl(*p
++);
802 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
804 return nfs_stat_to_errno(status
);
805 res
->access
= ntohl(*p
++);
810 nfs3_xdr_readlinkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_readlinkargs
*args
)
812 struct rpc_auth
*auth
= req
->rq_cred
->cr_auth
;
815 p
= xdr_encode_fhandle(p
, args
->fh
);
816 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
818 /* Inline the page array */
819 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readlinkres_sz
) << 2;
820 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, args
->pgbase
, args
->pglen
);
825 * Decode READLINK reply
828 nfs3_xdr_readlinkres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fattr
*fattr
)
830 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
831 struct kvec
*iov
= rcvbuf
->head
;
836 status
= ntohl(*p
++);
837 p
= xdr_decode_post_op_attr(p
, fattr
);
840 return nfs_stat_to_errno(status
);
842 /* Convert length of symlink */
844 if (len
>= rcvbuf
->page_len
) {
845 dprintk("nfs: server returned giant symlink!\n");
846 return -ENAMETOOLONG
;
849 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
850 if (iov
->iov_len
< hdrlen
) {
851 dprintk("NFS: READLINK reply header overflowed:"
852 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
853 return -errno_NFSERR_IO
;
854 } else if (iov
->iov_len
!= hdrlen
) {
855 dprintk("NFS: READLINK header is short. "
856 "iovec will be shifted.\n");
857 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
859 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
861 dprintk("NFS: server cheating in readlink reply: "
862 "count %u > recvd %u\n", len
, recvd
);
866 xdr_terminate_string(rcvbuf
, len
);
874 nfs3_xdr_readres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readres
*res
)
876 struct kvec
*iov
= req
->rq_rcv_buf
.head
;
878 u32 count
, ocount
, recvd
;
881 status
= ntohl(*p
++);
882 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
885 return nfs_stat_to_errno(status
);
887 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
888 * in that it puts the count both in the res struct and in the
889 * opaque data count. */
891 res
->eof
= ntohl(*p
++);
892 ocount
= ntohl(*p
++);
894 if (ocount
!= count
) {
895 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
896 return -errno_NFSERR_IO
;
899 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
900 if (iov
->iov_len
< hdrlen
) {
901 dprintk("NFS: READ reply header overflowed:"
902 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
903 return -errno_NFSERR_IO
;
904 } else if (iov
->iov_len
!= hdrlen
) {
905 dprintk("NFS: READ header is short. iovec will be shifted.\n");
906 xdr_shift_buf(&req
->rq_rcv_buf
, iov
->iov_len
- hdrlen
);
909 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
911 dprintk("NFS: server cheating in read reply: "
912 "count %u > recvd %u\n", count
, recvd
);
917 if (count
< res
->count
)
924 * Decode WRITE response
927 nfs3_xdr_writeres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeres
*res
)
931 status
= ntohl(*p
++);
932 p
= xdr_decode_wcc_data(p
, res
->fattr
);
935 return nfs_stat_to_errno(status
);
937 res
->count
= ntohl(*p
++);
938 res
->verf
->committed
= (enum nfs3_stable_how
)ntohl(*p
++);
939 res
->verf
->verifier
[0] = *p
++;
940 res
->verf
->verifier
[1] = *p
++;
946 * Decode a CREATE response
949 nfs3_xdr_createres(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_diropres
*res
)
953 status
= ntohl(*p
++);
956 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
957 return -errno_NFSERR_IO
;
958 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
960 memset(res
->fh
, 0, sizeof(*res
->fh
));
961 /* Do decode post_op_attr but set it to NULL */
962 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
963 res
->fattr
->valid
= 0;
966 status
= nfs_stat_to_errno(status
);
968 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
973 * Decode RENAME reply
976 nfs3_xdr_renameres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_renameres
*res
)
980 if ((status
= ntohl(*p
++)) != 0)
981 status
= nfs_stat_to_errno(status
);
982 p
= xdr_decode_wcc_data(p
, res
->old_fattr
);
983 p
= xdr_decode_wcc_data(p
, res
->new_fattr
);
991 nfs3_xdr_linkres(struct rpc_rqst
*req
, __be32
*p
, struct nfs3_linkres
*res
)
995 if ((status
= ntohl(*p
++)) != 0)
996 status
= nfs_stat_to_errno(status
);
997 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
998 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
1003 * Decode FSSTAT reply
1006 nfs3_xdr_fsstatres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fsstat
*res
)
1010 status
= ntohl(*p
++);
1012 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1014 return nfs_stat_to_errno(status
);
1016 p
= xdr_decode_hyper(p
, &res
->tbytes
);
1017 p
= xdr_decode_hyper(p
, &res
->fbytes
);
1018 p
= xdr_decode_hyper(p
, &res
->abytes
);
1019 p
= xdr_decode_hyper(p
, &res
->tfiles
);
1020 p
= xdr_decode_hyper(p
, &res
->ffiles
);
1021 p
= xdr_decode_hyper(p
, &res
->afiles
);
1023 /* ignore invarsec */
1028 * Decode FSINFO reply
1031 nfs3_xdr_fsinfores(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fsinfo
*res
)
1035 status
= ntohl(*p
++);
1037 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1039 return nfs_stat_to_errno(status
);
1041 res
->rtmax
= ntohl(*p
++);
1042 res
->rtpref
= ntohl(*p
++);
1043 res
->rtmult
= ntohl(*p
++);
1044 res
->wtmax
= ntohl(*p
++);
1045 res
->wtpref
= ntohl(*p
++);
1046 res
->wtmult
= ntohl(*p
++);
1047 res
->dtpref
= ntohl(*p
++);
1048 p
= xdr_decode_hyper(p
, &res
->maxfilesize
);
1049 p
= xdr_decode_time3(p
, &res
->time_delta
);
1051 /* ignore properties */
1052 res
->lease_time
= 0;
1057 * Decode PATHCONF reply
1060 nfs3_xdr_pathconfres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_pathconf
*res
)
1064 status
= ntohl(*p
++);
1066 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1068 return nfs_stat_to_errno(status
);
1069 res
->max_link
= ntohl(*p
++);
1070 res
->max_namelen
= ntohl(*p
++);
1072 /* ignore remaining fields */
1077 * Decode COMMIT reply
1080 nfs3_xdr_commitres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeres
*res
)
1084 status
= ntohl(*p
++);
1085 p
= xdr_decode_wcc_data(p
, res
->fattr
);
1087 return nfs_stat_to_errno(status
);
1089 res
->verf
->verifier
[0] = *p
++;
1090 res
->verf
->verifier
[1] = *p
++;
1094 #ifdef CONFIG_NFS_V3_ACL
1096 * Decode GETACL reply
1099 nfs3_xdr_getaclres(struct rpc_rqst
*req
, __be32
*p
,
1100 struct nfs3_getaclres
*res
)
1102 struct xdr_buf
*buf
= &req
->rq_rcv_buf
;
1103 int status
= ntohl(*p
++);
1104 struct posix_acl
**acl
;
1105 unsigned int *aclcnt
;
1109 return nfs_stat_to_errno(status
);
1110 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1111 res
->mask
= ntohl(*p
++);
1112 if (res
->mask
& ~(NFS_ACL
|NFS_ACLCNT
|NFS_DFACL
|NFS_DFACLCNT
))
1114 base
= (char *)p
- (char *)req
->rq_rcv_buf
.head
->iov_base
;
1116 acl
= (res
->mask
& NFS_ACL
) ? &res
->acl_access
: NULL
;
1117 aclcnt
= (res
->mask
& NFS_ACLCNT
) ? &res
->acl_access_count
: NULL
;
1118 err
= nfsacl_decode(buf
, base
, aclcnt
, acl
);
1120 acl
= (res
->mask
& NFS_DFACL
) ? &res
->acl_default
: NULL
;
1121 aclcnt
= (res
->mask
& NFS_DFACLCNT
) ? &res
->acl_default_count
: NULL
;
1123 err
= nfsacl_decode(buf
, base
+ err
, aclcnt
, acl
);
1124 return (err
> 0) ? 0 : err
;
1128 * Decode setacl reply.
1131 nfs3_xdr_setaclres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fattr
*fattr
)
1133 int status
= ntohl(*p
++);
1136 return nfs_stat_to_errno(status
);
1137 xdr_decode_post_op_attr(p
, fattr
);
1140 #endif /* CONFIG_NFS_V3_ACL */
1142 #define PROC(proc, argtype, restype, timer) \
1143 [NFS3PROC_##proc] = { \
1144 .p_proc = NFS3PROC_##proc, \
1145 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1146 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1147 .p_arglen = NFS3_##argtype##_sz, \
1148 .p_replen = NFS3_##restype##_sz, \
1150 .p_statidx = NFS3PROC_##proc, \
1154 struct rpc_procinfo nfs3_procedures
[] = {
1155 PROC(GETATTR
, fhandle
, attrstat
, 1),
1156 PROC(SETATTR
, sattrargs
, wccstat
, 0),
1157 PROC(LOOKUP
, diropargs
, lookupres
, 2),
1158 PROC(ACCESS
, accessargs
, accessres
, 1),
1159 PROC(READLINK
, readlinkargs
, readlinkres
, 3),
1160 PROC(READ
, readargs
, readres
, 3),
1161 PROC(WRITE
, writeargs
, writeres
, 4),
1162 PROC(CREATE
, createargs
, createres
, 0),
1163 PROC(MKDIR
, mkdirargs
, createres
, 0),
1164 PROC(SYMLINK
, symlinkargs
, createres
, 0),
1165 PROC(MKNOD
, mknodargs
, createres
, 0),
1166 PROC(REMOVE
, removeargs
, removeres
, 0),
1167 PROC(RMDIR
, diropargs
, wccstat
, 0),
1168 PROC(RENAME
, renameargs
, renameres
, 0),
1169 PROC(LINK
, linkargs
, linkres
, 0),
1170 PROC(READDIR
, readdirargs
, readdirres
, 3),
1171 PROC(READDIRPLUS
, readdirargs
, readdirres
, 3),
1172 PROC(FSSTAT
, fhandle
, fsstatres
, 0),
1173 PROC(FSINFO
, fhandle
, fsinfores
, 0),
1174 PROC(PATHCONF
, fhandle
, pathconfres
, 0),
1175 PROC(COMMIT
, commitargs
, commitres
, 5),
1178 struct rpc_version nfs_version3
= {
1180 .nrprocs
= ARRAY_SIZE(nfs3_procedures
),
1181 .procs
= nfs3_procedures
1184 #ifdef CONFIG_NFS_V3_ACL
1185 static struct rpc_procinfo nfs3_acl_procedures
[] = {
1186 [ACLPROC3_GETACL
] = {
1187 .p_proc
= ACLPROC3_GETACL
,
1188 .p_encode
= (kxdrproc_t
) nfs3_xdr_getaclargs
,
1189 .p_decode
= (kxdrproc_t
) nfs3_xdr_getaclres
,
1190 .p_arglen
= ACL3_getaclargs_sz
,
1191 .p_replen
= ACL3_getaclres_sz
,
1195 [ACLPROC3_SETACL
] = {
1196 .p_proc
= ACLPROC3_SETACL
,
1197 .p_encode
= (kxdrproc_t
) nfs3_xdr_setaclargs
,
1198 .p_decode
= (kxdrproc_t
) nfs3_xdr_setaclres
,
1199 .p_arglen
= ACL3_setaclargs_sz
,
1200 .p_replen
= ACL3_setaclres_sz
,
1206 struct rpc_version nfsacl_version3
= {
1208 .nrprocs
= sizeof(nfs3_acl_procedures
)/
1209 sizeof(nfs3_acl_procedures
[0]),
1210 .procs
= nfs3_acl_procedures
,
1212 #endif /* CONFIG_NFS_V3_ACL */