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/vserver/xid.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)
84 * Map file type to S_IFMT bits
88 unsigned int nfs2type;
102 * Common NFS XDR functions as inlines
105 xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
107 return xdr_encode_array(p, fh->data, fh->size);
111 xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
113 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
114 memcpy(fh->data, p, fh->size);
115 return p + XDR_QUADLEN(fh->size);
121 * Encode/decode time.
124 xdr_encode_time3(u32 *p, struct timespec *timep)
126 *p++ = htonl(timep->tv_sec);
127 *p++ = htonl(timep->tv_nsec);
132 xdr_decode_time3(u32 *p, struct timespec *timep)
134 timep->tv_sec = ntohl(*p++);
135 timep->tv_nsec = ntohl(*p++);
140 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
142 unsigned int type, major, minor;
148 fmode = nfs_type2fmt[type].mode;
149 fattr->type = nfs_type2fmt[type].nfs2type;
150 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
151 fattr->nlink = ntohl(*p++);
152 fattr->uid = ntohl(*p++);
153 fattr->gid = ntohl(*p++);
154 p = xdr_decode_hyper(p, &fattr->size);
155 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
157 /* Turn remote device info into Linux-specific dev_t */
160 fattr->rdev = MKDEV(major, minor);
161 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
164 p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
165 p = xdr_decode_hyper(p, &fattr->fileid);
166 p = xdr_decode_time3(p, &fattr->atime);
167 p = xdr_decode_time3(p, &fattr->mtime);
168 p = xdr_decode_time3(p, &fattr->ctime);
170 /* Update the mode bits */
171 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
172 fattr->timestamp = jiffies;
177 xdr_encode_sattr(u32 *p, struct iattr *attr, int tagxid)
179 if (attr->ia_valid & ATTR_MODE) {
181 *p++ = htonl(attr->ia_mode);
185 if (attr->ia_valid & ATTR_UID ||
186 (tagxid && (attr->ia_valid & ATTR_XID))) {
188 *p++ = htonl(XIDINO_UID(tagxid, attr->ia_uid, attr->ia_xid));
192 if (attr->ia_valid & ATTR_GID ||
193 (tagxid && (attr->ia_valid & ATTR_XID))) {
195 *p++ = htonl(XIDINO_GID(tagxid, attr->ia_gid, attr->ia_xid));
199 if (attr->ia_valid & ATTR_SIZE) {
201 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
205 if (attr->ia_valid & ATTR_ATIME_SET) {
207 p = xdr_encode_time3(p, &attr->ia_atime);
208 } else if (attr->ia_valid & ATTR_ATIME) {
213 if (attr->ia_valid & ATTR_MTIME_SET) {
215 p = xdr_encode_time3(p, &attr->ia_mtime);
216 } else if (attr->ia_valid & ATTR_MTIME) {
225 xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
227 p = xdr_decode_hyper(p, &fattr->pre_size);
228 p = xdr_decode_time3(p, &fattr->pre_mtime);
229 p = xdr_decode_time3(p, &fattr->pre_ctime);
230 fattr->valid |= NFS_ATTR_WCC;
235 xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
238 p = xdr_decode_fattr(p, fattr);
243 xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
246 return xdr_decode_wcc_attr(p, fattr);
252 xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
254 p = xdr_decode_pre_op_attr(p, fattr);
255 return xdr_decode_post_op_attr(p, fattr);
259 * NFS encode functions
263 * Encode file handle argument
266 nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
268 p = xdr_encode_fhandle(p, fh);
269 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
274 * Encode SETATTR arguments
277 nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
279 p = xdr_encode_fhandle(p, args->fh);
280 p = xdr_encode_sattr(p, args->sattr,
281 req->rq_task->tk_client->cl_tagxid);
282 *p++ = htonl(args->guard);
284 p = xdr_encode_time3(p, &args->guardtime);
285 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
290 * Encode directory ops argument
293 nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
295 p = xdr_encode_fhandle(p, args->fh);
296 p = xdr_encode_array(p, args->name, args->len);
297 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
302 * Encode access() argument
305 nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
307 p = xdr_encode_fhandle(p, args->fh);
308 *p++ = htonl(args->access);
309 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
314 * Arguments to a READ call. Since we read data directly into the page
315 * cache, we also set up the reply iovec here so that iov[1] points
316 * exactly to the page we want to fetch.
319 nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
321 struct rpc_auth *auth = req->rq_task->tk_auth;
323 u32 count = args->count;
325 p = xdr_encode_fhandle(p, args->fh);
326 p = xdr_encode_hyper(p, args->offset);
328 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
330 /* Inline the page array */
331 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
332 xdr_inline_pages(&req->rq_rcv_buf, replen,
333 args->pages, args->pgbase, count);
338 * Write arguments. Splice the buffer to be written into the iovec.
341 nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
343 struct xdr_buf *sndbuf = &req->rq_snd_buf;
344 u32 count = args->count;
346 p = xdr_encode_fhandle(p, args->fh);
347 p = xdr_encode_hyper(p, args->offset);
349 *p++ = htonl(args->stable);
351 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
353 /* Copy the page array */
354 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
359 * Encode CREATE arguments
362 nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
364 p = xdr_encode_fhandle(p, args->fh);
365 p = xdr_encode_array(p, args->name, args->len);
367 *p++ = htonl(args->createmode);
368 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
369 *p++ = args->verifier[0];
370 *p++ = args->verifier[1];
372 p = xdr_encode_sattr(p, args->sattr,
373 req->rq_task->tk_client->cl_tagxid);
375 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
380 * Encode MKDIR arguments
383 nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
385 p = xdr_encode_fhandle(p, args->fh);
386 p = xdr_encode_array(p, args->name, args->len);
387 p = xdr_encode_sattr(p, args->sattr,
388 req->rq_task->tk_client->cl_tagxid);
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 req->rq_task->tk_client->cl_tagxid);
403 p = xdr_encode_array(p, args->topath, args->tolen);
404 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
409 * Encode MKNOD arguments
412 nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
414 p = xdr_encode_fhandle(p, args->fh);
415 p = xdr_encode_array(p, args->name, args->len);
416 *p++ = htonl(args->type);
417 p = xdr_encode_sattr(p, args->sattr,
418 req->rq_task->tk_client->cl_tagxid);
419 if (args->type == NF3CHR || args->type == NF3BLK) {
420 *p++ = htonl(MAJOR(args->rdev));
421 *p++ = htonl(MINOR(args->rdev));
424 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
429 * Encode RENAME arguments
432 nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
434 p = xdr_encode_fhandle(p, args->fromfh);
435 p = xdr_encode_array(p, args->fromname, args->fromlen);
436 p = xdr_encode_fhandle(p, args->tofh);
437 p = xdr_encode_array(p, args->toname, args->tolen);
438 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
443 * Encode LINK arguments
446 nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
448 p = xdr_encode_fhandle(p, args->fromfh);
449 p = xdr_encode_fhandle(p, args->tofh);
450 p = xdr_encode_array(p, args->toname, args->tolen);
451 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
456 * Encode arguments to readdir call
459 nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
461 struct rpc_auth *auth = req->rq_task->tk_auth;
463 u32 count = args->count;
465 p = xdr_encode_fhandle(p, args->fh);
466 p = xdr_encode_hyper(p, args->cookie);
467 *p++ = args->verf[0];
468 *p++ = args->verf[1];
470 /* readdirplus: need dircount + buffer size.
471 * We just make sure we make dircount big enough */
472 *p++ = htonl(count >> 3);
475 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
477 /* Inline the page array */
478 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
479 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
484 * Decode the result of a readdir call.
485 * We just check for syntactical correctness.
488 nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
490 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
491 struct kvec *iov = rcvbuf->head;
495 unsigned int len, pglen;
496 u32 *entry, *end, *kaddr;
498 status = ntohl(*p++);
499 /* Decode post_op_attrs */
500 p = xdr_decode_post_op_attr(p, res->dir_attr);
502 return -nfs_stat_to_errno(status);
503 /* Decode verifier cookie */
511 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
512 if (iov->iov_len < hdrlen) {
513 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
514 "length %d > %Zu\n", hdrlen, iov->iov_len);
515 return -errno_NFSERR_IO;
516 } else if (iov->iov_len != hdrlen) {
517 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
518 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
521 pglen = rcvbuf->page_len;
522 recvd = rcvbuf->len - hdrlen;
525 page = rcvbuf->pages;
526 kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
527 end = (u32 *)((char *)p + pglen);
529 for (nr = 0; *p++; nr++) {
532 p += 2; /* inode # */
533 len = ntohl(*p++); /* string length */
534 p += XDR_QUADLEN(len) + 2; /* name + cookie */
535 if (len > NFS3_MAXNAMLEN) {
536 printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
555 if (len > NFS3_FHSIZE) {
556 printk(KERN_WARNING "NFS: giant filehandle in "
557 "readdir (len %x)!\n", len);
560 p += XDR_QUADLEN(len);
568 if (!nr && (entry[0] != 0 || entry[1] == 0))
571 kunmap_atomic(kaddr, KM_USER0);
574 entry[0] = entry[1] = 0;
575 /* truncate listing ? */
577 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
582 nr = -errno_NFSERR_IO;
587 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
589 struct nfs_entry old = *entry;
593 return ERR_PTR(-EAGAIN);
595 return ERR_PTR(-EBADCOOKIE);
598 p = xdr_decode_hyper(p, &entry->ino);
599 entry->len = ntohl(*p++);
600 entry->name = (const char *) p;
601 p += XDR_QUADLEN(entry->len);
602 entry->prev_cookie = entry->cookie;
603 p = xdr_decode_hyper(p, &entry->cookie);
606 entry->fattr->valid = 0;
607 p = xdr_decode_post_op_attr(p, entry->fattr);
608 /* In fact, a post_op_fh3: */
610 p = xdr_decode_fhandle(p, entry->fh);
611 /* Ugh -- server reply was truncated */
613 dprintk("NFS: FH truncated\n");
615 return ERR_PTR(-EAGAIN);
618 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
621 entry->eof = !p[0] && p[1];
626 * Encode COMMIT arguments
629 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
631 p = xdr_encode_fhandle(p, args->fh);
632 p = xdr_encode_hyper(p, args->offset);
633 *p++ = htonl(args->count);
634 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
639 * NFS XDR decode functions
643 * Decode attrstat reply.
646 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
650 if ((status = ntohl(*p++)))
651 return -nfs_stat_to_errno(status);
652 xdr_decode_fattr(p, fattr);
657 * Decode status+wcc_data reply
658 * SATTR, REMOVE, RMDIR
661 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
665 if ((status = ntohl(*p++)))
666 status = -nfs_stat_to_errno(status);
667 xdr_decode_wcc_data(p, fattr);
672 * Decode LOOKUP reply
675 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
679 if ((status = ntohl(*p++))) {
680 status = -nfs_stat_to_errno(status);
682 if (!(p = xdr_decode_fhandle(p, res->fh)))
683 return -errno_NFSERR_IO;
684 p = xdr_decode_post_op_attr(p, res->fattr);
686 xdr_decode_post_op_attr(p, res->dir_attr);
691 * Decode ACCESS reply
694 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
696 int status = ntohl(*p++);
698 p = xdr_decode_post_op_attr(p, res->fattr);
700 return -nfs_stat_to_errno(status);
701 res->access = ntohl(*p++);
706 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
708 struct rpc_auth *auth = req->rq_task->tk_auth;
711 p = xdr_encode_fhandle(p, args->fh);
712 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
714 /* Inline the page array */
715 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
716 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
721 * Decode READLINK reply
724 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
726 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
727 struct kvec *iov = rcvbuf->head;
728 int hdrlen, len, recvd;
732 status = ntohl(*p++);
733 p = xdr_decode_post_op_attr(p, fattr);
736 return -nfs_stat_to_errno(status);
738 /* Convert length of symlink */
740 if (len >= rcvbuf->page_len || len <= 0) {
741 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
742 return -ENAMETOOLONG;
745 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
746 if (iov->iov_len < hdrlen) {
747 printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
748 "length %d > %Zu\n", hdrlen, iov->iov_len);
749 return -errno_NFSERR_IO;
750 } else if (iov->iov_len != hdrlen) {
751 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
752 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
754 recvd = req->rq_rcv_buf.len - hdrlen;
756 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
757 "count %u > recvd %u\n", len, recvd);
761 /* NULL terminate the string we got */
762 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
763 kaddr[len+rcvbuf->page_base] = '\0';
764 kunmap_atomic(kaddr, KM_USER0);
772 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
774 struct kvec *iov = req->rq_rcv_buf.head;
775 int status, count, ocount, recvd, hdrlen;
777 status = ntohl(*p++);
778 p = xdr_decode_post_op_attr(p, res->fattr);
781 return -nfs_stat_to_errno(status);
783 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
784 * in that it puts the count both in the res struct and in the
785 * opaque data count. */
787 res->eof = ntohl(*p++);
788 ocount = ntohl(*p++);
790 if (ocount != count) {
791 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
792 return -errno_NFSERR_IO;
795 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
796 if (iov->iov_len < hdrlen) {
797 printk(KERN_WARNING "NFS: READ reply header overflowed:"
798 "length %d > %Zu\n", hdrlen, iov->iov_len);
799 return -errno_NFSERR_IO;
800 } else if (iov->iov_len != hdrlen) {
801 dprintk("NFS: READ header is short. iovec will be shifted.\n");
802 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
805 recvd = req->rq_rcv_buf.len - hdrlen;
807 printk(KERN_WARNING "NFS: server cheating in read reply: "
808 "count %d > recvd %d\n", count, recvd);
813 if (count < res->count)
820 * Decode WRITE response
823 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
827 status = ntohl(*p++);
828 p = xdr_decode_wcc_data(p, res->fattr);
831 return -nfs_stat_to_errno(status);
833 res->count = ntohl(*p++);
834 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
835 res->verf->verifier[0] = *p++;
836 res->verf->verifier[1] = *p++;
842 * Decode a CREATE response
845 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
849 status = ntohl(*p++);
852 if (!(p = xdr_decode_fhandle(p, res->fh)))
853 return -errno_NFSERR_IO;
854 p = xdr_decode_post_op_attr(p, res->fattr);
856 memset(res->fh, 0, sizeof(*res->fh));
857 /* Do decode post_op_attr but set it to NULL */
858 p = xdr_decode_post_op_attr(p, res->fattr);
859 res->fattr->valid = 0;
862 status = -nfs_stat_to_errno(status);
864 p = xdr_decode_wcc_data(p, res->dir_attr);
869 * Decode RENAME reply
872 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
876 if ((status = ntohl(*p++)) != 0)
877 status = -nfs_stat_to_errno(status);
878 p = xdr_decode_wcc_data(p, res->fromattr);
879 p = xdr_decode_wcc_data(p, res->toattr);
887 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
891 if ((status = ntohl(*p++)) != 0)
892 status = -nfs_stat_to_errno(status);
893 p = xdr_decode_post_op_attr(p, res->fattr);
894 p = xdr_decode_wcc_data(p, res->dir_attr);
899 * Decode FSSTAT reply
902 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
906 status = ntohl(*p++);
908 p = xdr_decode_post_op_attr(p, res->fattr);
910 return -nfs_stat_to_errno(status);
912 p = xdr_decode_hyper(p, &res->tbytes);
913 p = xdr_decode_hyper(p, &res->fbytes);
914 p = xdr_decode_hyper(p, &res->abytes);
915 p = xdr_decode_hyper(p, &res->tfiles);
916 p = xdr_decode_hyper(p, &res->ffiles);
917 p = xdr_decode_hyper(p, &res->afiles);
919 /* ignore invarsec */
924 * Decode FSINFO reply
927 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
931 status = ntohl(*p++);
933 p = xdr_decode_post_op_attr(p, res->fattr);
935 return -nfs_stat_to_errno(status);
937 res->rtmax = ntohl(*p++);
938 res->rtpref = ntohl(*p++);
939 res->rtmult = ntohl(*p++);
940 res->wtmax = ntohl(*p++);
941 res->wtpref = ntohl(*p++);
942 res->wtmult = ntohl(*p++);
943 res->dtpref = ntohl(*p++);
944 p = xdr_decode_hyper(p, &res->maxfilesize);
946 /* ignore time_delta and properties */
952 * Decode PATHCONF reply
955 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
959 status = ntohl(*p++);
961 p = xdr_decode_post_op_attr(p, res->fattr);
963 return -nfs_stat_to_errno(status);
964 res->max_link = ntohl(*p++);
965 res->max_namelen = ntohl(*p++);
967 /* ignore remaining fields */
972 * Decode COMMIT reply
975 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
979 status = ntohl(*p++);
980 p = xdr_decode_wcc_data(p, res->fattr);
982 return -nfs_stat_to_errno(status);
984 res->verf->verifier[0] = *p++;
985 res->verf->verifier[1] = *p++;
990 # define MAX(a, b) (((a) > (b))? (a) : (b))
993 #define PROC(proc, argtype, restype, timer) \
994 [NFS3PROC_##proc] = { \
995 .p_proc = NFS3PROC_##proc, \
996 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
997 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
998 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1002 struct rpc_procinfo nfs3_procedures[] = {
1003 PROC(GETATTR, fhandle, attrstat, 1),
1004 PROC(SETATTR, sattrargs, wccstat, 0),
1005 PROC(LOOKUP, diropargs, lookupres, 2),
1006 PROC(ACCESS, accessargs, accessres, 1),
1007 PROC(READLINK, readlinkargs, readlinkres, 3),
1008 PROC(READ, readargs, readres, 3),
1009 PROC(WRITE, writeargs, writeres, 4),
1010 PROC(CREATE, createargs, createres, 0),
1011 PROC(MKDIR, mkdirargs, createres, 0),
1012 PROC(SYMLINK, symlinkargs, createres, 0),
1013 PROC(MKNOD, mknodargs, createres, 0),
1014 PROC(REMOVE, diropargs, wccstat, 0),
1015 PROC(RMDIR, diropargs, wccstat, 0),
1016 PROC(RENAME, renameargs, renameres, 0),
1017 PROC(LINK, linkargs, linkres, 0),
1018 PROC(READDIR, readdirargs, readdirres, 3),
1019 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1020 PROC(FSSTAT, fhandle, fsstatres, 0),
1021 PROC(FSINFO, fhandle, fsinfores, 0),
1022 PROC(PATHCONF, fhandle, pathconfres, 0),
1023 PROC(COMMIT, commitargs, commitres, 5),
1026 struct rpc_version nfs_version3 = {
1028 .nrprocs = sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
1029 .procs = nfs3_procedures