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/errno.h>
13 #include <linux/string.h>
15 #include <linux/pagemap.h>
16 #include <linux/proc_fs.h>
17 #include <linux/kdev_t.h>
18 #include <linux/sunrpc/clnt.h>
19 #include <linux/nfs.h>
20 #include <linux/nfs3.h>
21 #include <linux/nfs_fs.h>
22 #include <linux/nfsacl.h>
25 #define NFSDBG_FACILITY NFSDBG_XDR
27 /* Mapping from NFS error code to "errno" error code. */
28 #define errno_NFSERR_IO EIO
31 * Declare the space requirements for NFS arguments and replies as
32 * number of 32bit-words
34 #define NFS3_fhandle_sz (1+16)
35 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
36 #define NFS3_sattr_sz (15)
37 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
38 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
39 #define NFS3_fattr_sz (21)
40 #define NFS3_wcc_attr_sz (6)
41 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
42 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
43 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
44 #define NFS3_fsstat_sz
45 #define NFS3_fsinfo_sz
46 #define NFS3_pathconf_sz
47 #define NFS3_entry_sz (NFS3_filename_sz+3)
49 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
50 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
51 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
52 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
53 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
54 #define NFS3_readargs_sz (NFS3_fh_sz+3)
55 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
56 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
57 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
59 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
60 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
61 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
62 #define NFS3_readdirargs_sz (NFS3_fh_sz+2)
63 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
65 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
66 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
67 #define NFS3_removeres_sz (NFS3_wccstat_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)
82 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
83 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
84 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
85 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
87 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
90 * Map file type to S_IFMT bits
92 static const umode_t nfs_type2fmt[] = {
103 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
105 dprintk("nfs: %s: prematurely hit end of receive buffer. "
106 "Remaining buffer length is %tu words.\n",
107 func, xdr->end - xdr->p);
111 * Common NFS XDR functions as inlines
113 static inline __be32 *
114 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
116 return xdr_encode_array(p, fh->data, fh->size);
119 static inline __be32 *
120 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
122 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
123 memcpy(fh->data, p, fh->size);
124 return p + XDR_QUADLEN(fh->size);
129 static inline __be32 *
130 xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
133 p = xdr_inline_decode(xdr, 4);
136 fh->size = ntohl(*p++);
138 if (fh->size <= NFS3_FHSIZE) {
139 p = xdr_inline_decode(xdr, fh->size);
142 memcpy(fh->data, p, fh->size);
143 return p + XDR_QUADLEN(fh->size);
148 print_overflow_msg(__func__, xdr);
149 return ERR_PTR(-EIO);
153 * Encode/decode time.
155 static inline __be32 *
156 xdr_encode_time3(__be32 *p, struct timespec *timep)
158 *p++ = htonl(timep->tv_sec);
159 *p++ = htonl(timep->tv_nsec);
163 static inline __be32 *
164 xdr_decode_time3(__be32 *p, struct timespec *timep)
166 timep->tv_sec = ntohl(*p++);
167 timep->tv_nsec = ntohl(*p++);
172 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
174 unsigned int type, major, minor;
180 fmode = nfs_type2fmt[type];
181 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
182 fattr->nlink = ntohl(*p++);
183 fattr->uid = ntohl(*p++);
184 fattr->gid = ntohl(*p++);
185 p = xdr_decode_hyper(p, &fattr->size);
186 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
188 /* Turn remote device info into Linux-specific dev_t */
191 fattr->rdev = MKDEV(major, minor);
192 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
195 p = xdr_decode_hyper(p, &fattr->fsid.major);
196 fattr->fsid.minor = 0;
197 p = xdr_decode_hyper(p, &fattr->fileid);
198 p = xdr_decode_time3(p, &fattr->atime);
199 p = xdr_decode_time3(p, &fattr->mtime);
200 p = xdr_decode_time3(p, &fattr->ctime);
202 /* Update the mode bits */
203 fattr->valid |= NFS_ATTR_FATTR_V3;
207 static inline __be32 *
208 xdr_encode_sattr(__be32 *p, struct iattr *attr)
210 if (attr->ia_valid & ATTR_MODE) {
212 *p++ = htonl(attr->ia_mode & S_IALLUGO);
216 if (attr->ia_valid & ATTR_UID) {
218 *p++ = htonl(attr->ia_uid);
222 if (attr->ia_valid & ATTR_GID) {
224 *p++ = htonl(attr->ia_gid);
228 if (attr->ia_valid & ATTR_SIZE) {
230 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
234 if (attr->ia_valid & ATTR_ATIME_SET) {
236 p = xdr_encode_time3(p, &attr->ia_atime);
237 } else if (attr->ia_valid & ATTR_ATIME) {
242 if (attr->ia_valid & ATTR_MTIME_SET) {
244 p = xdr_encode_time3(p, &attr->ia_mtime);
245 } else if (attr->ia_valid & ATTR_MTIME) {
253 static inline __be32 *
254 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
256 p = xdr_decode_hyper(p, &fattr->pre_size);
257 p = xdr_decode_time3(p, &fattr->pre_mtime);
258 p = xdr_decode_time3(p, &fattr->pre_ctime);
259 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
260 | NFS_ATTR_FATTR_PREMTIME
261 | NFS_ATTR_FATTR_PRECTIME;
265 static inline __be32 *
266 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
269 p = xdr_decode_fattr(p, fattr);
273 static inline __be32 *
274 xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
278 p = xdr_inline_decode(xdr, 4);
282 p = xdr_inline_decode(xdr, 84);
285 p = xdr_decode_fattr(p, fattr);
289 print_overflow_msg(__func__, xdr);
290 return ERR_PTR(-EIO);
293 static inline __be32 *
294 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
297 return xdr_decode_wcc_attr(p, fattr);
302 static inline __be32 *
303 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
305 p = xdr_decode_pre_op_attr(p, fattr);
306 return xdr_decode_post_op_attr(p, fattr);
310 * NFS encode functions
314 * Encode file handle argument
317 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
319 p = xdr_encode_fhandle(p, fh);
320 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
325 * Encode SETATTR arguments
328 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
330 p = xdr_encode_fhandle(p, args->fh);
331 p = xdr_encode_sattr(p, args->sattr);
332 *p++ = htonl(args->guard);
334 p = xdr_encode_time3(p, &args->guardtime);
335 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
340 * Encode directory ops argument
343 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
345 p = xdr_encode_fhandle(p, args->fh);
346 p = xdr_encode_array(p, args->name, args->len);
347 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
352 * Encode REMOVE argument
355 nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
357 p = xdr_encode_fhandle(p, args->fh);
358 p = xdr_encode_array(p, args->name.name, args->name.len);
359 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
364 * Encode access() argument
367 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
369 p = xdr_encode_fhandle(p, args->fh);
370 *p++ = htonl(args->access);
371 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
376 * Arguments to a READ call. Since we read data directly into the page
377 * cache, we also set up the reply iovec here so that iov[1] points
378 * exactly to the page we want to fetch.
381 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
383 struct rpc_auth *auth = req->rq_cred->cr_auth;
385 u32 count = args->count;
387 p = xdr_encode_fhandle(p, args->fh);
388 p = xdr_encode_hyper(p, args->offset);
390 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
392 /* Inline the page array */
393 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
394 xdr_inline_pages(&req->rq_rcv_buf, replen,
395 args->pages, args->pgbase, count);
396 req->rq_rcv_buf.flags |= XDRBUF_READ;
401 * Write arguments. Splice the buffer to be written into the iovec.
404 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
406 struct xdr_buf *sndbuf = &req->rq_snd_buf;
407 u32 count = args->count;
409 p = xdr_encode_fhandle(p, args->fh);
410 p = xdr_encode_hyper(p, args->offset);
412 *p++ = htonl(args->stable);
414 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
416 /* Copy the page array */
417 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
418 sndbuf->flags |= XDRBUF_WRITE;
423 * Encode CREATE arguments
426 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
428 p = xdr_encode_fhandle(p, args->fh);
429 p = xdr_encode_array(p, args->name, args->len);
431 *p++ = htonl(args->createmode);
432 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
433 *p++ = args->verifier[0];
434 *p++ = args->verifier[1];
436 p = xdr_encode_sattr(p, args->sattr);
438 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
443 * Encode MKDIR arguments
446 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
448 p = xdr_encode_fhandle(p, args->fh);
449 p = xdr_encode_array(p, args->name, args->len);
450 p = xdr_encode_sattr(p, args->sattr);
451 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
456 * Encode SYMLINK arguments
459 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
461 p = xdr_encode_fhandle(p, args->fromfh);
462 p = xdr_encode_array(p, args->fromname, args->fromlen);
463 p = xdr_encode_sattr(p, args->sattr);
464 *p++ = htonl(args->pathlen);
465 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
468 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
473 * Encode MKNOD arguments
476 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
478 p = xdr_encode_fhandle(p, args->fh);
479 p = xdr_encode_array(p, args->name, args->len);
480 *p++ = htonl(args->type);
481 p = xdr_encode_sattr(p, args->sattr);
482 if (args->type == NF3CHR || args->type == NF3BLK) {
483 *p++ = htonl(MAJOR(args->rdev));
484 *p++ = htonl(MINOR(args->rdev));
487 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
492 * Encode RENAME arguments
495 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
497 p = xdr_encode_fhandle(p, args->old_dir);
498 p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
499 p = xdr_encode_fhandle(p, args->new_dir);
500 p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
501 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
506 * Encode LINK arguments
509 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
511 p = xdr_encode_fhandle(p, args->fromfh);
512 p = xdr_encode_fhandle(p, args->tofh);
513 p = xdr_encode_array(p, args->toname, args->tolen);
514 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
519 * Encode arguments to readdir call
522 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
524 struct rpc_auth *auth = req->rq_cred->cr_auth;
526 u32 count = args->count;
528 p = xdr_encode_fhandle(p, args->fh);
529 p = xdr_encode_hyper(p, args->cookie);
530 *p++ = args->verf[0];
531 *p++ = args->verf[1];
533 /* readdirplus: need dircount + buffer size.
534 * We just make sure we make dircount big enough */
535 *p++ = htonl(count >> 3);
538 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
540 /* Inline the page array */
541 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
542 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
547 * Decode the result of a readdir call.
548 * We just check for syntactical correctness.
551 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
553 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
554 struct kvec *iov = rcvbuf->head;
560 status = ntohl(*p++);
561 /* Decode post_op_attrs */
562 p = xdr_decode_post_op_attr(p, res->dir_attr);
564 return nfs_stat_to_errno(status);
565 /* Decode verifier cookie */
573 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
574 if (iov->iov_len < hdrlen) {
575 dprintk("NFS: READDIR reply header overflowed:"
576 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
577 return -errno_NFSERR_IO;
578 } else if (iov->iov_len != hdrlen) {
579 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
580 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
583 pglen = rcvbuf->page_len;
584 recvd = rcvbuf->len - hdrlen;
587 page = rcvbuf->pages;
593 nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
596 struct nfs_entry old = *entry;
598 p = xdr_inline_decode(xdr, 4);
602 p = xdr_inline_decode(xdr, 4);
606 return ERR_PTR(-EAGAIN);
608 return ERR_PTR(-EBADCOOKIE);
611 p = xdr_inline_decode(xdr, 12);
614 p = xdr_decode_hyper(p, &entry->ino);
615 entry->len = ntohl(*p++);
617 p = xdr_inline_decode(xdr, entry->len + 8);
620 entry->name = (const char *) p;
621 p += XDR_QUADLEN(entry->len);
622 entry->prev_cookie = entry->cookie;
623 p = xdr_decode_hyper(p, &entry->cookie);
625 entry->d_type = DT_UNKNOWN;
627 entry->fattr->valid = 0;
628 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
630 goto out_overflow_exit;
631 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
632 /* In fact, a post_op_fh3: */
633 p = xdr_inline_decode(xdr, 4);
637 p = xdr_decode_fhandle_stream(xdr, entry->fh);
639 goto out_overflow_exit;
640 /* Ugh -- server reply was truncated */
642 dprintk("NFS: FH truncated\n");
644 return ERR_PTR(-EAGAIN);
647 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
653 print_overflow_msg(__func__, xdr);
655 return ERR_PTR(-EAGAIN);
659 * Encode COMMIT arguments
662 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
664 p = xdr_encode_fhandle(p, args->fh);
665 p = xdr_encode_hyper(p, args->offset);
666 *p++ = htonl(args->count);
667 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
671 #ifdef CONFIG_NFS_V3_ACL
673 * Encode GETACL arguments
676 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
677 struct nfs3_getaclargs *args)
679 struct rpc_auth *auth = req->rq_cred->cr_auth;
682 p = xdr_encode_fhandle(p, args->fh);
683 *p++ = htonl(args->mask);
684 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
686 if (args->mask & (NFS_ACL | NFS_DFACL)) {
687 /* Inline the page array */
688 replen = (RPC_REPHDRSIZE + auth->au_rslack +
689 ACL3_getaclres_sz) << 2;
690 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
691 NFSACL_MAXPAGES << PAGE_SHIFT);
697 * Encode SETACL arguments
700 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
701 struct nfs3_setaclargs *args)
703 struct xdr_buf *buf = &req->rq_snd_buf;
707 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
708 *p++ = htonl(args->mask);
709 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
712 if (args->npages != 0)
713 xdr_encode_pages(buf, args->pages, 0, args->len);
715 req->rq_slen = xdr_adjust_iovec(req->rq_svec,
716 p + XDR_QUADLEN(args->len));
718 err = nfsacl_encode(buf, base, args->inode,
719 (args->mask & NFS_ACL) ?
720 args->acl_access : NULL, 1, 0);
722 err = nfsacl_encode(buf, base + err, args->inode,
723 (args->mask & NFS_DFACL) ?
724 args->acl_default : NULL, 1,
726 return (err > 0) ? 0 : err;
728 #endif /* CONFIG_NFS_V3_ACL */
731 * NFS XDR decode functions
735 * Decode attrstat reply.
738 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
742 if ((status = ntohl(*p++)))
743 return nfs_stat_to_errno(status);
744 xdr_decode_fattr(p, fattr);
749 * Decode status+wcc_data reply
750 * SATTR, REMOVE, RMDIR
753 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
757 if ((status = ntohl(*p++)))
758 status = nfs_stat_to_errno(status);
759 xdr_decode_wcc_data(p, fattr);
764 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
766 return nfs3_xdr_wccstat(req, p, res->dir_attr);
770 * Decode LOOKUP reply
773 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
777 if ((status = ntohl(*p++))) {
778 status = nfs_stat_to_errno(status);
780 if (!(p = xdr_decode_fhandle(p, res->fh)))
781 return -errno_NFSERR_IO;
782 p = xdr_decode_post_op_attr(p, res->fattr);
784 xdr_decode_post_op_attr(p, res->dir_attr);
789 * Decode ACCESS reply
792 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
794 int status = ntohl(*p++);
796 p = xdr_decode_post_op_attr(p, res->fattr);
798 return nfs_stat_to_errno(status);
799 res->access = ntohl(*p++);
804 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
806 struct rpc_auth *auth = req->rq_cred->cr_auth;
809 p = xdr_encode_fhandle(p, args->fh);
810 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
812 /* Inline the page array */
813 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
814 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
819 * Decode READLINK reply
822 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
824 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
825 struct kvec *iov = rcvbuf->head;
830 status = ntohl(*p++);
831 p = xdr_decode_post_op_attr(p, fattr);
834 return nfs_stat_to_errno(status);
836 /* Convert length of symlink */
838 if (len >= rcvbuf->page_len) {
839 dprintk("nfs: server returned giant symlink!\n");
840 return -ENAMETOOLONG;
843 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
844 if (iov->iov_len < hdrlen) {
845 dprintk("NFS: READLINK reply header overflowed:"
846 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
847 return -errno_NFSERR_IO;
848 } else if (iov->iov_len != hdrlen) {
849 dprintk("NFS: READLINK header is short. "
850 "iovec will be shifted.\n");
851 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
853 recvd = req->rq_rcv_buf.len - hdrlen;
855 dprintk("NFS: server cheating in readlink reply: "
856 "count %u > recvd %u\n", len, recvd);
860 xdr_terminate_string(rcvbuf, len);
868 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
870 struct kvec *iov = req->rq_rcv_buf.head;
872 u32 count, ocount, recvd;
875 status = ntohl(*p++);
876 p = xdr_decode_post_op_attr(p, res->fattr);
879 return nfs_stat_to_errno(status);
881 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
882 * in that it puts the count both in the res struct and in the
883 * opaque data count. */
885 res->eof = ntohl(*p++);
886 ocount = ntohl(*p++);
888 if (ocount != count) {
889 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
890 return -errno_NFSERR_IO;
893 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
894 if (iov->iov_len < hdrlen) {
895 dprintk("NFS: READ reply header overflowed:"
896 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
897 return -errno_NFSERR_IO;
898 } else if (iov->iov_len != hdrlen) {
899 dprintk("NFS: READ header is short. iovec will be shifted.\n");
900 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
903 recvd = req->rq_rcv_buf.len - hdrlen;
905 dprintk("NFS: server cheating in read reply: "
906 "count %u > recvd %u\n", count, recvd);
911 if (count < res->count)
918 * Decode WRITE response
921 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
925 status = ntohl(*p++);
926 p = xdr_decode_wcc_data(p, res->fattr);
929 return nfs_stat_to_errno(status);
931 res->count = ntohl(*p++);
932 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
933 res->verf->verifier[0] = *p++;
934 res->verf->verifier[1] = *p++;
940 * Decode a CREATE response
943 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
947 status = ntohl(*p++);
950 if (!(p = xdr_decode_fhandle(p, res->fh)))
951 return -errno_NFSERR_IO;
952 p = xdr_decode_post_op_attr(p, res->fattr);
954 memset(res->fh, 0, sizeof(*res->fh));
955 /* Do decode post_op_attr but set it to NULL */
956 p = xdr_decode_post_op_attr(p, res->fattr);
957 res->fattr->valid = 0;
960 status = nfs_stat_to_errno(status);
962 p = xdr_decode_wcc_data(p, res->dir_attr);
967 * Decode RENAME reply
970 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
974 if ((status = ntohl(*p++)) != 0)
975 status = nfs_stat_to_errno(status);
976 p = xdr_decode_wcc_data(p, res->old_fattr);
977 p = xdr_decode_wcc_data(p, res->new_fattr);
985 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
989 if ((status = ntohl(*p++)) != 0)
990 status = nfs_stat_to_errno(status);
991 p = xdr_decode_post_op_attr(p, res->fattr);
992 p = xdr_decode_wcc_data(p, res->dir_attr);
997 * Decode FSSTAT reply
1000 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1004 status = ntohl(*p++);
1006 p = xdr_decode_post_op_attr(p, res->fattr);
1008 return nfs_stat_to_errno(status);
1010 p = xdr_decode_hyper(p, &res->tbytes);
1011 p = xdr_decode_hyper(p, &res->fbytes);
1012 p = xdr_decode_hyper(p, &res->abytes);
1013 p = xdr_decode_hyper(p, &res->tfiles);
1014 p = xdr_decode_hyper(p, &res->ffiles);
1015 p = xdr_decode_hyper(p, &res->afiles);
1017 /* ignore invarsec */
1022 * Decode FSINFO reply
1025 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1029 status = ntohl(*p++);
1031 p = xdr_decode_post_op_attr(p, res->fattr);
1033 return nfs_stat_to_errno(status);
1035 res->rtmax = ntohl(*p++);
1036 res->rtpref = ntohl(*p++);
1037 res->rtmult = ntohl(*p++);
1038 res->wtmax = ntohl(*p++);
1039 res->wtpref = ntohl(*p++);
1040 res->wtmult = ntohl(*p++);
1041 res->dtpref = ntohl(*p++);
1042 p = xdr_decode_hyper(p, &res->maxfilesize);
1043 p = xdr_decode_time3(p, &res->time_delta);
1045 /* ignore properties */
1046 res->lease_time = 0;
1051 * Decode PATHCONF reply
1054 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1058 status = ntohl(*p++);
1060 p = xdr_decode_post_op_attr(p, res->fattr);
1062 return nfs_stat_to_errno(status);
1063 res->max_link = ntohl(*p++);
1064 res->max_namelen = ntohl(*p++);
1066 /* ignore remaining fields */
1071 * Decode COMMIT reply
1074 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1078 status = ntohl(*p++);
1079 p = xdr_decode_wcc_data(p, res->fattr);
1081 return nfs_stat_to_errno(status);
1083 res->verf->verifier[0] = *p++;
1084 res->verf->verifier[1] = *p++;
1088 #ifdef CONFIG_NFS_V3_ACL
1090 * Decode GETACL reply
1093 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1094 struct nfs3_getaclres *res)
1096 struct xdr_buf *buf = &req->rq_rcv_buf;
1097 int status = ntohl(*p++);
1098 struct posix_acl **acl;
1099 unsigned int *aclcnt;
1103 return nfs_stat_to_errno(status);
1104 p = xdr_decode_post_op_attr(p, res->fattr);
1105 res->mask = ntohl(*p++);
1106 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1108 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1110 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1111 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1112 err = nfsacl_decode(buf, base, aclcnt, acl);
1114 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1115 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1117 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1118 return (err > 0) ? 0 : err;
1122 * Decode setacl reply.
1125 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1127 int status = ntohl(*p++);
1130 return nfs_stat_to_errno(status);
1131 xdr_decode_post_op_attr(p, fattr);
1134 #endif /* CONFIG_NFS_V3_ACL */
1136 #define PROC(proc, argtype, restype, timer) \
1137 [NFS3PROC_##proc] = { \
1138 .p_proc = NFS3PROC_##proc, \
1139 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1140 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1141 .p_arglen = NFS3_##argtype##_sz, \
1142 .p_replen = NFS3_##restype##_sz, \
1144 .p_statidx = NFS3PROC_##proc, \
1148 struct rpc_procinfo nfs3_procedures[] = {
1149 PROC(GETATTR, fhandle, attrstat, 1),
1150 PROC(SETATTR, sattrargs, wccstat, 0),
1151 PROC(LOOKUP, diropargs, lookupres, 2),
1152 PROC(ACCESS, accessargs, accessres, 1),
1153 PROC(READLINK, readlinkargs, readlinkres, 3),
1154 PROC(READ, readargs, readres, 3),
1155 PROC(WRITE, writeargs, writeres, 4),
1156 PROC(CREATE, createargs, createres, 0),
1157 PROC(MKDIR, mkdirargs, createres, 0),
1158 PROC(SYMLINK, symlinkargs, createres, 0),
1159 PROC(MKNOD, mknodargs, createres, 0),
1160 PROC(REMOVE, removeargs, removeres, 0),
1161 PROC(RMDIR, diropargs, wccstat, 0),
1162 PROC(RENAME, renameargs, renameres, 0),
1163 PROC(LINK, linkargs, linkres, 0),
1164 PROC(READDIR, readdirargs, readdirres, 3),
1165 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1166 PROC(FSSTAT, fhandle, fsstatres, 0),
1167 PROC(FSINFO, fhandle, fsinfores, 0),
1168 PROC(PATHCONF, fhandle, pathconfres, 0),
1169 PROC(COMMIT, commitargs, commitres, 5),
1172 struct rpc_version nfs_version3 = {
1174 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1175 .procs = nfs3_procedures
1178 #ifdef CONFIG_NFS_V3_ACL
1179 static struct rpc_procinfo nfs3_acl_procedures[] = {
1180 [ACLPROC3_GETACL] = {
1181 .p_proc = ACLPROC3_GETACL,
1182 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1183 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1184 .p_arglen = ACL3_getaclargs_sz,
1185 .p_replen = ACL3_getaclres_sz,
1189 [ACLPROC3_SETACL] = {
1190 .p_proc = ACLPROC3_SETACL,
1191 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1192 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1193 .p_arglen = ACL3_setaclargs_sz,
1194 .p_replen = ACL3_setaclres_sz,
1200 struct rpc_version nfsacl_version3 = {
1202 .nrprocs = sizeof(nfs3_acl_procedures)/
1203 sizeof(nfs3_acl_procedures[0]),
1204 .procs = nfs3_acl_procedures,
1206 #endif /* CONFIG_NFS_V3_ACL */