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)
602 struct nfs_entry old = *entry;
606 return ERR_PTR(-EAGAIN);
608 return ERR_PTR(-EBADCOOKIE);
611 p = xdr_decode_hyper(p, &entry->ino);
612 entry->len = ntohl(*p++);
613 entry->name = (const char *) p;
614 p += XDR_QUADLEN(entry->len);
615 entry->prev_cookie = entry->cookie;
616 p = xdr_decode_hyper(p, &entry->cookie);
619 p = xdr_decode_post_op_attr(p, &entry->fattr);
620 /* In fact, a post_op_fh3: */
622 p = xdr_decode_fhandle(p, &entry->fh);
623 /* Ugh -- server reply was truncated */
625 dprintk("NFS: FH truncated\n");
627 return ERR_PTR(-EAGAIN);
630 /* If we don't get a file handle, the attrs
631 * aren't worth a lot. */
632 entry->fattr.valid = 0;
636 entry->eof = !p[0] && p[1];
641 * Encode COMMIT arguments
644 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
646 p = xdr_encode_fhandle(p, args->fh);
647 p = xdr_encode_hyper(p, args->offset);
648 *p++ = htonl(args->count);
649 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
654 * NFS XDR decode functions
660 nfs3_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
666 * Decode attrstat reply.
669 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
673 if ((status = ntohl(*p++)))
674 return -nfs_stat_to_errno(status);
675 xdr_decode_fattr(p, fattr);
680 * Decode status+wcc_data reply
681 * SATTR, REMOVE, RMDIR
684 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
688 if ((status = ntohl(*p++)))
689 status = -nfs_stat_to_errno(status);
690 xdr_decode_wcc_data(p, fattr);
695 * Decode LOOKUP reply
698 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
702 if ((status = ntohl(*p++))) {
703 status = -nfs_stat_to_errno(status);
705 if (!(p = xdr_decode_fhandle(p, res->fh)))
706 return -errno_NFSERR_IO;
707 p = xdr_decode_post_op_attr(p, res->fattr);
709 xdr_decode_post_op_attr(p, res->dir_attr);
714 * Decode ACCESS reply
717 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
719 int status = ntohl(*p++);
721 p = xdr_decode_post_op_attr(p, res->fattr);
723 return -nfs_stat_to_errno(status);
724 res->access = ntohl(*p++);
729 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
731 struct rpc_auth *auth = req->rq_task->tk_auth;
733 u32 count = args->count - 4;
735 p = xdr_encode_fhandle(p, args->fh);
736 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
738 /* Inline the page array */
739 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
740 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
745 * Decode READLINK reply
748 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
750 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
751 struct iovec *iov = rcvbuf->head;
757 status = ntohl(*p++);
758 p = xdr_decode_post_op_attr(p, fattr);
761 return -nfs_stat_to_errno(status);
763 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
764 if (iov->iov_len > hdrlen) {
765 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
766 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
769 strlen = (u32*)kmap(rcvbuf->pages[0]);
770 /* Convert length of symlink */
771 len = ntohl(*strlen);
772 if (len > rcvbuf->page_len)
773 len = rcvbuf->page_len;
775 /* NULL terminate the string we got */
776 string = (char *)(strlen + 1);
778 kunmap(rcvbuf->pages[0]);
786 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
788 struct iovec *iov = req->rq_rvec;
789 int status, count, ocount, recvd, hdrlen;
791 status = ntohl(*p++);
792 p = xdr_decode_post_op_attr(p, res->fattr);
795 return -nfs_stat_to_errno(status);
797 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
798 * in that it puts the count both in the res struct and in the
799 * opaque data count. */
801 res->eof = ntohl(*p++);
802 ocount = ntohl(*p++);
804 if (ocount != count) {
805 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
806 return -errno_NFSERR_IO;
809 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
810 if (iov->iov_len < hdrlen) {
811 printk(KERN_WARNING "NFS: READ reply header overflowed:"
812 "length %d > %Zu\n", hdrlen, iov->iov_len);
813 return -errno_NFSERR_IO;
814 } else if (iov->iov_len != hdrlen) {
815 dprintk("NFS: READ header is short. iovec will be shifted.\n");
816 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
819 recvd = req->rq_received - hdrlen;
821 printk(KERN_WARNING "NFS: server cheating in read reply: "
822 "count %d > recvd %d\n", count, recvd);
827 if (count < res->count)
834 * Decode WRITE response
837 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
841 status = ntohl(*p++);
842 p = xdr_decode_wcc_data(p, res->fattr);
845 return -nfs_stat_to_errno(status);
847 res->count = ntohl(*p++);
848 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
849 res->verf->verifier[0] = *p++;
850 res->verf->verifier[1] = *p++;
856 * Decode a CREATE response
859 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
863 status = ntohl(*p++);
866 if (!(p = xdr_decode_fhandle(p, res->fh)))
867 return -errno_NFSERR_IO;
868 p = xdr_decode_post_op_attr(p, res->fattr);
870 memset(res->fh, 0, sizeof(*res->fh));
871 /* Do decode post_op_attr but set it to NULL */
872 p = xdr_decode_post_op_attr(p, res->fattr);
873 res->fattr->valid = 0;
876 status = -nfs_stat_to_errno(status);
878 p = xdr_decode_wcc_data(p, res->dir_attr);
883 * Decode RENAME reply
886 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
890 if ((status = ntohl(*p++)) != 0)
891 status = -nfs_stat_to_errno(status);
892 p = xdr_decode_wcc_data(p, res->fromattr);
893 p = xdr_decode_wcc_data(p, res->toattr);
901 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
905 if ((status = ntohl(*p++)) != 0)
906 status = -nfs_stat_to_errno(status);
907 p = xdr_decode_post_op_attr(p, res->fattr);
908 p = xdr_decode_wcc_data(p, res->dir_attr);
913 * Decode FSSTAT reply
916 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
918 struct nfs_fattr dummy;
921 status = ntohl(*p++);
923 p = xdr_decode_post_op_attr(p, &dummy);
925 return -nfs_stat_to_errno(status);
927 p = xdr_decode_hyper(p, &res->tbytes);
928 p = xdr_decode_hyper(p, &res->fbytes);
929 p = xdr_decode_hyper(p, &res->abytes);
930 p = xdr_decode_hyper(p, &res->tfiles);
931 p = xdr_decode_hyper(p, &res->ffiles);
932 p = xdr_decode_hyper(p, &res->afiles);
934 /* ignore invarsec */
939 * Decode FSINFO reply
942 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
944 struct nfs_fattr dummy;
947 status = ntohl(*p++);
949 p = xdr_decode_post_op_attr(p, &dummy);
951 return -nfs_stat_to_errno(status);
953 res->rtmax = ntohl(*p++);
954 res->rtpref = ntohl(*p++);
955 res->rtmult = ntohl(*p++);
956 res->wtmax = ntohl(*p++);
957 res->wtpref = ntohl(*p++);
958 res->wtmult = ntohl(*p++);
959 res->dtpref = ntohl(*p++);
960 p = xdr_decode_hyper(p, &res->maxfilesize);
962 /* ignore time_delta and properties */
967 * Decode PATHCONF reply
970 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
972 struct nfs_fattr dummy;
975 status = ntohl(*p++);
977 p = xdr_decode_post_op_attr(p, &dummy);
979 return -nfs_stat_to_errno(status);
980 res->linkmax = ntohl(*p++);
981 res->namelen = ntohl(*p++);
983 /* ignore remaining fields */
988 * Decode COMMIT reply
991 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
995 status = ntohl(*p++);
996 p = xdr_decode_wcc_data(p, res->fattr);
998 return -nfs_stat_to_errno(status);
1000 res->verf->verifier[0] = *p++;
1001 res->verf->verifier[1] = *p++;
1006 # define MAX(a, b) (((a) > (b))? (a) : (b))
1009 #define PROC(proc, argtype, restype, timer) \
1010 { .p_procname = "nfs3_" #proc, \
1011 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1012 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1013 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1017 static struct rpc_procinfo nfs3_procedures[22] = {
1018 PROC(null, enc_void, dec_void, 0),
1019 PROC(getattr, fhandle, attrstat, 1),
1020 PROC(setattr, sattrargs, wccstat, 0),
1021 PROC(lookup, diropargs, lookupres, 2),
1022 PROC(access, accessargs, accessres, 1),
1023 PROC(readlink, readlinkargs, readlinkres, 3),
1024 PROC(read, readargs, readres, 3),
1025 PROC(write, writeargs, writeres, 4),
1026 PROC(create, createargs, createres, 0),
1027 PROC(mkdir, mkdirargs, createres, 0),
1028 PROC(symlink, symlinkargs, createres, 0),
1029 PROC(mknod, mknodargs, createres, 0),
1030 PROC(remove, diropargs, wccstat, 0),
1031 PROC(rmdir, diropargs, wccstat, 0),
1032 PROC(rename, renameargs, renameres, 0),
1033 PROC(link, linkargs, linkres, 0),
1034 PROC(readdir, readdirargs, readdirres, 3),
1035 PROC(readdirplus, readdirargs, readdirres, 3),
1036 PROC(fsstat, fhandle, fsstatres, 0),
1037 PROC(fsinfo, fhandle, fsinfores, 0),
1038 PROC(pathconf, fhandle, pathconfres, 0),
1039 PROC(commit, commitargs, commitres, 5),
1042 struct rpc_version nfs_version3 = {
1044 sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),