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>
25 #define NFSDBG_FACILITY NFSDBG_XDR
27 /* Mapping from NFS error code to "errno" error code. */
28 #define errno_NFSERR_IO EIO
30 extern int nfs_stat_to_errno(int);
33 * Declare the space requirements for NFS arguments and replies as
34 * number of 32bit-words
36 #define NFS3_fhandle_sz (1+16)
37 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
38 #define NFS3_sattr_sz (15)
39 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
40 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
41 #define NFS3_fattr_sz (21)
42 #define NFS3_wcc_attr_sz (6)
43 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
44 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
45 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
46 #define NFS3_fsstat_sz
47 #define NFS3_fsinfo_sz
48 #define NFS3_pathconf_sz
49 #define NFS3_entry_sz (NFS3_filename_sz+3)
51 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
52 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
53 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
54 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
55 #define NFS3_readargs_sz (NFS3_fh_sz+3)
56 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
57 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
60 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
61 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
62 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
63 #define NFS3_readdirargs_sz (NFS3_fh_sz+2)
64 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
66 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
67 #define NFS3_wccstat_sz (1+NFS3_wcc_data_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)
83 * Map file type to S_IFMT bits
87 unsigned int nfs2type
;
101 * Common NFS XDR functions as inlines
104 xdr_encode_fhandle(u32
*p
, struct nfs_fh
*fh
)
106 return xdr_encode_array(p
, fh
->data
, fh
->size
);
110 xdr_decode_fhandle(u32
*p
, struct nfs_fh
*fh
)
112 if ((fh
->size
= ntohl(*p
++)) <= NFS3_FHSIZE
) {
113 memcpy(fh
->data
, p
, fh
->size
);
114 return p
+ XDR_QUADLEN(fh
->size
);
120 * Encode/decode time.
123 xdr_encode_time3(u32
*p
, struct timespec
*timep
)
125 *p
++ = htonl(timep
->tv_sec
);
126 *p
++ = htonl(timep
->tv_nsec
);
131 xdr_decode_time3(u32
*p
, struct timespec
*timep
)
133 timep
->tv_sec
= ntohl(*p
++);
134 timep
->tv_nsec
= ntohl(*p
++);
139 xdr_decode_fattr(u32
*p
, struct nfs_fattr
*fattr
)
141 unsigned int type
, major
, minor
;
147 fmode
= nfs_type2fmt
[type
].mode
;
148 fattr
->type
= nfs_type2fmt
[type
].nfs2type
;
149 fattr
->mode
= (ntohl(*p
++) & ~S_IFMT
) | fmode
;
150 fattr
->nlink
= ntohl(*p
++);
151 fattr
->uid
= ntohl(*p
++);
152 fattr
->gid
= ntohl(*p
++);
153 p
= xdr_decode_hyper(p
, &fattr
->size
);
154 p
= xdr_decode_hyper(p
, &fattr
->du
.nfs3
.used
);
156 /* Turn remote device info into Linux-specific dev_t */
159 fattr
->rdev
= MKDEV(major
, minor
);
160 if (MAJOR(fattr
->rdev
) != major
|| MINOR(fattr
->rdev
) != minor
)
163 p
= xdr_decode_hyper(p
, &fattr
->fsid_u
.nfs3
);
164 p
= xdr_decode_hyper(p
, &fattr
->fileid
);
165 p
= xdr_decode_time3(p
, &fattr
->atime
);
166 p
= xdr_decode_time3(p
, &fattr
->mtime
);
167 p
= xdr_decode_time3(p
, &fattr
->ctime
);
169 /* Update the mode bits */
170 fattr
->valid
|= (NFS_ATTR_FATTR
| NFS_ATTR_FATTR_V3
);
171 fattr
->timestamp
= jiffies
;
176 xdr_encode_sattr(u32
*p
, struct iattr
*attr
)
178 if (attr
->ia_valid
& ATTR_MODE
) {
180 *p
++ = htonl(attr
->ia_mode
);
184 if (attr
->ia_valid
& ATTR_UID
) {
186 *p
++ = htonl(attr
->ia_uid
);
190 if (attr
->ia_valid
& ATTR_GID
) {
192 *p
++ = htonl(attr
->ia_gid
);
196 if (attr
->ia_valid
& ATTR_SIZE
) {
198 p
= xdr_encode_hyper(p
, (__u64
) attr
->ia_size
);
202 if (attr
->ia_valid
& ATTR_ATIME_SET
) {
204 p
= xdr_encode_time3(p
, &attr
->ia_atime
);
205 } else if (attr
->ia_valid
& ATTR_ATIME
) {
210 if (attr
->ia_valid
& ATTR_MTIME_SET
) {
212 p
= xdr_encode_time3(p
, &attr
->ia_mtime
);
213 } else if (attr
->ia_valid
& ATTR_MTIME
) {
222 xdr_decode_wcc_attr(u32
*p
, struct nfs_fattr
*fattr
)
224 p
= xdr_decode_hyper(p
, &fattr
->pre_size
);
225 p
= xdr_decode_time3(p
, &fattr
->pre_mtime
);
226 p
= xdr_decode_time3(p
, &fattr
->pre_ctime
);
227 fattr
->valid
|= NFS_ATTR_WCC
;
232 xdr_decode_post_op_attr(u32
*p
, struct nfs_fattr
*fattr
)
235 p
= xdr_decode_fattr(p
, fattr
);
240 xdr_decode_pre_op_attr(u32
*p
, struct nfs_fattr
*fattr
)
243 return xdr_decode_wcc_attr(p
, fattr
);
249 xdr_decode_wcc_data(u32
*p
, struct nfs_fattr
*fattr
)
251 p
= xdr_decode_pre_op_attr(p
, fattr
);
252 return xdr_decode_post_op_attr(p
, fattr
);
256 * NFS encode functions
260 * Encode file handle argument
263 nfs3_xdr_fhandle(struct rpc_rqst
*req
, u32
*p
, struct nfs_fh
*fh
)
265 p
= xdr_encode_fhandle(p
, fh
);
266 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
271 * Encode SETATTR arguments
274 nfs3_xdr_sattrargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_sattrargs
*args
)
276 p
= xdr_encode_fhandle(p
, args
->fh
);
277 p
= xdr_encode_sattr(p
, args
->sattr
);
278 *p
++ = htonl(args
->guard
);
280 p
= xdr_encode_time3(p
, &args
->guardtime
);
281 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
286 * Encode directory ops argument
289 nfs3_xdr_diropargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropargs
*args
)
291 p
= xdr_encode_fhandle(p
, args
->fh
);
292 p
= xdr_encode_array(p
, args
->name
, args
->len
);
293 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
298 * Encode access() argument
301 nfs3_xdr_accessargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_accessargs
*args
)
303 p
= xdr_encode_fhandle(p
, args
->fh
);
304 *p
++ = htonl(args
->access
);
305 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
310 * Arguments to a READ call. Since we read data directly into the page
311 * cache, we also set up the reply iovec here so that iov[1] points
312 * exactly to the page we want to fetch.
315 nfs3_xdr_readargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_readargs
*args
)
317 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
319 u32 count
= args
->count
;
321 p
= xdr_encode_fhandle(p
, args
->fh
);
322 p
= xdr_encode_hyper(p
, args
->offset
);
324 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
326 /* Inline the page array */
327 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readres_sz
) << 2;
328 xdr_inline_pages(&req
->rq_rcv_buf
, replen
,
329 args
->pages
, args
->pgbase
, count
);
334 * Write arguments. Splice the buffer to be written into the iovec.
337 nfs3_xdr_writeargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeargs
*args
)
339 struct xdr_buf
*sndbuf
= &req
->rq_snd_buf
;
340 u32 count
= args
->count
;
342 p
= xdr_encode_fhandle(p
, args
->fh
);
343 p
= xdr_encode_hyper(p
, args
->offset
);
345 *p
++ = htonl(args
->stable
);
347 sndbuf
->len
= xdr_adjust_iovec(sndbuf
->head
, p
);
349 /* Copy the page array */
350 xdr_encode_pages(sndbuf
, args
->pages
, args
->pgbase
, count
);
355 * Encode CREATE arguments
358 nfs3_xdr_createargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_createargs
*args
)
360 p
= xdr_encode_fhandle(p
, args
->fh
);
361 p
= xdr_encode_array(p
, args
->name
, args
->len
);
363 *p
++ = htonl(args
->createmode
);
364 if (args
->createmode
== NFS3_CREATE_EXCLUSIVE
) {
365 *p
++ = args
->verifier
[0];
366 *p
++ = args
->verifier
[1];
368 p
= xdr_encode_sattr(p
, args
->sattr
);
370 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
375 * Encode MKDIR arguments
378 nfs3_xdr_mkdirargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_mkdirargs
*args
)
380 p
= xdr_encode_fhandle(p
, args
->fh
);
381 p
= xdr_encode_array(p
, args
->name
, args
->len
);
382 p
= xdr_encode_sattr(p
, args
->sattr
);
383 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
388 * Encode SYMLINK arguments
391 nfs3_xdr_symlinkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_symlinkargs
*args
)
393 p
= xdr_encode_fhandle(p
, args
->fromfh
);
394 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
395 p
= xdr_encode_sattr(p
, args
->sattr
);
396 p
= xdr_encode_array(p
, args
->topath
, args
->tolen
);
397 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
402 * Encode MKNOD arguments
405 nfs3_xdr_mknodargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_mknodargs
*args
)
407 p
= xdr_encode_fhandle(p
, args
->fh
);
408 p
= xdr_encode_array(p
, args
->name
, args
->len
);
409 *p
++ = htonl(args
->type
);
410 p
= xdr_encode_sattr(p
, args
->sattr
);
411 if (args
->type
== NF3CHR
|| args
->type
== NF3BLK
) {
412 *p
++ = htonl(MAJOR(args
->rdev
));
413 *p
++ = htonl(MINOR(args
->rdev
));
416 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
421 * Encode RENAME arguments
424 nfs3_xdr_renameargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_renameargs
*args
)
426 p
= xdr_encode_fhandle(p
, args
->fromfh
);
427 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
428 p
= xdr_encode_fhandle(p
, args
->tofh
);
429 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
430 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
435 * Encode LINK arguments
438 nfs3_xdr_linkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_linkargs
*args
)
440 p
= xdr_encode_fhandle(p
, args
->fromfh
);
441 p
= xdr_encode_fhandle(p
, args
->tofh
);
442 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
443 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
448 * Encode arguments to readdir call
451 nfs3_xdr_readdirargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readdirargs
*args
)
453 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
455 u32 count
= args
->count
;
457 p
= xdr_encode_fhandle(p
, args
->fh
);
458 p
= xdr_encode_hyper(p
, args
->cookie
);
459 *p
++ = args
->verf
[0];
460 *p
++ = args
->verf
[1];
462 /* readdirplus: need dircount + buffer size.
463 * We just make sure we make dircount big enough */
464 *p
++ = htonl(count
>> 3);
467 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
469 /* Inline the page array */
470 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readdirres_sz
) << 2;
471 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0, count
);
476 * Decode the result of a readdir call.
477 * We just check for syntactical correctness.
480 nfs3_xdr_readdirres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readdirres
*res
)
482 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
483 struct kvec
*iov
= rcvbuf
->head
;
487 unsigned int len
, pglen
;
488 u32
*entry
, *end
, *kaddr
;
490 status
= ntohl(*p
++);
491 /* Decode post_op_attrs */
492 p
= xdr_decode_post_op_attr(p
, res
->dir_attr
);
494 return -nfs_stat_to_errno(status
);
495 /* Decode verifier cookie */
503 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
504 if (iov
->iov_len
< hdrlen
) {
505 printk(KERN_WARNING
"NFS: READDIR reply header overflowed:"
506 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
507 return -errno_NFSERR_IO
;
508 } else if (iov
->iov_len
!= hdrlen
) {
509 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
510 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
513 pglen
= rcvbuf
->page_len
;
514 recvd
= rcvbuf
->len
- hdrlen
;
517 page
= rcvbuf
->pages
;
518 kaddr
= p
= (u32
*)kmap_atomic(*page
, KM_USER0
);
519 end
= (u32
*)((char *)p
+ pglen
);
521 for (nr
= 0; *p
++; nr
++) {
524 p
+= 2; /* inode # */
525 len
= ntohl(*p
++); /* string length */
526 p
+= XDR_QUADLEN(len
) + 2; /* name + cookie */
527 if (len
> NFS3_MAXNAMLEN
) {
528 printk(KERN_WARNING
"NFS: giant filename in readdir (len %x)!\n",
547 if (len
> NFS3_FHSIZE
) {
548 printk(KERN_WARNING
"NFS: giant filehandle in "
549 "readdir (len %x)!\n", len
);
552 p
+= XDR_QUADLEN(len
);
560 if (!nr
&& (entry
[0] != 0 || entry
[1] == 0))
563 kunmap_atomic(kaddr
, KM_USER0
);
566 entry
[0] = entry
[1] = 0;
567 /* truncate listing ? */
569 printk(KERN_NOTICE
"NFS: readdir reply truncated!\n");
574 nr
= -errno_NFSERR_IO
;
579 nfs3_decode_dirent(u32
*p
, struct nfs_entry
*entry
, int plus
)
581 struct nfs_entry old
= *entry
;
585 return ERR_PTR(-EAGAIN
);
587 return ERR_PTR(-EBADCOOKIE
);
590 p
= xdr_decode_hyper(p
, &entry
->ino
);
591 entry
->len
= ntohl(*p
++);
592 entry
->name
= (const char *) p
;
593 p
+= XDR_QUADLEN(entry
->len
);
594 entry
->prev_cookie
= entry
->cookie
;
595 p
= xdr_decode_hyper(p
, &entry
->cookie
);
598 entry
->fattr
->valid
= 0;
599 p
= xdr_decode_post_op_attr(p
, entry
->fattr
);
600 /* In fact, a post_op_fh3: */
602 p
= xdr_decode_fhandle(p
, entry
->fh
);
603 /* Ugh -- server reply was truncated */
605 dprintk("NFS: FH truncated\n");
607 return ERR_PTR(-EAGAIN
);
610 memset((u8
*)(entry
->fh
), 0, sizeof(*entry
->fh
));
613 entry
->eof
= !p
[0] && p
[1];
618 * Encode COMMIT arguments
621 nfs3_xdr_commitargs(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeargs
*args
)
623 p
= xdr_encode_fhandle(p
, args
->fh
);
624 p
= xdr_encode_hyper(p
, args
->offset
);
625 *p
++ = htonl(args
->count
);
626 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
631 * NFS XDR decode functions
635 * Decode attrstat reply.
638 nfs3_xdr_attrstat(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
642 if ((status
= ntohl(*p
++)))
643 return -nfs_stat_to_errno(status
);
644 xdr_decode_fattr(p
, fattr
);
649 * Decode status+wcc_data reply
650 * SATTR, REMOVE, RMDIR
653 nfs3_xdr_wccstat(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
657 if ((status
= ntohl(*p
++)))
658 status
= -nfs_stat_to_errno(status
);
659 xdr_decode_wcc_data(p
, fattr
);
664 * Decode LOOKUP reply
667 nfs3_xdr_lookupres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropres
*res
)
671 if ((status
= ntohl(*p
++))) {
672 status
= -nfs_stat_to_errno(status
);
674 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
675 return -errno_NFSERR_IO
;
676 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
678 xdr_decode_post_op_attr(p
, res
->dir_attr
);
683 * Decode ACCESS reply
686 nfs3_xdr_accessres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_accessres
*res
)
688 int status
= ntohl(*p
++);
690 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
692 return -nfs_stat_to_errno(status
);
693 res
->access
= ntohl(*p
++);
698 nfs3_xdr_readlinkargs(struct rpc_rqst
*req
, u32
*p
, struct nfs3_readlinkargs
*args
)
700 struct rpc_auth
*auth
= req
->rq_task
->tk_auth
;
703 p
= xdr_encode_fhandle(p
, args
->fh
);
704 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
706 /* Inline the page array */
707 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS3_readlinkres_sz
) << 2;
708 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, args
->pgbase
, args
->pglen
);
713 * Decode READLINK reply
716 nfs3_xdr_readlinkres(struct rpc_rqst
*req
, u32
*p
, struct nfs_fattr
*fattr
)
718 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
719 struct kvec
*iov
= rcvbuf
->head
;
720 int hdrlen
, len
, recvd
;
724 status
= ntohl(*p
++);
725 p
= xdr_decode_post_op_attr(p
, fattr
);
728 return -nfs_stat_to_errno(status
);
730 /* Convert length of symlink */
732 if (len
>= rcvbuf
->page_len
|| len
<= 0) {
733 dprintk(KERN_WARNING
"nfs: server returned giant symlink!\n");
734 return -ENAMETOOLONG
;
737 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
738 if (iov
->iov_len
< hdrlen
) {
739 printk(KERN_WARNING
"NFS: READLINK reply header overflowed:"
740 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
741 return -errno_NFSERR_IO
;
742 } else if (iov
->iov_len
!= hdrlen
) {
743 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
744 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
746 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
748 printk(KERN_WARNING
"NFS: server cheating in readlink reply: "
749 "count %u > recvd %u\n", len
, recvd
);
753 /* NULL terminate the string we got */
754 kaddr
= (char*)kmap_atomic(rcvbuf
->pages
[0], KM_USER0
);
755 kaddr
[len
+rcvbuf
->page_base
] = '\0';
756 kunmap_atomic(kaddr
, KM_USER0
);
764 nfs3_xdr_readres(struct rpc_rqst
*req
, u32
*p
, struct nfs_readres
*res
)
766 struct kvec
*iov
= req
->rq_rcv_buf
.head
;
767 int status
, count
, ocount
, recvd
, hdrlen
;
769 status
= ntohl(*p
++);
770 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
773 return -nfs_stat_to_errno(status
);
775 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
776 * in that it puts the count both in the res struct and in the
777 * opaque data count. */
779 res
->eof
= ntohl(*p
++);
780 ocount
= ntohl(*p
++);
782 if (ocount
!= count
) {
783 printk(KERN_WARNING
"NFS: READ count doesn't match RPC opaque count.\n");
784 return -errno_NFSERR_IO
;
787 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
788 if (iov
->iov_len
< hdrlen
) {
789 printk(KERN_WARNING
"NFS: READ reply header overflowed:"
790 "length %d > %Zu\n", hdrlen
, iov
->iov_len
);
791 return -errno_NFSERR_IO
;
792 } else if (iov
->iov_len
!= hdrlen
) {
793 dprintk("NFS: READ header is short. iovec will be shifted.\n");
794 xdr_shift_buf(&req
->rq_rcv_buf
, iov
->iov_len
- hdrlen
);
797 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
799 printk(KERN_WARNING
"NFS: server cheating in read reply: "
800 "count %d > recvd %d\n", count
, recvd
);
805 if (count
< res
->count
)
812 * Decode WRITE response
815 nfs3_xdr_writeres(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeres
*res
)
819 status
= ntohl(*p
++);
820 p
= xdr_decode_wcc_data(p
, res
->fattr
);
823 return -nfs_stat_to_errno(status
);
825 res
->count
= ntohl(*p
++);
826 res
->verf
->committed
= (enum nfs3_stable_how
)ntohl(*p
++);
827 res
->verf
->verifier
[0] = *p
++;
828 res
->verf
->verifier
[1] = *p
++;
834 * Decode a CREATE response
837 nfs3_xdr_createres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_diropres
*res
)
841 status
= ntohl(*p
++);
844 if (!(p
= xdr_decode_fhandle(p
, res
->fh
)))
845 return -errno_NFSERR_IO
;
846 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
848 memset(res
->fh
, 0, sizeof(*res
->fh
));
849 /* Do decode post_op_attr but set it to NULL */
850 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
851 res
->fattr
->valid
= 0;
854 status
= -nfs_stat_to_errno(status
);
856 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
861 * Decode RENAME reply
864 nfs3_xdr_renameres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_renameres
*res
)
868 if ((status
= ntohl(*p
++)) != 0)
869 status
= -nfs_stat_to_errno(status
);
870 p
= xdr_decode_wcc_data(p
, res
->fromattr
);
871 p
= xdr_decode_wcc_data(p
, res
->toattr
);
879 nfs3_xdr_linkres(struct rpc_rqst
*req
, u32
*p
, struct nfs3_linkres
*res
)
883 if ((status
= ntohl(*p
++)) != 0)
884 status
= -nfs_stat_to_errno(status
);
885 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
886 p
= xdr_decode_wcc_data(p
, res
->dir_attr
);
891 * Decode FSSTAT reply
894 nfs3_xdr_fsstatres(struct rpc_rqst
*req
, u32
*p
, struct nfs_fsstat
*res
)
898 status
= ntohl(*p
++);
900 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
902 return -nfs_stat_to_errno(status
);
904 p
= xdr_decode_hyper(p
, &res
->tbytes
);
905 p
= xdr_decode_hyper(p
, &res
->fbytes
);
906 p
= xdr_decode_hyper(p
, &res
->abytes
);
907 p
= xdr_decode_hyper(p
, &res
->tfiles
);
908 p
= xdr_decode_hyper(p
, &res
->ffiles
);
909 p
= xdr_decode_hyper(p
, &res
->afiles
);
911 /* ignore invarsec */
916 * Decode FSINFO reply
919 nfs3_xdr_fsinfores(struct rpc_rqst
*req
, u32
*p
, struct nfs_fsinfo
*res
)
923 status
= ntohl(*p
++);
925 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
927 return -nfs_stat_to_errno(status
);
929 res
->rtmax
= ntohl(*p
++);
930 res
->rtpref
= ntohl(*p
++);
931 res
->rtmult
= ntohl(*p
++);
932 res
->wtmax
= ntohl(*p
++);
933 res
->wtpref
= ntohl(*p
++);
934 res
->wtmult
= ntohl(*p
++);
935 res
->dtpref
= ntohl(*p
++);
936 p
= xdr_decode_hyper(p
, &res
->maxfilesize
);
938 /* ignore time_delta and properties */
944 * Decode PATHCONF reply
947 nfs3_xdr_pathconfres(struct rpc_rqst
*req
, u32
*p
, struct nfs_pathconf
*res
)
951 status
= ntohl(*p
++);
953 p
= xdr_decode_post_op_attr(p
, res
->fattr
);
955 return -nfs_stat_to_errno(status
);
956 res
->max_link
= ntohl(*p
++);
957 res
->max_namelen
= ntohl(*p
++);
959 /* ignore remaining fields */
964 * Decode COMMIT reply
967 nfs3_xdr_commitres(struct rpc_rqst
*req
, u32
*p
, struct nfs_writeres
*res
)
971 status
= ntohl(*p
++);
972 p
= xdr_decode_wcc_data(p
, res
->fattr
);
974 return -nfs_stat_to_errno(status
);
976 res
->verf
->verifier
[0] = *p
++;
977 res
->verf
->verifier
[1] = *p
++;
982 # define MAX(a, b) (((a) > (b))? (a) : (b))
985 #define PROC(proc, argtype, restype, timer) \
986 [NFS3PROC_##proc] = { \
987 .p_proc = NFS3PROC_##proc, \
988 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
989 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
990 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
994 struct rpc_procinfo nfs3_procedures
[] = {
995 PROC(GETATTR
, fhandle
, attrstat
, 1),
996 PROC(SETATTR
, sattrargs
, wccstat
, 0),
997 PROC(LOOKUP
, diropargs
, lookupres
, 2),
998 PROC(ACCESS
, accessargs
, accessres
, 1),
999 PROC(READLINK
, readlinkargs
, readlinkres
, 3),
1000 PROC(READ
, readargs
, readres
, 3),
1001 PROC(WRITE
, writeargs
, writeres
, 4),
1002 PROC(CREATE
, createargs
, createres
, 0),
1003 PROC(MKDIR
, mkdirargs
, createres
, 0),
1004 PROC(SYMLINK
, symlinkargs
, createres
, 0),
1005 PROC(MKNOD
, mknodargs
, createres
, 0),
1006 PROC(REMOVE
, diropargs
, wccstat
, 0),
1007 PROC(RMDIR
, diropargs
, wccstat
, 0),
1008 PROC(RENAME
, renameargs
, renameres
, 0),
1009 PROC(LINK
, linkargs
, linkres
, 0),
1010 PROC(READDIR
, readdirargs
, readdirres
, 3),
1011 PROC(READDIRPLUS
, readdirargs
, readdirres
, 3),
1012 PROC(FSSTAT
, fhandle
, fsstatres
, 0),
1013 PROC(FSINFO
, fhandle
, fsinfores
, 0),
1014 PROC(PATHCONF
, fhandle
, pathconfres
, 0),
1015 PROC(COMMIT
, commitargs
, commitres
, 5),
1018 struct rpc_version nfs_version3
= {
1020 .nrprocs
= sizeof(nfs3_procedures
)/sizeof(nfs3_procedures
[0]),
1021 .procs
= nfs3_procedures