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)
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)
113 * Zero all nonused bytes
115 memset((u8 *)fh, 0, sizeof(*fh));
116 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
117 memcpy(fh->data, p, fh->size);
118 return p + XDR_QUADLEN(fh->size);
124 * Encode/decode time.
127 xdr_encode_time3(u32 *p, struct timespec *timep)
129 *p++ = htonl(timep->tv_sec);
130 *p++ = htonl(timep->tv_nsec);
135 xdr_decode_time3(u32 *p, struct timespec *timep)
137 timep->tv_sec = ntohl(*p++);
138 timep->tv_nsec = ntohl(*p++);
143 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
145 unsigned int type, major, minor;
151 fmode = nfs_type2fmt[type].mode;
152 fattr->type = nfs_type2fmt[type].nfs2type;
153 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
154 fattr->nlink = ntohl(*p++);
155 fattr->uid = ntohl(*p++);
156 fattr->gid = ntohl(*p++);
157 p = xdr_decode_hyper(p, &fattr->size);
158 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
160 /* Turn remote device info into Linux-specific dev_t */
163 fattr->rdev = MKDEV(major, minor);
164 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
167 p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
168 p = xdr_decode_hyper(p, &fattr->fileid);
169 p = xdr_decode_time3(p, &fattr->atime);
170 p = xdr_decode_time3(p, &fattr->mtime);
171 p = xdr_decode_time3(p, &fattr->ctime);
173 /* Update the mode bits */
174 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
175 fattr->timestamp = jiffies;
180 xdr_encode_sattr(u32 *p, struct iattr *attr)
182 if (attr->ia_valid & ATTR_MODE) {
184 *p++ = htonl(attr->ia_mode);
188 if (attr->ia_valid & ATTR_UID) {
190 *p++ = htonl(attr->ia_uid);
194 if (attr->ia_valid & ATTR_GID) {
196 *p++ = htonl(attr->ia_gid);
200 if (attr->ia_valid & ATTR_SIZE) {
202 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
206 if (attr->ia_valid & ATTR_ATIME_SET) {
208 p = xdr_encode_time3(p, &attr->ia_atime);
209 } else if (attr->ia_valid & ATTR_ATIME) {
214 if (attr->ia_valid & ATTR_MTIME_SET) {
216 p = xdr_encode_time3(p, &attr->ia_mtime);
217 } else if (attr->ia_valid & ATTR_MTIME) {
226 xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
228 p = xdr_decode_hyper(p, &fattr->pre_size);
229 p = xdr_decode_time3(p, &fattr->pre_mtime);
230 p = xdr_decode_time3(p, &fattr->pre_ctime);
231 fattr->valid |= NFS_ATTR_WCC;
236 xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
239 p = xdr_decode_fattr(p, fattr);
244 xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
247 return xdr_decode_wcc_attr(p, fattr);
253 xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
255 p = xdr_decode_pre_op_attr(p, fattr);
256 return xdr_decode_post_op_attr(p, fattr);
260 * NFS encode functions
264 * Encode file handle argument
267 nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
269 p = xdr_encode_fhandle(p, fh);
270 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
275 * Encode SETATTR arguments
278 nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
280 p = xdr_encode_fhandle(p, args->fh);
281 p = xdr_encode_sattr(p, args->sattr);
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);
374 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
379 * Encode MKDIR arguments
382 nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
384 p = xdr_encode_fhandle(p, args->fh);
385 p = xdr_encode_array(p, args->name, args->len);
386 p = xdr_encode_sattr(p, args->sattr);
387 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
392 * Encode SYMLINK arguments
395 nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
397 p = xdr_encode_fhandle(p, args->fromfh);
398 p = xdr_encode_array(p, args->fromname, args->fromlen);
399 p = xdr_encode_sattr(p, args->sattr);
400 p = xdr_encode_array(p, args->topath, args->tolen);
401 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
406 * Encode MKNOD arguments
409 nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
411 p = xdr_encode_fhandle(p, args->fh);
412 p = xdr_encode_array(p, args->name, args->len);
413 *p++ = htonl(args->type);
414 p = xdr_encode_sattr(p, args->sattr);
415 if (args->type == NF3CHR || args->type == NF3BLK) {
416 *p++ = htonl(MAJOR(args->rdev));
417 *p++ = htonl(MINOR(args->rdev));
420 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
425 * Encode RENAME arguments
428 nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
430 p = xdr_encode_fhandle(p, args->fromfh);
431 p = xdr_encode_array(p, args->fromname, args->fromlen);
432 p = xdr_encode_fhandle(p, args->tofh);
433 p = xdr_encode_array(p, args->toname, args->tolen);
434 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
439 * Encode LINK arguments
442 nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
444 p = xdr_encode_fhandle(p, args->fromfh);
445 p = xdr_encode_fhandle(p, args->tofh);
446 p = xdr_encode_array(p, args->toname, args->tolen);
447 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
452 * Encode arguments to readdir call
455 nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
457 struct rpc_auth *auth = req->rq_task->tk_auth;
459 u32 count = args->count;
461 p = xdr_encode_fhandle(p, args->fh);
462 p = xdr_encode_hyper(p, args->cookie);
463 *p++ = args->verf[0];
464 *p++ = args->verf[1];
466 /* readdirplus: need dircount + buffer size.
467 * We just make sure we make dircount big enough */
468 *p++ = htonl(count >> 3);
471 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
473 /* Inline the page array */
474 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
475 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
480 * Decode the result of a readdir call.
481 * We just check for syntactical correctness.
484 nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
486 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
487 struct iovec *iov = rcvbuf->head;
491 unsigned int len, pglen;
492 u32 *entry, *end, *kaddr;
494 status = ntohl(*p++);
495 /* Decode post_op_attrs */
496 p = xdr_decode_post_op_attr(p, res->dir_attr);
498 return -nfs_stat_to_errno(status);
499 /* Decode verifier cookie */
507 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
508 if (iov->iov_len < hdrlen) {
509 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
510 "length %d > %Zu\n", hdrlen, iov->iov_len);
511 return -errno_NFSERR_IO;
512 } else if (iov->iov_len != hdrlen) {
513 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
514 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
517 pglen = rcvbuf->page_len;
518 recvd = rcvbuf->len - hdrlen;
521 page = rcvbuf->pages;
522 kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
523 end = (u32 *)((char *)p + pglen);
525 for (nr = 0; *p++; nr++) {
528 p += 2; /* inode # */
529 len = ntohl(*p++); /* string length */
530 p += XDR_QUADLEN(len) + 2; /* name + cookie */
531 if (len > NFS3_MAXNAMLEN) {
532 printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
551 if (len > NFS3_FHSIZE) {
552 printk(KERN_WARNING "NFS: giant filehandle in "
553 "readdir (len %x)!\n", len);
556 p += XDR_QUADLEN(len);
564 if (!nr && (entry[0] != 0 || entry[1] == 0))
567 kunmap_atomic(kaddr, KM_USER0);
570 entry[0] = entry[1] = 0;
571 /* truncate listing ? */
573 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
578 nr = -errno_NFSERR_IO;
583 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
585 struct nfs_entry old = *entry;
589 return ERR_PTR(-EAGAIN);
591 return ERR_PTR(-EBADCOOKIE);
594 p = xdr_decode_hyper(p, &entry->ino);
595 entry->len = ntohl(*p++);
596 entry->name = (const char *) p;
597 p += XDR_QUADLEN(entry->len);
598 entry->prev_cookie = entry->cookie;
599 p = xdr_decode_hyper(p, &entry->cookie);
602 entry->fattr->valid = 0;
603 p = xdr_decode_post_op_attr(p, entry->fattr);
604 /* In fact, a post_op_fh3: */
606 p = xdr_decode_fhandle(p, entry->fh);
607 /* Ugh -- server reply was truncated */
609 dprintk("NFS: FH truncated\n");
611 return ERR_PTR(-EAGAIN);
614 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
617 entry->eof = !p[0] && p[1];
622 * Encode COMMIT arguments
625 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
627 p = xdr_encode_fhandle(p, args->fh);
628 p = xdr_encode_hyper(p, args->offset);
629 *p++ = htonl(args->count);
630 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
635 * NFS XDR decode functions
639 * Decode attrstat reply.
642 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
646 if ((status = ntohl(*p++)))
647 return -nfs_stat_to_errno(status);
648 xdr_decode_fattr(p, fattr);
653 * Decode status+wcc_data reply
654 * SATTR, REMOVE, RMDIR
657 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
661 if ((status = ntohl(*p++)))
662 status = -nfs_stat_to_errno(status);
663 xdr_decode_wcc_data(p, fattr);
668 * Decode LOOKUP reply
671 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
675 if ((status = ntohl(*p++))) {
676 status = -nfs_stat_to_errno(status);
678 if (!(p = xdr_decode_fhandle(p, res->fh)))
679 return -errno_NFSERR_IO;
680 p = xdr_decode_post_op_attr(p, res->fattr);
682 xdr_decode_post_op_attr(p, res->dir_attr);
687 * Decode ACCESS reply
690 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
692 int status = ntohl(*p++);
694 p = xdr_decode_post_op_attr(p, res->fattr);
696 return -nfs_stat_to_errno(status);
697 res->access = ntohl(*p++);
702 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
704 struct rpc_auth *auth = req->rq_task->tk_auth;
706 u32 count = args->count - 4;
708 p = xdr_encode_fhandle(p, args->fh);
709 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
711 /* Inline the page array */
712 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
713 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
718 * Decode READLINK reply
721 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
723 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
724 struct iovec *iov = rcvbuf->head;
730 status = ntohl(*p++);
731 p = xdr_decode_post_op_attr(p, fattr);
734 return -nfs_stat_to_errno(status);
736 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
737 if (iov->iov_len > hdrlen) {
738 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
739 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
742 strlen = (u32*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
743 /* Convert length of symlink */
744 len = ntohl(*strlen);
745 if (len > rcvbuf->page_len)
746 len = rcvbuf->page_len;
748 /* NULL terminate the string we got */
749 string = (char *)(strlen + 1);
751 kunmap_atomic(strlen, KM_USER0);
759 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
761 struct iovec *iov = req->rq_rcv_buf.head;
762 int status, count, ocount, recvd, hdrlen;
764 status = ntohl(*p++);
765 p = xdr_decode_post_op_attr(p, res->fattr);
768 return -nfs_stat_to_errno(status);
770 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
771 * in that it puts the count both in the res struct and in the
772 * opaque data count. */
774 res->eof = ntohl(*p++);
775 ocount = ntohl(*p++);
777 if (ocount != count) {
778 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
779 return -errno_NFSERR_IO;
782 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
783 if (iov->iov_len < hdrlen) {
784 printk(KERN_WARNING "NFS: READ reply header overflowed:"
785 "length %d > %Zu\n", hdrlen, iov->iov_len);
786 return -errno_NFSERR_IO;
787 } else if (iov->iov_len != hdrlen) {
788 dprintk("NFS: READ header is short. iovec will be shifted.\n");
789 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
792 recvd = req->rq_rcv_buf.len - hdrlen;
794 printk(KERN_WARNING "NFS: server cheating in read reply: "
795 "count %d > recvd %d\n", count, recvd);
800 if (count < res->count)
807 * Decode WRITE response
810 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
814 status = ntohl(*p++);
815 p = xdr_decode_wcc_data(p, res->fattr);
818 return -nfs_stat_to_errno(status);
820 res->count = ntohl(*p++);
821 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
822 res->verf->verifier[0] = *p++;
823 res->verf->verifier[1] = *p++;
829 * Decode a CREATE response
832 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
836 status = ntohl(*p++);
839 if (!(p = xdr_decode_fhandle(p, res->fh)))
840 return -errno_NFSERR_IO;
841 p = xdr_decode_post_op_attr(p, res->fattr);
843 memset(res->fh, 0, sizeof(*res->fh));
844 /* Do decode post_op_attr but set it to NULL */
845 p = xdr_decode_post_op_attr(p, res->fattr);
846 res->fattr->valid = 0;
849 status = -nfs_stat_to_errno(status);
851 p = xdr_decode_wcc_data(p, res->dir_attr);
856 * Decode RENAME reply
859 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
863 if ((status = ntohl(*p++)) != 0)
864 status = -nfs_stat_to_errno(status);
865 p = xdr_decode_wcc_data(p, res->fromattr);
866 p = xdr_decode_wcc_data(p, res->toattr);
874 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
878 if ((status = ntohl(*p++)) != 0)
879 status = -nfs_stat_to_errno(status);
880 p = xdr_decode_post_op_attr(p, res->fattr);
881 p = xdr_decode_wcc_data(p, res->dir_attr);
886 * Decode FSSTAT reply
889 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
893 status = ntohl(*p++);
895 p = xdr_decode_post_op_attr(p, res->fattr);
897 return -nfs_stat_to_errno(status);
899 p = xdr_decode_hyper(p, &res->tbytes);
900 p = xdr_decode_hyper(p, &res->fbytes);
901 p = xdr_decode_hyper(p, &res->abytes);
902 p = xdr_decode_hyper(p, &res->tfiles);
903 p = xdr_decode_hyper(p, &res->ffiles);
904 p = xdr_decode_hyper(p, &res->afiles);
906 /* ignore invarsec */
911 * Decode FSINFO reply
914 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
918 status = ntohl(*p++);
920 p = xdr_decode_post_op_attr(p, res->fattr);
922 return -nfs_stat_to_errno(status);
924 res->rtmax = ntohl(*p++);
925 res->rtpref = ntohl(*p++);
926 res->rtmult = ntohl(*p++);
927 res->wtmax = ntohl(*p++);
928 res->wtpref = ntohl(*p++);
929 res->wtmult = ntohl(*p++);
930 res->dtpref = ntohl(*p++);
931 p = xdr_decode_hyper(p, &res->maxfilesize);
933 /* ignore time_delta and properties */
939 * Decode PATHCONF reply
942 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
946 status = ntohl(*p++);
948 p = xdr_decode_post_op_attr(p, res->fattr);
950 return -nfs_stat_to_errno(status);
951 res->max_link = ntohl(*p++);
952 res->max_namelen = ntohl(*p++);
954 /* ignore remaining fields */
959 * Decode COMMIT reply
962 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
966 status = ntohl(*p++);
967 p = xdr_decode_wcc_data(p, res->fattr);
969 return -nfs_stat_to_errno(status);
971 res->verf->verifier[0] = *p++;
972 res->verf->verifier[1] = *p++;
977 # define MAX(a, b) (((a) > (b))? (a) : (b))
980 #define PROC(proc, argtype, restype, timer) \
981 [NFS3PROC_##proc] = { \
982 .p_proc = NFS3PROC_##proc, \
983 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
984 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
985 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
989 struct rpc_procinfo nfs3_procedures[] = {
990 PROC(GETATTR, fhandle, attrstat, 1),
991 PROC(SETATTR, sattrargs, wccstat, 0),
992 PROC(LOOKUP, diropargs, lookupres, 2),
993 PROC(ACCESS, accessargs, accessres, 1),
994 PROC(READLINK, readlinkargs, readlinkres, 3),
995 PROC(READ, readargs, readres, 3),
996 PROC(WRITE, writeargs, writeres, 4),
997 PROC(CREATE, createargs, createres, 0),
998 PROC(MKDIR, mkdirargs, createres, 0),
999 PROC(SYMLINK, symlinkargs, createres, 0),
1000 PROC(MKNOD, mknodargs, createres, 0),
1001 PROC(REMOVE, diropargs, wccstat, 0),
1002 PROC(RMDIR, diropargs, wccstat, 0),
1003 PROC(RENAME, renameargs, renameres, 0),
1004 PROC(LINK, linkargs, linkres, 0),
1005 PROC(READDIR, readdirargs, readdirres, 3),
1006 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1007 PROC(FSSTAT, fhandle, fsstatres, 0),
1008 PROC(FSINFO, fhandle, fsinfores, 0),
1009 PROC(PATHCONF, fhandle, pathconfres, 0),
1010 PROC(COMMIT, commitargs, commitres, 5),
1013 struct rpc_version nfs_version3 = {
1015 .nrprocs = sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
1016 .procs = nfs3_procedures