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/slab.h>
13 #include <linux/utsname.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
17 #include <linux/pagemap.h>
18 #include <linux/proc_fs.h>
19 #include <linux/kdev_t.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs3.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/nfsacl.h>
26 #define NFSDBG_FACILITY NFSDBG_XDR
28 /* Mapping from NFS error code to "errno" error code. */
29 #define errno_NFSERR_IO EIO
31 extern int nfs_stat_to_errno(int);
34 * Declare the space requirements for NFS arguments and replies as
35 * number of 32bit-words
37 #define NFS3_fhandle_sz (1+16)
38 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
39 #define NFS3_sattr_sz (15)
40 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
41 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
42 #define NFS3_fattr_sz (21)
43 #define NFS3_wcc_attr_sz (6)
44 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
45 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
46 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
47 #define NFS3_fsstat_sz
48 #define NFS3_fsinfo_sz
49 #define NFS3_pathconf_sz
50 #define NFS3_entry_sz (NFS3_filename_sz+3)
52 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
53 #define NFS3_diropargs_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+NFS3_path_sz+NFS3_sattr_sz)
61 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
63 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
64 #define NFS3_readdirargs_sz (NFS3_fh_sz+2)
65 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
67 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
68 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
69 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
70 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
71 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
72 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
73 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
74 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
75 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
76 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
77 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
78 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
79 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
80 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
81 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
83 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
84 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
85 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
86 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
89 * Map file type to S_IFMT bits
93 unsigned int nfs2type
;
101 { S_IFSOCK
, NFSOCK
},
107 * Common NFS XDR functions as inlines
110 xdr_encode_fhandle(u32
*p
, struct nfs_fh
*fh
)
112 return xdr_encode_array(p
, fh
->data
, fh
->size
);
116 xdr_decode_fhandle(u32
*p
, struct nfs_fh
*fh
)
118 if ((fh
->size
= ntohl(*p
++)) <= NFS3_FHSIZE
) {
119 memcpy(fh
->data
, p
, fh
->size
);
120 return p
+ XDR_QUADLEN(fh
->size
);
126 * Encode/decode time.
129 xdr_encode_time3(u32
*p
, struct timespec
*timep
)
131 *p
++ = htonl(timep
->tv_sec
);
132 *p
++ = htonl(timep
->tv_nsec
);
137 xdr_decode_time3(u32
*p
, struct timespec
*timep
)
139 timep
->tv_sec
= ntohl(*p
++);
140 timep
->tv_nsec
= ntohl(*p
++);
145 xdr_decode_fattr(u32
*p
, struct nfs_fattr
*fattr
)
147 unsigned int type
, major
, minor
;
153 fmode
= nfs_type2fmt
[type
].mode
;
154 fattr
->type
= nfs_type2fmt
[type
].nfs2type
;
155 fattr
->mode
= (ntohl(*p
++) & ~S_IFMT
) | fmode
;
156 fattr
->nlink
= ntohl(*p
++);
157 fattr
->uid
= ntohl(*p
++);
158 fattr
->gid
= ntohl(*p
++);
159 p
= xdr_decode_hyper(p
, &fattr
->size
);
160 p
= xdr_decode_hyper(p
, &fattr
->du
.nfs3
.used
);
162 /* Turn remote device info into Linux-specific dev_t */
165 fattr
->rdev
= MKDEV(major
, minor
);
166 if (MAJOR(fattr
->rdev
) != major
|| MINOR(fattr
->rdev
) != minor
)
169 p
= xdr_decode_hyper(p
, &fattr
->fsid_u
.nfs3
);
170 p
= xdr_decode_hyper(p
, &fattr
->fileid
);
171 p
= xdr_decode_time3(p
, &fattr
->atime
);
172 p
= xdr_decode_time3(p
, &fattr
->mtime
);
173 p
= xdr_decode_time3(p
, &fattr
->ctime
);
175 /* Update the mode bits */
176 fattr
->valid
|= (NFS_ATTR_FATTR
| NFS_ATTR_FATTR_V3
);
177 fattr
->timestamp
= jiffies
;
182 xdr_encode_sattr(u32
*p
, struct iattr
*attr
)
184 if (attr
->ia_valid
& ATTR_MODE
) {
186 *p
++ = htonl(attr
->ia_mode
);
190 if (attr
->ia_valid
& ATTR_UID
) {
192 *p
++ = htonl(attr
->ia_uid
);
196 if (attr
->ia_valid
& ATTR_GID
) {
198 *p
++ = htonl(attr
->ia_gid
);
202 if (attr
->ia_valid
& ATTR_SIZE
) {
204 p
= xdr_encode_hyper(p
, (__u64
) attr
->ia_size
);
208 if (attr
->ia_valid
& ATTR_ATIME_SET
) {
210 p
= xdr_encode_time3(p
, &attr
->ia_atime
);
211 } else if (attr
->ia_valid
& ATTR_ATIME
) {
216 if (attr
->ia_valid
& ATTR_MTIME_SET
) {
218 p
= xdr_encode_time3(p
, &attr
->ia_mtime
);
219 } else if (attr
->ia_valid
& ATTR_MTIME
) {
228 xdr_decode_wcc_attr(u32
*p
, struct nfs_fattr
*fattr
)
230 p
= xdr_decode_hyper(p
, &fattr
->pre_size
);
231 p
= xdr_decode_time3(p
, &fattr
->pre_mtime
);
232 p
= xdr_decode_time3(p
, &fattr
->pre_ctime
);
233 fattr
->valid
|= NFS_ATTR_WCC
;
238 xdr_decode_post_op_attr(u32
*p
, struct nfs_fattr
*fattr
)
241 p
= xdr_decode_fattr(p
, fattr
);
246 xdr_decode_pre_op_attr(u32
*p
, struct nfs_fattr
*fattr
)
249 return xdr_decode_wcc_attr(p
, fattr
);
255 xdr_decode_wcc_data(u32
*p
, struct nfs_fattr
*fattr
)
257 p
= xdr_decode_pre_op_attr(p
, fattr
);
258 return xdr_decode_post_op_attr(p
, fattr
);
262 * NFS encode functions
266 * Encode file handle argument
269 nfs3_xdr_fhandle(struct rpc_rqst
*req
, u32
*p
, struct nfs_fh
*fh
)
271 p
= xdr_encode_fhandle(p
, fh
);
272 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
277 * Encode SETATTR arguments
280 nfs3_xdr_sattrargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_sattrargs
*args
)
282 p
= xdr_encode_fhandle(p
, args
->fh
);
283 p
= xdr_encode_sattr(p
, args
->sattr
);
284 *p
++ = htonl(args
->guard
);
286 p
= xdr_encode_time3(p
, &args
->guardtime
);
287 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
292 * Encode directory ops argument
295 nfs3_xdr_diropargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropargs
*args
)
297 p
= xdr_encode_fhandle(p
, args
->fh
);
298 p
= xdr_encode_array(p
, args
->name
, args
->len
);
299 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
304 * Encode access() argument
307 nfs3_xdr_accessargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_accessargs
*args
)
309 p
= xdr_encode_fhandle(p
, args
->fh
);
310 *p
++ = htonl(args
->access
);
311 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
316 * Arguments to a READ call. Since we read data directly into the page
317 * cache, we also set up the reply iovec here so that iov[1] points
318 * exactly to the page we want to fetch.
321 nfs3_xdr_readargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_readargs
*args
)
323 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
325 u32 count
= args
->count
;
327 p
= xdr_encode_fhandle(p
, args
->fh
);
328 p
= xdr_encode_hyper(p
, args
->offset
);
330 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
332 /* Inline the page array */
333 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readres_sz
) << 2;
334 xdr_inline_pages(&req
->rq_rcv_buf
, replen
,
335 args
->pages
, args
->pgbase
, count
);
340 * Write arguments. Splice the buffer to be written into the iovec.
343 nfs3_xdr_writeargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeargs
*args
)
345 struct xdr_buf
*sndbuf
= &req
->rq_snd_buf
;
346 u32 count
= args
->count
;
348 p
= xdr_encode_fhandle(p
, args
->fh
);
349 p
= xdr_encode_hyper(p
, args
->offset
);
351 *p
++ = htonl(args
->stable
);
353 sndbuf
->len
= xdr_adjust_iovec(sndbuf
->head
, p
);
355 /* Copy the page array */
356 xdr_encode_pages(sndbuf
, args
->pages
, args
->pgbase
, count
);
361 * Encode CREATE arguments
364 nfs3_xdr_createargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_createargs
*args
)
366 p
= xdr_encode_fhandle(p
, args
->fh
);
367 p
= xdr_encode_array(p
, args
->name
, args
->len
);
369 *p
++ = htonl(args
->createmode
);
370 if (args
->createmode
== NFS3_CREATE_EXCLUSIVE
) {
371 *p
++ = args
->verifier
[0];
372 *p
++ = args
->verifier
[1];
374 p
= xdr_encode_sattr(p
, args
->sattr
);
376 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
381 * Encode MKDIR arguments
384 nfs3_xdr_mkdirargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_mkdirargs
*args
)
386 p
= xdr_encode_fhandle(p
, args
->fh
);
387 p
= xdr_encode_array(p
, args
->name
, args
->len
);
388 p
= xdr_encode_sattr(p
, args
->sattr
);
389 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
394 * Encode SYMLINK arguments
397 nfs3_xdr_symlinkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_symlinkargs
*args
)
399 p
= xdr_encode_fhandle(p
, args
->fromfh
);
400 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
401 p
= xdr_encode_sattr(p
, args
->sattr
);
402 p
= xdr_encode_array(p
, args
->topath
, args
->tolen
);
403 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
408 * Encode MKNOD arguments
411 nfs3_xdr_mknodargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_mknodargs
*args
)
413 p
= xdr_encode_fhandle(p
, args
->fh
);
414 p
= xdr_encode_array(p
, args
->name
, args
->len
);
415 *p
++ = htonl(args
->type
);
416 p
= xdr_encode_sattr(p
, args
->sattr
);
417 if (args
->type
== NF3CHR
|| args
->type
== NF3BLK
) {
418 *p
++ = htonl(MAJOR(args
->rdev
));
419 *p
++ = htonl(MINOR(args
->rdev
));
422 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
427 * Encode RENAME arguments
430 nfs3_xdr_renameargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_renameargs
*args
)
432 p
= xdr_encode_fhandle(p
, args
->fromfh
);
433 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
434 p
= xdr_encode_fhandle(p
, args
->tofh
);
435 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
436 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
441 * Encode LINK arguments
444 nfs3_xdr_linkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_linkargs
*args
)
446 p
= xdr_encode_fhandle(p
, args
->fromfh
);
447 p
= xdr_encode_fhandle(p
, args
->tofh
);
448 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
449 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
454 * Encode arguments to readdir call
457 nfs3_xdr_readdirargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readdirargs
*args
)
459 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
461 u32 count
= args
->count
;
463 p
= xdr_encode_fhandle(p
, args
->fh
);
464 p
= xdr_encode_hyper(p
, args
->cookie
);
465 *p
++ = args
->verf
[0];
466 *p
++ = args
->verf
[1];
468 /* readdirplus: need dircount + buffer size.
469 * We just make sure we make dircount big enough */
470 *p
++ = htonl(count
>> 3);
473 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
475 /* Inline the page array */
476 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readdirres_sz
) << 2;
477 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0, count
);
482 * Decode the result of a readdir call.
483 * We just check for syntactical correctness.
486 nfs3_xdr_readdirres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readdirres
*res
)
488 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
489 struct kvec
*iov
= rcvbuf
->head
;
493 unsigned int len
, pglen
;
494 u32
*entry
, *end
, *kaddr
;
496 status
= ntohl(*p
++);
497 /* Decode post_op_attrs */
498 p
= xdr_decode_post_op_attr(p
, res
->dir_attr
);
500 return -nfs_stat_to_errno(status
);
501 /* Decode verifier cookie */
509 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
510 if (iov
->iov_len
< hdrlen
) {
511 printk(KERN_WARNING
"NFS: READDIR reply header overflowed:"
512 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
513 return -errno_NFSERR_IO
;
514 } else if (iov
->iov_len
!= hdrlen
) {
515 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
516 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
519 pglen
= rcvbuf
->page_len
;
520 recvd
= rcvbuf
->len
- hdrlen
;
523 page
= rcvbuf
->pages
;
524 kaddr
= p
= (u32
*)kmap_atomic(*page
, KM_USER0
);
525 end
= (u32
*)((char *)p
+ pglen
);
527 for (nr
= 0; *p
++; nr
++) {
530 p
+= 2; /* inode # */
531 len
= ntohl(*p
++); /* string length */
532 p
+= XDR_QUADLEN(len
) + 2; /* name + cookie */
533 if (len
> NFS3_MAXNAMLEN
) {
534 printk(KERN_WARNING
"NFS: giant filename in readdir (len %x)!\n",
553 if (len
> NFS3_FHSIZE
) {
554 printk(KERN_WARNING
"NFS: giant filehandle in "
555 "readdir (len %x)!\n", len
);
558 p
+= XDR_QUADLEN(len
);
566 if (!nr
&& (entry
[0] != 0 || entry
[1] == 0))
569 kunmap_atomic(kaddr
, KM_USER0
);
572 entry
[0] = entry
[1] = 0;
573 /* truncate listing ? */
575 printk(KERN_NOTICE
"NFS: readdir reply truncated!\n");
580 nr
= -errno_NFSERR_IO
;
585 nfs3_decode_dirent(u32
*p
, struct nfs_entry
*entry
, int plus
)
587 struct nfs_entry old
= *entry
;
591 return ERR_PTR(-EAGAIN
);
593 return ERR_PTR(-EBADCOOKIE
);
596 p
= xdr_decode_hyper(p
, &entry
->ino
);
597 entry
->len
= ntohl(*p
++);
598 entry
->name
= (const char *) p
;
599 p
+= XDR_QUADLEN(entry
->len
);
600 entry
->prev_cookie
= entry
->cookie
;
601 p
= xdr_decode_hyper(p
, &entry
->cookie
);
604 entry
->fattr
->valid
= 0;
605 p
= xdr_decode_post_op_attr(p
, entry
->fattr
);
606 /* In fact, a post_op_fh3: */
608 p
= xdr_decode_fhandle(p
, entry
->fh
);
609 /* Ugh -- server reply was truncated */
611 dprintk("NFS: FH truncated\n");
613 return ERR_PTR(-EAGAIN
);
616 memset((u8
*)(entry
->fh
), 0, sizeof(*entry
->fh
));
619 entry
->eof
= !p
[0] && p
[1];
624 * Encode COMMIT arguments
627 nfs3_xdr_commitargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeargs
*args
)
629 p
= xdr_encode_fhandle(p
, args
->fh
);
630 p
= xdr_encode_hyper(p
, args
->offset
);
631 *p
++ = htonl(args
->count
);
632 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
636 #ifdef CONFIG_NFS_V3_ACL
638 * Encode GETACL arguments
641 nfs3_xdr_getaclargs(struct rpc_rqst
*req
, u32
*p
,
642 struct nfs3_getaclargs
*args
)
644 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
647 p
= xdr_encode_fhandle(p
, args
->fh
);
648 *p
++ = htonl(args
->mask
);
649 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
651 if (args
->mask
& (NFS_ACL
| NFS_DFACL
)) {
652 /* Inline the page array */
653 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+
654 ACL3_getaclres_sz
) << 2;
655 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0,
656 NFSACL_MAXPAGES
<< PAGE_SHIFT
);
662 * Encode SETACL arguments
665 nfs3_xdr_setaclargs(struct rpc_rqst
*req
, u32
*p
,
666 struct nfs3_setaclargs
*args
)
668 struct xdr_buf
*buf
= &req
->rq_snd_buf
;
669 unsigned int base
, len_in_head
, len
= nfsacl_size(
670 (args
->mask
& NFS_ACL
) ? args
->acl_access
: NULL
,
671 (args
->mask
& NFS_DFACL
) ? args
->acl_default
: NULL
);
674 p
= xdr_encode_fhandle(p
, NFS_FH(args
->inode
));
675 *p
++ = htonl(args
->mask
);
676 base
= (char *)p
- (char *)buf
->head
->iov_base
;
677 /* put as much of the acls into head as possible. */
678 len_in_head
= min_t(unsigned int, buf
->head
->iov_len
- base
, len
);
680 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
+ (len_in_head
>> 2));
682 for (count
= 0; (count
<< PAGE_SHIFT
) < len
; count
++) {
683 args
->pages
[count
] = alloc_page(GFP_KERNEL
);
684 if (!args
->pages
[count
]) {
686 __free_page(args
->pages
[--count
]);
690 xdr_encode_pages(buf
, args
->pages
, 0, len
);
692 err
= nfsacl_encode(buf
, base
, args
->inode
,
693 (args
->mask
& NFS_ACL
) ?
694 args
->acl_access
: NULL
, 1, 0);
696 err
= nfsacl_encode(buf
, base
+ err
, args
->inode
,
697 (args
->mask
& NFS_DFACL
) ?
698 args
->acl_default
: NULL
, 1,
700 return (err
> 0) ? 0 : err
;
702 #endif /* CONFIG_NFS_V3_ACL */
705 * NFS XDR decode functions
709 * Decode attrstat reply.
712 nfs3_xdr_attrstat(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
716 if ((status
= ntohl(*p
++)))
717 return -nfs_stat_to_errno(status
);
718 xdr_decode_fattr(p
, fattr
);
723 * Decode status+wcc_data reply
724 * SATTR, REMOVE, RMDIR
727 nfs3_xdr_wccstat(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
731 if ((status
= ntohl(*p
++)))
732 status
= -nfs_stat_to_errno(status
);
733 xdr_decode_wcc_data(p
, fattr
);
738 * Decode LOOKUP reply
741 nfs3_xdr_lookupres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropres
*res
)
745 if ((status
= ntohl(*p
++))) {
746 status
= -nfs_stat_to_errno(status
);
748 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
749 return -errno_NFSERR_IO
;
750 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
752 xdr_decode_post_op_attr(p
, res
->dir_attr
);
757 * Decode ACCESS reply
760 nfs3_xdr_accessres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_accessres
*res
)
762 int status
= ntohl(*p
++);
764 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
766 return -nfs_stat_to_errno(status
);
767 res
->access
= ntohl(*p
++);
772 nfs3_xdr_readlinkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readlinkargs
*args
)
774 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
777 p
= xdr_encode_fhandle(p
, args
->fh
);
778 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
780 /* Inline the page array */
781 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readlinkres_sz
) << 2;
782 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, args
->pgbase
, args
->pglen
);
787 * Decode READLINK reply
790 nfs3_xdr_readlinkres(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
792 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
793 struct kvec
*iov
= rcvbuf
->head
;
794 int hdrlen
, len
, recvd
;
798 status
= ntohl(*p
++);
799 p
= xdr_decode_post_op_attr(p
, fattr
);
802 return -nfs_stat_to_errno(status
);
804 /* Convert length of symlink */
806 if (len
>= rcvbuf
->page_len
|| len
<= 0) {
807 dprintk(KERN_WARNING
"nfs: server returned giant symlink!\n");
808 return -ENAMETOOLONG
;
811 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
812 if (iov
->iov_len
< hdrlen
) {
813 printk(KERN_WARNING
"NFS: READLINK reply header overflowed:"
814 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
815 return -errno_NFSERR_IO
;
816 } else if (iov
->iov_len
!= hdrlen
) {
817 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
818 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
820 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
822 printk(KERN_WARNING
"NFS: server cheating in readlink reply: "
823 "count %u > recvd %u\n", len
, recvd
);
827 /* NULL terminate the string we got */
828 kaddr
= (char*)kmap_atomic(rcvbuf
->pages
[0], KM_USER0
);
829 kaddr
[len
+rcvbuf
->page_base
] = '\0';
830 kunmap_atomic(kaddr
, KM_USER0
);
838 nfs3_xdr_readres(struct rpc_rqst
*req
, u32
*p
, struct nfs_readres
*res
)
840 struct kvec
*iov
= req
->rq_rcv_buf
.head
;
841 int status
, count
, ocount
, recvd
, hdrlen
;
843 status
= ntohl(*p
++);
844 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
847 return -nfs_stat_to_errno(status
);
849 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
850 * in that it puts the count both in the res struct and in the
851 * opaque data count. */
853 res
->eof
= ntohl(*p
++);
854 ocount
= ntohl(*p
++);
856 if (ocount
!= count
) {
857 printk(KERN_WARNING
"NFS: READ count doesn't match RPC opaque count.\n");
858 return -errno_NFSERR_IO
;
861 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
862 if (iov
->iov_len
< hdrlen
) {
863 printk(KERN_WARNING
"NFS: READ reply header overflowed:"
864 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
865 return -errno_NFSERR_IO
;
866 } else if (iov
->iov_len
!= hdrlen
) {
867 dprintk("NFS: READ header is short. iovec will be shifted.\n");
868 xdr_shift_buf(&req
->rq_rcv_buf
, iov
->iov_len
- hdrlen
);
871 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
873 printk(KERN_WARNING
"NFS: server cheating in read reply: "
874 "count %d > recvd %d\n", count
, recvd
);
879 if (count
< res
->count
)
886 * Decode WRITE response
889 nfs3_xdr_writeres(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeres
*res
)
893 status
= ntohl(*p
++);
894 p
= xdr_decode_wcc_data(p
, res
->fattr
);
897 return -nfs_stat_to_errno(status
);
899 res
->count
= ntohl(*p
++);
900 res
->verf
->committed
= (enum nfs3_stable_how
)ntohl(*p
++);
901 res
->verf
->verifier
[0] = *p
++;
902 res
->verf
->verifier
[1] = *p
++;
908 * Decode a CREATE response
911 nfs3_xdr_createres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropres
*res
)
915 status
= ntohl(*p
++);
918 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
919 return -errno_NFSERR_IO
;
920 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
922 memset(res
->fh
, 0, sizeof(*res
->fh
));
923 /* Do decode post_op_attr but set it to NULL */
924 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
925 res
->fattr
->valid
= 0;
928 status
= -nfs_stat_to_errno(status
);
930 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
935 * Decode RENAME reply
938 nfs3_xdr_renameres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_renameres
*res
)
942 if ((status
= ntohl(*p
++)) != 0)
943 status
= -nfs_stat_to_errno(status
);
944 p
= xdr_decode_wcc_data(p
, res
->fromattr
);
945 p
= xdr_decode_wcc_data(p
, res
->toattr
);
953 nfs3_xdr_linkres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_linkres
*res
)
957 if ((status
= ntohl(*p
++)) != 0)
958 status
= -nfs_stat_to_errno(status
);
959 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
960 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
965 * Decode FSSTAT reply
968 nfs3_xdr_fsstatres(struct rpc_rqst
*req
, u32
*p
, struct nfs_fsstat
*res
)
972 status
= ntohl(*p
++);
974 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
976 return -nfs_stat_to_errno(status
);
978 p
= xdr_decode_hyper(p
, &res
->tbytes
);
979 p
= xdr_decode_hyper(p
, &res
->fbytes
);
980 p
= xdr_decode_hyper(p
, &res
->abytes
);
981 p
= xdr_decode_hyper(p
, &res
->tfiles
);
982 p
= xdr_decode_hyper(p
, &res
->ffiles
);
983 p
= xdr_decode_hyper(p
, &res
->afiles
);
985 /* ignore invarsec */
990 * Decode FSINFO reply
993 nfs3_xdr_fsinfores(struct rpc_rqst
*req
, u32
*p
, struct nfs_fsinfo
*res
)
997 status
= ntohl(*p
++);
999 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1001 return -nfs_stat_to_errno(status
);
1003 res
->rtmax
= ntohl(*p
++);
1004 res
->rtpref
= ntohl(*p
++);
1005 res
->rtmult
= ntohl(*p
++);
1006 res
->wtmax
= ntohl(*p
++);
1007 res
->wtpref
= ntohl(*p
++);
1008 res
->wtmult
= ntohl(*p
++);
1009 res
->dtpref
= ntohl(*p
++);
1010 p
= xdr_decode_hyper(p
, &res
->maxfilesize
);
1012 /* ignore time_delta and properties */
1013 res
->lease_time
= 0;
1018 * Decode PATHCONF reply
1021 nfs3_xdr_pathconfres(struct rpc_rqst
*req
, u32
*p
, struct nfs_pathconf
*res
)
1025 status
= ntohl(*p
++);
1027 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1029 return -nfs_stat_to_errno(status
);
1030 res
->max_link
= ntohl(*p
++);
1031 res
->max_namelen
= ntohl(*p
++);
1033 /* ignore remaining fields */
1038 * Decode COMMIT reply
1041 nfs3_xdr_commitres(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeres
*res
)
1045 status
= ntohl(*p
++);
1046 p
= xdr_decode_wcc_data(p
, res
->fattr
);
1048 return -nfs_stat_to_errno(status
);
1050 res
->verf
->verifier
[0] = *p
++;
1051 res
->verf
->verifier
[1] = *p
++;
1055 #ifdef CONFIG_NFS_V3_ACL
1057 * Decode GETACL reply
1060 nfs3_xdr_getaclres(struct rpc_rqst
*req
, u32
*p
,
1061 struct nfs3_getaclres
*res
)
1063 struct xdr_buf
*buf
= &req
->rq_rcv_buf
;
1064 int status
= ntohl(*p
++);
1065 struct posix_acl
**acl
;
1066 unsigned int *aclcnt
;
1070 return -nfs_stat_to_errno(status
);
1071 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
1072 res
->mask
= ntohl(*p
++);
1073 if (res
->mask
& ~(NFS_ACL
|NFS_ACLCNT
|NFS_DFACL
|NFS_DFACLCNT
))
1075 base
= (char *)p
- (char *)req
->rq_rcv_buf
.head
->iov_base
;
1077 acl
= (res
->mask
& NFS_ACL
) ? &res
->acl_access
: NULL
;
1078 aclcnt
= (res
->mask
& NFS_ACLCNT
) ? &res
->acl_access_count
: NULL
;
1079 err
= nfsacl_decode(buf
, base
, aclcnt
, acl
);
1081 acl
= (res
->mask
& NFS_DFACL
) ? &res
->acl_default
: NULL
;
1082 aclcnt
= (res
->mask
& NFS_DFACLCNT
) ? &res
->acl_default_count
: NULL
;
1084 err
= nfsacl_decode(buf
, base
+ err
, aclcnt
, acl
);
1085 return (err
> 0) ? 0 : err
;
1089 * Decode setacl reply.
1092 nfs3_xdr_setaclres(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
1094 int status
= ntohl(*p
++);
1097 return -nfs_stat_to_errno(status
);
1098 xdr_decode_post_op_attr(p
, fattr
);
1101 #endif /* CONFIG_NFS_V3_ACL */
1104 # define MAX(a, b) (((a) > (b))? (a) : (b))
1107 #define PROC(proc, argtype, restype, timer) \
1108 [NFS3PROC_##proc] = { \
1109 .p_proc = NFS3PROC_##proc, \
1110 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1111 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1112 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1116 struct rpc_procinfo nfs3_procedures
[] = {
1117 PROC(GETATTR
, fhandle
, attrstat
, 1),
1118 PROC(SETATTR
, sattrargs
, wccstat
, 0),
1119 PROC(LOOKUP
, diropargs
, lookupres
, 2),
1120 PROC(ACCESS
, accessargs
, accessres
, 1),
1121 PROC(READLINK
, readlinkargs
, readlinkres
, 3),
1122 PROC(READ
, readargs
, readres
, 3),
1123 PROC(WRITE
, writeargs
, writeres
, 4),
1124 PROC(CREATE
, createargs
, createres
, 0),
1125 PROC(MKDIR
, mkdirargs
, createres
, 0),
1126 PROC(SYMLINK
, symlinkargs
, createres
, 0),
1127 PROC(MKNOD
, mknodargs
, createres
, 0),
1128 PROC(REMOVE
, diropargs
, wccstat
, 0),
1129 PROC(RMDIR
, diropargs
, wccstat
, 0),
1130 PROC(RENAME
, renameargs
, renameres
, 0),
1131 PROC(LINK
, linkargs
, linkres
, 0),
1132 PROC(READDIR
, readdirargs
, readdirres
, 3),
1133 PROC(READDIRPLUS
, readdirargs
, readdirres
, 3),
1134 PROC(FSSTAT
, fhandle
, fsstatres
, 0),
1135 PROC(FSINFO
, fhandle
, fsinfores
, 0),
1136 PROC(PATHCONF
, fhandle
, pathconfres
, 0),
1137 PROC(COMMIT
, commitargs
, commitres
, 5),
1140 struct rpc_version nfs_version3
= {
1142 .nrprocs
= sizeof(nfs3_procedures
)/sizeof(nfs3_procedures
[0]),
1143 .procs
= nfs3_procedures
1146 #ifdef CONFIG_NFS_V3_ACL
1147 static struct rpc_procinfo nfs3_acl_procedures
[] = {
1148 [ACLPROC3_GETACL
] = {
1149 .p_proc
= ACLPROC3_GETACL
,
1150 .p_encode
= (kxdrproc_t
) nfs3_xdr_getaclargs
,
1151 .p_decode
= (kxdrproc_t
) nfs3_xdr_getaclres
,
1152 .p_bufsiz
= MAX(ACL3_getaclargs_sz
, ACL3_getaclres_sz
) << 2,
1155 [ACLPROC3_SETACL
] = {
1156 .p_proc
= ACLPROC3_SETACL
,
1157 .p_encode
= (kxdrproc_t
) nfs3_xdr_setaclargs
,
1158 .p_decode
= (kxdrproc_t
) nfs3_xdr_setaclres
,
1159 .p_bufsiz
= MAX(ACL3_setaclargs_sz
, ACL3_setaclres_sz
) << 2,
1164 struct rpc_version nfsacl_version3
= {
1166 .nrprocs
= sizeof(nfs3_acl_procedures
)/
1167 sizeof(nfs3_acl_procedures
[0]),
1168 .procs
= nfs3_acl_procedures
,
1170 #endif /* CONFIG_NFS_V3_ACL */