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/sched.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_enc_void_sz 0
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_dec_void_sz 0
68 #define NFS3_attrstat_sz 1+NFS3_fattr_sz
69 #define NFS3_wccstat_sz 1+NFS3_wcc_data_sz
70 #define NFS3_lookupres_sz 1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)
71 #define NFS3_accessres_sz 1+NFS3_post_op_attr_sz+1
72 #define NFS3_readlinkres_sz 1+NFS3_post_op_attr_sz
73 #define NFS3_readres_sz 1+NFS3_post_op_attr_sz+3
74 #define NFS3_writeres_sz 1+NFS3_wcc_data_sz+4
75 #define NFS3_createres_sz 1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
76 #define NFS3_renameres_sz 1+(2 * NFS3_wcc_data_sz)
77 #define NFS3_linkres_sz 1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz
78 #define NFS3_readdirres_sz 1+NFS3_post_op_attr_sz+2
79 #define NFS3_fsstatres_sz 1+NFS3_post_op_attr_sz+13
80 #define NFS3_fsinfores_sz 1+NFS3_post_op_attr_sz+12
81 #define NFS3_pathconfres_sz 1+NFS3_post_op_attr_sz+6
82 #define NFS3_commitres_sz 1+NFS3_wcc_data_sz+2
85 * Map file type to S_IFMT bits
89 unsigned int nfs2type;
103 * Common NFS XDR functions as inlines
106 xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
108 *p++ = htonl(fh->size);
109 memcpy(p, fh->data, fh->size);
110 return p + XDR_QUADLEN(fh->size);
114 xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
117 * Zero all nonused bytes
119 memset((u8 *)fh, 0, sizeof(*fh));
120 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
121 memcpy(fh->data, p, fh->size);
122 return p + XDR_QUADLEN(fh->size);
128 * Encode/decode time.
129 * Since the VFS doesn't care for fractional times, we ignore the
133 xdr_encode_time(u32 *p, time_t time)
141 xdr_decode_time3(u32 *p, u64 *timep)
143 u64 tmp = (u64)ntohl(*p++) << 32;
144 *timep = tmp + (u64)ntohl(*p++);
149 xdr_encode_time3(u32 *p, u64 time)
151 *p++ = htonl(time >> 32);
152 *p++ = htonl(time & 0xFFFFFFFF);
157 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
165 fmode = nfs_type2fmt[type].mode;
166 fattr->type = nfs_type2fmt[type].nfs2type;
167 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
168 fattr->nlink = ntohl(*p++);
169 fattr->uid = ntohl(*p++);
170 fattr->gid = ntohl(*p++);
171 p = xdr_decode_hyper(p, &fattr->size);
172 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
173 /* Turn remote device info into Linux-specific dev_t */
174 fattr->rdev = ntohl(*p++) << MINORBITS;
175 fattr->rdev |= ntohl(*p++) & MINORMASK;
176 p = xdr_decode_hyper(p, &fattr->fsid);
177 p = xdr_decode_hyper(p, &fattr->fileid);
178 p = xdr_decode_time3(p, &fattr->atime);
179 p = xdr_decode_time3(p, &fattr->mtime);
180 p = xdr_decode_time3(p, &fattr->ctime);
182 /* Update the mode bits */
183 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
188 xdr_encode_sattr(u32 *p, struct iattr *attr)
190 if (attr->ia_valid & ATTR_MODE) {
192 *p++ = htonl(attr->ia_mode);
196 if (attr->ia_valid & ATTR_UID) {
198 *p++ = htonl(attr->ia_uid);
202 if (attr->ia_valid & ATTR_GID) {
204 *p++ = htonl(attr->ia_gid);
208 if (attr->ia_valid & ATTR_SIZE) {
210 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
214 if (attr->ia_valid & ATTR_ATIME_SET) {
216 p = xdr_encode_time(p, attr->ia_atime);
217 } else if (attr->ia_valid & ATTR_ATIME) {
222 if (attr->ia_valid & ATTR_MTIME_SET) {
224 p = xdr_encode_time(p, attr->ia_mtime);
225 } else if (attr->ia_valid & ATTR_MTIME) {
234 xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
236 p = xdr_decode_hyper(p, &fattr->pre_size);
237 p = xdr_decode_time3(p, &fattr->pre_mtime);
238 p = xdr_decode_time3(p, &fattr->pre_ctime);
239 fattr->valid |= NFS_ATTR_WCC;
244 xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
247 p = xdr_decode_fattr(p, fattr);
252 xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
255 return xdr_decode_wcc_attr(p, fattr);
261 xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
263 p = xdr_decode_pre_op_attr(p, fattr);
264 return xdr_decode_post_op_attr(p, fattr);
268 * NFS encode functions
271 * Encode void argument
274 nfs3_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
276 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
281 * Encode file handle argument
284 nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
286 p = xdr_encode_fhandle(p, fh);
287 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
292 * Encode SETATTR arguments
295 nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
297 p = xdr_encode_fhandle(p, args->fh);
298 p = xdr_encode_sattr(p, args->sattr);
299 *p++ = htonl(args->guard);
301 p = xdr_encode_time3(p, args->guardtime);
302 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
307 * Encode directory ops argument
310 nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
312 p = xdr_encode_fhandle(p, args->fh);
313 p = xdr_encode_array(p, args->name, args->len);
314 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
319 * Encode access() argument
322 nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
324 p = xdr_encode_fhandle(p, args->fh);
325 *p++ = htonl(args->access);
326 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
331 * Arguments to a READ call. Since we read data directly into the page
332 * cache, we also set up the reply iovec here so that iov[1] points
333 * exactly to the page we want to fetch.
336 nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
338 struct rpc_auth *auth = req->rq_task->tk_auth;
340 u32 count = args->count;
342 p = xdr_encode_fhandle(p, args->fh);
343 p = xdr_encode_hyper(p, args->offset);
345 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
347 /* Inline the page array */
348 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
349 xdr_inline_pages(&req->rq_rcv_buf, replen,
350 args->pages, args->pgbase, count);
355 * Write arguments. Splice the buffer to be written into the iovec.
358 nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
360 struct xdr_buf *sndbuf = &req->rq_snd_buf;
361 u32 count = args->count;
363 p = xdr_encode_fhandle(p, args->fh);
364 p = xdr_encode_hyper(p, args->offset);
366 *p++ = htonl(args->stable);
368 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
370 /* Copy the page array */
371 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
376 * Encode CREATE arguments
379 nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
381 p = xdr_encode_fhandle(p, args->fh);
382 p = xdr_encode_array(p, args->name, args->len);
384 *p++ = htonl(args->createmode);
385 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
386 *p++ = args->verifier[0];
387 *p++ = args->verifier[1];
389 p = xdr_encode_sattr(p, args->sattr);
391 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
396 * Encode MKDIR arguments
399 nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
401 p = xdr_encode_fhandle(p, args->fh);
402 p = xdr_encode_array(p, args->name, args->len);
403 p = xdr_encode_sattr(p, args->sattr);
404 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
409 * Encode SYMLINK arguments
412 nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
414 p = xdr_encode_fhandle(p, args->fromfh);
415 p = xdr_encode_array(p, args->fromname, args->fromlen);
416 p = xdr_encode_sattr(p, args->sattr);
417 p = xdr_encode_array(p, args->topath, args->tolen);
418 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
423 * Encode MKNOD arguments
426 nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
428 p = xdr_encode_fhandle(p, args->fh);
429 p = xdr_encode_array(p, args->name, args->len);
430 *p++ = htonl(args->type);
431 p = xdr_encode_sattr(p, args->sattr);
432 if (args->type == NF3CHR || args->type == NF3BLK) {
433 *p++ = htonl(args->rdev >> MINORBITS);
434 *p++ = htonl(args->rdev & MINORMASK);
437 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
442 * Encode RENAME arguments
445 nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
447 p = xdr_encode_fhandle(p, args->fromfh);
448 p = xdr_encode_array(p, args->fromname, args->fromlen);
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 LINK arguments
459 nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
461 p = xdr_encode_fhandle(p, args->fromfh);
462 p = xdr_encode_fhandle(p, args->tofh);
463 p = xdr_encode_array(p, args->toname, args->tolen);
464 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
469 * Encode arguments to readdir call
472 nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
474 struct rpc_auth *auth = req->rq_task->tk_auth;
476 u32 count = args->count;
478 p = xdr_encode_fhandle(p, args->fh);
479 p = xdr_encode_hyper(p, args->cookie);
480 *p++ = args->verf[0];
481 *p++ = args->verf[1];
483 /* readdirplus: need dircount + buffer size.
484 * We just make sure we make dircount big enough */
485 *p++ = htonl(count >> 3);
488 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
490 /* Inline the page array */
491 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
492 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
497 * Decode the result of a readdir call.
498 * We just check for syntactical correctness.
501 nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
503 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
504 struct iovec *iov = rcvbuf->head;
508 unsigned int len, pglen;
511 status = ntohl(*p++);
512 /* Decode post_op_attrs */
513 p = xdr_decode_post_op_attr(p, res->dir_attr);
515 return -nfs_stat_to_errno(status);
516 /* Decode verifier cookie */
524 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
525 if (iov->iov_len < hdrlen) {
526 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
527 "length %d > %Zu\n", hdrlen, iov->iov_len);
528 return -errno_NFSERR_IO;
529 } else if (iov->iov_len != hdrlen) {
530 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
531 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
534 pglen = rcvbuf->page_len;
535 recvd = req->rq_received - hdrlen;
538 page = rcvbuf->pages;
540 end = (u32 *)((char *)p + pglen);
542 for (nr = 0; *p++; nr++) {
545 p += 2; /* inode # */
546 len = ntohl(*p++); /* string length */
547 p += XDR_QUADLEN(len) + 2; /* name + cookie */
548 if (len > NFS3_MAXNAMLEN) {
549 printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
568 if (len > NFS3_FHSIZE) {
569 printk(KERN_WARNING "NFS: giant filehandle in "
570 "readdir (len %x)!\n", len);
573 p += XDR_QUADLEN(len);
581 if (!nr && (entry[0] != 0 || entry[1] == 0))
587 entry[0] = entry[1] = 0;
588 /* truncate listing ? */
590 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
596 return -errno_NFSERR_IO;
600 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
604 return ERR_PTR(-EAGAIN);
606 return ERR_PTR(-EBADCOOKIE);
609 p = xdr_decode_hyper(p, &entry->ino);
610 entry->len = ntohl(*p++);
611 entry->name = (const char *) p;
612 p += XDR_QUADLEN(entry->len);
613 entry->prev_cookie = entry->cookie;
614 p = xdr_decode_hyper(p, &entry->cookie);
617 struct nfs_fattr fattr;
618 p = xdr_decode_post_op_attr(p, &fattr);
619 /* In fact, a post_op_fh3: */
622 p = xdr_decode_fhandle(p, &fh);
626 entry->eof = !p[0] && p[1];
631 * Encode COMMIT arguments
634 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
636 p = xdr_encode_fhandle(p, args->fh);
637 p = xdr_encode_hyper(p, args->offset);
638 *p++ = htonl(args->count);
639 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
644 * NFS XDR decode functions
650 nfs3_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
656 * Decode attrstat reply.
659 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
663 if ((status = ntohl(*p++)))
664 return -nfs_stat_to_errno(status);
665 xdr_decode_fattr(p, fattr);
670 * Decode status+wcc_data reply
671 * SATTR, REMOVE, RMDIR
674 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
678 if ((status = ntohl(*p++)))
679 status = -nfs_stat_to_errno(status);
680 xdr_decode_wcc_data(p, fattr);
685 * Decode LOOKUP reply
688 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
692 if ((status = ntohl(*p++))) {
693 status = -nfs_stat_to_errno(status);
695 if (!(p = xdr_decode_fhandle(p, res->fh)))
696 return -errno_NFSERR_IO;
697 p = xdr_decode_post_op_attr(p, res->fattr);
699 xdr_decode_post_op_attr(p, res->dir_attr);
704 * Decode ACCESS reply
707 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
709 int status = ntohl(*p++);
711 p = xdr_decode_post_op_attr(p, res->fattr);
713 return -nfs_stat_to_errno(status);
714 res->access = ntohl(*p++);
719 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
721 struct rpc_auth *auth = req->rq_task->tk_auth;
723 u32 count = args->count - 4;
725 p = xdr_encode_fhandle(p, args->fh);
726 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
728 /* Inline the page array */
729 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
730 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
735 * Decode READLINK reply
738 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
740 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
741 struct iovec *iov = rcvbuf->head;
747 status = ntohl(*p++);
748 p = xdr_decode_post_op_attr(p, fattr);
751 return -nfs_stat_to_errno(status);
753 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
754 if (iov->iov_len > hdrlen) {
755 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
756 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
759 strlen = (u32*)kmap(rcvbuf->pages[0]);
760 /* Convert length of symlink */
761 len = ntohl(*strlen);
762 if (len >= rcvbuf->page_len - sizeof(u32)) {
763 dprintk("NFS: server returned giant symlink!\n");
764 kunmap(rcvbuf->pages[0]);
765 return -ENAMETOOLONG;
768 /* NULL terminate the string we got */
769 string = (char *)(strlen + 1);
771 kunmap(rcvbuf->pages[0]);
779 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
781 struct iovec *iov = req->rq_rvec;
782 int status, count, ocount, recvd, hdrlen;
784 status = ntohl(*p++);
785 p = xdr_decode_post_op_attr(p, res->fattr);
788 return -nfs_stat_to_errno(status);
790 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
791 * in that it puts the count both in the res struct and in the
792 * opaque data count. */
794 res->eof = ntohl(*p++);
795 ocount = ntohl(*p++);
797 if (ocount != count) {
798 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
799 return -errno_NFSERR_IO;
802 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
803 if (iov->iov_len < hdrlen) {
804 printk(KERN_WARNING "NFS: READ reply header overflowed:"
805 "length %d > %Zu\n", hdrlen, iov->iov_len);
806 return -errno_NFSERR_IO;
807 } else if (iov->iov_len != hdrlen) {
808 dprintk("NFS: READ header is short. iovec will be shifted.\n");
809 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
812 recvd = req->rq_received - hdrlen;
814 printk(KERN_WARNING "NFS: server cheating in read reply: "
815 "count %d > recvd %d\n", count, recvd);
820 if (count < res->count)
827 * Decode WRITE response
830 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
834 status = ntohl(*p++);
835 p = xdr_decode_wcc_data(p, res->fattr);
838 return -nfs_stat_to_errno(status);
840 res->count = ntohl(*p++);
841 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
842 res->verf->verifier[0] = *p++;
843 res->verf->verifier[1] = *p++;
849 * Decode a CREATE response
852 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
856 status = ntohl(*p++);
859 if (!(p = xdr_decode_fhandle(p, res->fh)))
860 return -errno_NFSERR_IO;
861 p = xdr_decode_post_op_attr(p, res->fattr);
863 memset(res->fh, 0, sizeof(*res->fh));
864 /* Do decode post_op_attr but set it to NULL */
865 p = xdr_decode_post_op_attr(p, res->fattr);
866 res->fattr->valid = 0;
869 status = -nfs_stat_to_errno(status);
871 p = xdr_decode_wcc_data(p, res->dir_attr);
876 * Decode RENAME reply
879 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
883 if ((status = ntohl(*p++)) != 0)
884 status = -nfs_stat_to_errno(status);
885 p = xdr_decode_wcc_data(p, res->fromattr);
886 p = xdr_decode_wcc_data(p, res->toattr);
894 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
898 if ((status = ntohl(*p++)) != 0)
899 status = -nfs_stat_to_errno(status);
900 p = xdr_decode_post_op_attr(p, res->fattr);
901 p = xdr_decode_wcc_data(p, res->dir_attr);
906 * Decode FSSTAT reply
909 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
911 struct nfs_fattr dummy;
914 status = ntohl(*p++);
916 p = xdr_decode_post_op_attr(p, &dummy);
918 return -nfs_stat_to_errno(status);
920 p = xdr_decode_hyper(p, &res->tbytes);
921 p = xdr_decode_hyper(p, &res->fbytes);
922 p = xdr_decode_hyper(p, &res->abytes);
923 p = xdr_decode_hyper(p, &res->tfiles);
924 p = xdr_decode_hyper(p, &res->ffiles);
925 p = xdr_decode_hyper(p, &res->afiles);
927 /* ignore invarsec */
932 * Decode FSINFO reply
935 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
937 struct nfs_fattr dummy;
940 status = ntohl(*p++);
942 p = xdr_decode_post_op_attr(p, &dummy);
944 return -nfs_stat_to_errno(status);
946 res->rtmax = ntohl(*p++);
947 res->rtpref = ntohl(*p++);
948 res->rtmult = ntohl(*p++);
949 res->wtmax = ntohl(*p++);
950 res->wtpref = ntohl(*p++);
951 res->wtmult = ntohl(*p++);
952 res->dtpref = ntohl(*p++);
953 p = xdr_decode_hyper(p, &res->maxfilesize);
955 /* ignore time_delta and properties */
960 * Decode PATHCONF reply
963 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
965 struct nfs_fattr dummy;
968 status = ntohl(*p++);
970 p = xdr_decode_post_op_attr(p, &dummy);
972 return -nfs_stat_to_errno(status);
973 res->linkmax = ntohl(*p++);
974 res->namelen = ntohl(*p++);
976 /* ignore remaining fields */
981 * Decode COMMIT reply
984 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
988 status = ntohl(*p++);
989 p = xdr_decode_wcc_data(p, res->fattr);
991 return -nfs_stat_to_errno(status);
993 res->verf->verifier[0] = *p++;
994 res->verf->verifier[1] = *p++;
999 # define MAX(a, b) (((a) > (b))? (a) : (b))
1002 #define PROC(proc, argtype, restype, timer) \
1003 { .p_procname = "nfs3_" #proc, \
1004 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1005 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1006 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1010 static struct rpc_procinfo nfs3_procedures[22] = {
1011 PROC(null, enc_void, dec_void, 0),
1012 PROC(getattr, fhandle, attrstat, 1),
1013 PROC(setattr, sattrargs, wccstat, 0),
1014 PROC(lookup, diropargs, lookupres, 2),
1015 PROC(access, accessargs, accessres, 1),
1016 PROC(readlink, readlinkargs, readlinkres, 3),
1017 PROC(read, readargs, readres, 3),
1018 PROC(write, writeargs, writeres, 4),
1019 PROC(create, createargs, createres, 0),
1020 PROC(mkdir, mkdirargs, createres, 0),
1021 PROC(symlink, symlinkargs, createres, 0),
1022 PROC(mknod, mknodargs, createres, 0),
1023 PROC(remove, diropargs, wccstat, 0),
1024 PROC(rmdir, diropargs, wccstat, 0),
1025 PROC(rename, renameargs, renameres, 0),
1026 PROC(link, linkargs, linkres, 0),
1027 PROC(readdir, readdirargs, readdirres, 3),
1028 PROC(readdirplus, readdirargs, readdirres, 3),
1029 PROC(fsstat, fhandle, fsstatres, 0),
1030 PROC(fsinfo, fhandle, fsinfores, 0),
1031 PROC(pathconf, fhandle, pathconfres, 0),
1032 PROC(commit, commitargs, commitres, 5),
1035 struct rpc_version nfs_version3 = {
1037 sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),