2 * linux/fs/nfs/nfs3xdr.c
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
6 * Copyright (C) 1996, 1997 Olaf Kirch
9 #include <linux/param.h>
10 #include <linux/time.h>
12 #include <linux/slab.h>
13 #include <linux/utsname.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
17 #include <linux/pagemap.h>
18 #include <linux/proc_fs.h>
19 #include <linux/kdev_t.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs3.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/nfsacl.h>
26 #define NFSDBG_FACILITY NFSDBG_XDR
28 /* Mapping from NFS error code to "errno" error code. */
29 #define errno_NFSERR_IO EIO
31 extern int nfs_stat_to_errno(int);
34 * Declare the space requirements for NFS arguments and replies as
35 * number of 32bit-words
37 #define NFS3_fhandle_sz (1+16)
38 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
39 #define NFS3_sattr_sz (15)
40 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
41 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
42 #define NFS3_fattr_sz (21)
43 #define NFS3_wcc_attr_sz (6)
44 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
45 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
46 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
47 #define NFS3_fsstat_sz
48 #define NFS3_fsinfo_sz
49 #define NFS3_pathconf_sz
50 #define NFS3_entry_sz (NFS3_filename_sz+3)
52 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
53 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
54 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
55 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
56 #define NFS3_readargs_sz (NFS3_fh_sz+3)
57 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
58 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
60 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+NFS3_path_sz+NFS3_sattr_sz)
61 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
63 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
64 #define NFS3_readdirargs_sz (NFS3_fh_sz+2)
65 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
67 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
68 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
69 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
70 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
71 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
72 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
73 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
74 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
75 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
76 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
77 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
78 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
79 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
80 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
81 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
83 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
84 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3))
85 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
86 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
89 * Map file type to S_IFMT bits
93 unsigned int nfs2type;
101 { S_IFSOCK, NFSOCK },
107 * Common NFS XDR functions as inlines
110 xdr_encode_fhandle(u32 *p, struct nfs_fh *fh)
112 return xdr_encode_array(p, fh->data, fh->size);
116 xdr_decode_fhandle(u32 *p, struct nfs_fh *fh)
118 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
119 memcpy(fh->data, p, fh->size);
120 return p + XDR_QUADLEN(fh->size);
126 * Encode/decode time.
129 xdr_encode_time3(u32 *p, struct timespec *timep)
131 *p++ = htonl(timep->tv_sec);
132 *p++ = htonl(timep->tv_nsec);
137 xdr_decode_time3(u32 *p, struct timespec *timep)
139 timep->tv_sec = ntohl(*p++);
140 timep->tv_nsec = ntohl(*p++);
145 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
147 unsigned int type, major, minor;
153 fmode = nfs_type2fmt[type].mode;
154 fattr->type = nfs_type2fmt[type].nfs2type;
155 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
156 fattr->nlink = ntohl(*p++);
157 fattr->uid = ntohl(*p++);
158 fattr->gid = ntohl(*p++);
159 p = xdr_decode_hyper(p, &fattr->size);
160 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
162 /* Turn remote device info into Linux-specific dev_t */
165 fattr->rdev = MKDEV(major, minor);
166 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
169 p = xdr_decode_hyper(p, &fattr->fsid_u.nfs3);
170 p = xdr_decode_hyper(p, &fattr->fileid);
171 p = xdr_decode_time3(p, &fattr->atime);
172 p = xdr_decode_time3(p, &fattr->mtime);
173 p = xdr_decode_time3(p, &fattr->ctime);
175 /* Update the mode bits */
176 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
177 fattr->timestamp = jiffies;
182 xdr_encode_sattr(u32 *p, struct iattr *attr)
184 if (attr->ia_valid & ATTR_MODE) {
186 *p++ = htonl(attr->ia_mode);
190 if (attr->ia_valid & ATTR_UID) {
192 *p++ = htonl(attr->ia_uid);
196 if (attr->ia_valid & ATTR_GID) {
198 *p++ = htonl(attr->ia_gid);
202 if (attr->ia_valid & ATTR_SIZE) {
204 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
208 if (attr->ia_valid & ATTR_ATIME_SET) {
210 p = xdr_encode_time3(p, &attr->ia_atime);
211 } else if (attr->ia_valid & ATTR_ATIME) {
216 if (attr->ia_valid & ATTR_MTIME_SET) {
218 p = xdr_encode_time3(p, &attr->ia_mtime);
219 } else if (attr->ia_valid & ATTR_MTIME) {
228 xdr_decode_wcc_attr(u32 *p, struct nfs_fattr *fattr)
230 p = xdr_decode_hyper(p, &fattr->pre_size);
231 p = xdr_decode_time3(p, &fattr->pre_mtime);
232 p = xdr_decode_time3(p, &fattr->pre_ctime);
233 fattr->valid |= NFS_ATTR_WCC;
238 xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
241 p = xdr_decode_fattr(p, fattr);
246 xdr_decode_pre_op_attr(u32 *p, struct nfs_fattr *fattr)
249 return xdr_decode_wcc_attr(p, fattr);
255 xdr_decode_wcc_data(u32 *p, struct nfs_fattr *fattr)
257 p = xdr_decode_pre_op_attr(p, fattr);
258 return xdr_decode_post_op_attr(p, fattr);
262 * NFS encode functions
266 * Encode file handle argument
269 nfs3_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
271 p = xdr_encode_fhandle(p, fh);
272 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
277 * Encode SETATTR arguments
280 nfs3_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs3_sattrargs *args)
282 p = xdr_encode_fhandle(p, args->fh);
283 p = xdr_encode_sattr(p, args->sattr);
284 *p++ = htonl(args->guard);
286 p = xdr_encode_time3(p, &args->guardtime);
287 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
292 * Encode directory ops argument
295 nfs3_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs3_diropargs *args)
297 p = xdr_encode_fhandle(p, args->fh);
298 p = xdr_encode_array(p, args->name, args->len);
299 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
304 * Encode access() argument
307 nfs3_xdr_accessargs(struct rpc_rqst *req, u32 *p, struct nfs3_accessargs *args)
309 p = xdr_encode_fhandle(p, args->fh);
310 *p++ = htonl(args->access);
311 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
316 * Arguments to a READ call. Since we read data directly into the page
317 * cache, we also set up the reply iovec here so that iov[1] points
318 * exactly to the page we want to fetch.
321 nfs3_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
323 struct rpc_auth *auth = req->rq_task->tk_auth;
325 u32 count = args->count;
327 p = xdr_encode_fhandle(p, args->fh);
328 p = xdr_encode_hyper(p, args->offset);
330 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
332 /* Inline the page array */
333 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
334 xdr_inline_pages(&req->rq_rcv_buf, replen,
335 args->pages, args->pgbase, count);
340 * Write arguments. Splice the buffer to be written into the iovec.
343 nfs3_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
345 struct xdr_buf *sndbuf = &req->rq_snd_buf;
346 u32 count = args->count;
348 p = xdr_encode_fhandle(p, args->fh);
349 p = xdr_encode_hyper(p, args->offset);
351 *p++ = htonl(args->stable);
353 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
355 /* Copy the page array */
356 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
361 * Encode CREATE arguments
364 nfs3_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs3_createargs *args)
366 p = xdr_encode_fhandle(p, args->fh);
367 p = xdr_encode_array(p, args->name, args->len);
369 *p++ = htonl(args->createmode);
370 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
371 *p++ = args->verifier[0];
372 *p++ = args->verifier[1];
374 p = xdr_encode_sattr(p, args->sattr);
376 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
381 * Encode MKDIR arguments
384 nfs3_xdr_mkdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_mkdirargs *args)
386 p = xdr_encode_fhandle(p, args->fh);
387 p = xdr_encode_array(p, args->name, args->len);
388 p = xdr_encode_sattr(p, args->sattr);
389 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
394 * Encode SYMLINK arguments
397 nfs3_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_symlinkargs *args)
399 p = xdr_encode_fhandle(p, args->fromfh);
400 p = xdr_encode_array(p, args->fromname, args->fromlen);
401 p = xdr_encode_sattr(p, args->sattr);
402 p = xdr_encode_array(p, args->topath, args->tolen);
403 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
408 * Encode MKNOD arguments
411 nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
413 p = xdr_encode_fhandle(p, args->fh);
414 p = xdr_encode_array(p, args->name, args->len);
415 *p++ = htonl(args->type);
416 p = xdr_encode_sattr(p, args->sattr);
417 if (args->type == NF3CHR || args->type == NF3BLK) {
418 *p++ = htonl(MAJOR(args->rdev));
419 *p++ = htonl(MINOR(args->rdev));
422 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
427 * Encode RENAME arguments
430 nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
432 p = xdr_encode_fhandle(p, args->fromfh);
433 p = xdr_encode_array(p, args->fromname, args->fromlen);
434 p = xdr_encode_fhandle(p, args->tofh);
435 p = xdr_encode_array(p, args->toname, args->tolen);
436 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
441 * Encode LINK arguments
444 nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
446 p = xdr_encode_fhandle(p, args->fromfh);
447 p = xdr_encode_fhandle(p, args->tofh);
448 p = xdr_encode_array(p, args->toname, args->tolen);
449 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
454 * Encode arguments to readdir call
457 nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
459 struct rpc_auth *auth = req->rq_task->tk_auth;
461 u32 count = args->count;
463 p = xdr_encode_fhandle(p, args->fh);
464 p = xdr_encode_hyper(p, args->cookie);
465 *p++ = args->verf[0];
466 *p++ = args->verf[1];
468 /* readdirplus: need dircount + buffer size.
469 * We just make sure we make dircount big enough */
470 *p++ = htonl(count >> 3);
473 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
475 /* Inline the page array */
476 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
477 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
482 * Decode the result of a readdir call.
483 * We just check for syntactical correctness.
486 nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
488 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
489 struct kvec *iov = rcvbuf->head;
493 unsigned int len, pglen;
494 u32 *entry, *end, *kaddr;
496 status = ntohl(*p++);
497 /* Decode post_op_attrs */
498 p = xdr_decode_post_op_attr(p, res->dir_attr);
500 return -nfs_stat_to_errno(status);
501 /* Decode verifier cookie */
509 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
510 if (iov->iov_len < hdrlen) {
511 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
512 "length %d > %Zu\n", hdrlen, iov->iov_len);
513 return -errno_NFSERR_IO;
514 } else if (iov->iov_len != hdrlen) {
515 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
516 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
519 pglen = rcvbuf->page_len;
520 recvd = rcvbuf->len - hdrlen;
523 page = rcvbuf->pages;
524 kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
525 end = (u32 *)((char *)p + pglen);
527 for (nr = 0; *p++; nr++) {
530 p += 2; /* inode # */
531 len = ntohl(*p++); /* string length */
532 p += XDR_QUADLEN(len) + 2; /* name + cookie */
533 if (len > NFS3_MAXNAMLEN) {
534 printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
553 if (len > NFS3_FHSIZE) {
554 printk(KERN_WARNING "NFS: giant filehandle in "
555 "readdir (len %x)!\n", len);
558 p += XDR_QUADLEN(len);
566 if (!nr && (entry[0] != 0 || entry[1] == 0))
569 kunmap_atomic(kaddr, KM_USER0);
572 entry[0] = entry[1] = 0;
573 /* truncate listing ? */
575 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
580 nr = -errno_NFSERR_IO;
585 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
587 struct nfs_entry old = *entry;
591 return ERR_PTR(-EAGAIN);
593 return ERR_PTR(-EBADCOOKIE);
596 p = xdr_decode_hyper(p, &entry->ino);
597 entry->len = ntohl(*p++);
598 entry->name = (const char *) p;
599 p += XDR_QUADLEN(entry->len);
600 entry->prev_cookie = entry->cookie;
601 p = xdr_decode_hyper(p, &entry->cookie);
604 entry->fattr->valid = 0;
605 p = xdr_decode_post_op_attr(p, entry->fattr);
606 /* In fact, a post_op_fh3: */
608 p = xdr_decode_fhandle(p, entry->fh);
609 /* Ugh -- server reply was truncated */
611 dprintk("NFS: FH truncated\n");
613 return ERR_PTR(-EAGAIN);
616 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
619 entry->eof = !p[0] && p[1];
624 * Encode COMMIT arguments
627 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
629 p = xdr_encode_fhandle(p, args->fh);
630 p = xdr_encode_hyper(p, args->offset);
631 *p++ = htonl(args->count);
632 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
636 #ifdef CONFIG_NFS_V3_ACL
638 * Encode GETACL arguments
641 nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
642 struct nfs3_getaclargs *args)
644 struct rpc_auth *auth = req->rq_task->tk_auth;
647 p = xdr_encode_fhandle(p, args->fh);
648 *p++ = htonl(args->mask);
649 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
651 if (args->mask & (NFS_ACL | NFS_DFACL)) {
652 /* Inline the page array */
653 replen = (RPC_REPHDRSIZE + auth->au_rslack +
654 ACL3_getaclres_sz) << 2;
655 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
656 NFSACL_MAXPAGES << PAGE_SHIFT);
662 * Encode SETACL arguments
665 nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
666 struct nfs3_setaclargs *args)
668 struct xdr_buf *buf = &req->rq_snd_buf;
669 unsigned int base, len_in_head, len = nfsacl_size(
670 (args->mask & NFS_ACL) ? args->acl_access : NULL,
671 (args->mask & NFS_DFACL) ? args->acl_default : NULL);
674 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
675 *p++ = htonl(args->mask);
676 base = (char *)p - (char *)buf->head->iov_base;
677 /* put as much of the acls into head as possible. */
678 len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
680 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
682 for (count = 0; (count << PAGE_SHIFT) < len; count++) {
683 args->pages[count] = alloc_page(GFP_KERNEL);
684 if (!args->pages[count]) {
686 __free_page(args->pages[--count]);
690 xdr_encode_pages(buf, args->pages, 0, len);
692 err = nfsacl_encode(buf, base, args->inode,
693 (args->mask & NFS_ACL) ?
694 args->acl_access : NULL, 1, 0);
696 err = nfsacl_encode(buf, base + err, args->inode,
697 (args->mask & NFS_DFACL) ?
698 args->acl_default : NULL, 1,
700 return (err > 0) ? 0 : err;
702 #endif /* CONFIG_NFS_V3_ACL */
705 * NFS XDR decode functions
709 * Decode attrstat reply.
712 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
716 if ((status = ntohl(*p++)))
717 return -nfs_stat_to_errno(status);
718 xdr_decode_fattr(p, fattr);
723 * Decode status+wcc_data reply
724 * SATTR, REMOVE, RMDIR
727 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
731 if ((status = ntohl(*p++)))
732 status = -nfs_stat_to_errno(status);
733 xdr_decode_wcc_data(p, fattr);
738 * Decode LOOKUP reply
741 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
745 if ((status = ntohl(*p++))) {
746 status = -nfs_stat_to_errno(status);
748 if (!(p = xdr_decode_fhandle(p, res->fh)))
749 return -errno_NFSERR_IO;
750 p = xdr_decode_post_op_attr(p, res->fattr);
752 xdr_decode_post_op_attr(p, res->dir_attr);
757 * Decode ACCESS reply
760 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
762 int status = ntohl(*p++);
764 p = xdr_decode_post_op_attr(p, res->fattr);
766 return -nfs_stat_to_errno(status);
767 res->access = ntohl(*p++);
772 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
774 struct rpc_auth *auth = req->rq_task->tk_auth;
777 p = xdr_encode_fhandle(p, args->fh);
778 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
780 /* Inline the page array */
781 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
782 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
787 * Decode READLINK reply
790 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
792 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
793 struct kvec *iov = rcvbuf->head;
794 int hdrlen, len, recvd;
798 status = ntohl(*p++);
799 p = xdr_decode_post_op_attr(p, fattr);
802 return -nfs_stat_to_errno(status);
804 /* Convert length of symlink */
806 if (len >= rcvbuf->page_len || len <= 0) {
807 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
808 return -ENAMETOOLONG;
811 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
812 if (iov->iov_len < hdrlen) {
813 printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
814 "length %d > %Zu\n", hdrlen, iov->iov_len);
815 return -errno_NFSERR_IO;
816 } else if (iov->iov_len != hdrlen) {
817 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
818 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
820 recvd = req->rq_rcv_buf.len - hdrlen;
822 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
823 "count %u > recvd %u\n", len, recvd);
827 /* NULL terminate the string we got */
828 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
829 kaddr[len+rcvbuf->page_base] = '\0';
830 kunmap_atomic(kaddr, KM_USER0);
838 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
840 struct kvec *iov = req->rq_rcv_buf.head;
841 int status, count, ocount, recvd, hdrlen;
843 status = ntohl(*p++);
844 p = xdr_decode_post_op_attr(p, res->fattr);
847 return -nfs_stat_to_errno(status);
849 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
850 * in that it puts the count both in the res struct and in the
851 * opaque data count. */
853 res->eof = ntohl(*p++);
854 ocount = ntohl(*p++);
856 if (ocount != count) {
857 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
858 return -errno_NFSERR_IO;
861 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
862 if (iov->iov_len < hdrlen) {
863 printk(KERN_WARNING "NFS: READ reply header overflowed:"
864 "length %d > %Zu\n", hdrlen, iov->iov_len);
865 return -errno_NFSERR_IO;
866 } else if (iov->iov_len != hdrlen) {
867 dprintk("NFS: READ header is short. iovec will be shifted.\n");
868 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
871 recvd = req->rq_rcv_buf.len - hdrlen;
873 printk(KERN_WARNING "NFS: server cheating in read reply: "
874 "count %d > recvd %d\n", count, recvd);
879 if (count < res->count)
886 * Decode WRITE response
889 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
893 status = ntohl(*p++);
894 p = xdr_decode_wcc_data(p, res->fattr);
897 return -nfs_stat_to_errno(status);
899 res->count = ntohl(*p++);
900 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
901 res->verf->verifier[0] = *p++;
902 res->verf->verifier[1] = *p++;
908 * Decode a CREATE response
911 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
915 status = ntohl(*p++);
918 if (!(p = xdr_decode_fhandle(p, res->fh)))
919 return -errno_NFSERR_IO;
920 p = xdr_decode_post_op_attr(p, res->fattr);
922 memset(res->fh, 0, sizeof(*res->fh));
923 /* Do decode post_op_attr but set it to NULL */
924 p = xdr_decode_post_op_attr(p, res->fattr);
925 res->fattr->valid = 0;
928 status = -nfs_stat_to_errno(status);
930 p = xdr_decode_wcc_data(p, res->dir_attr);
935 * Decode RENAME reply
938 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
942 if ((status = ntohl(*p++)) != 0)
943 status = -nfs_stat_to_errno(status);
944 p = xdr_decode_wcc_data(p, res->fromattr);
945 p = xdr_decode_wcc_data(p, res->toattr);
953 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
957 if ((status = ntohl(*p++)) != 0)
958 status = -nfs_stat_to_errno(status);
959 p = xdr_decode_post_op_attr(p, res->fattr);
960 p = xdr_decode_wcc_data(p, res->dir_attr);
965 * Decode FSSTAT reply
968 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
972 status = ntohl(*p++);
974 p = xdr_decode_post_op_attr(p, res->fattr);
976 return -nfs_stat_to_errno(status);
978 p = xdr_decode_hyper(p, &res->tbytes);
979 p = xdr_decode_hyper(p, &res->fbytes);
980 p = xdr_decode_hyper(p, &res->abytes);
981 p = xdr_decode_hyper(p, &res->tfiles);
982 p = xdr_decode_hyper(p, &res->ffiles);
983 p = xdr_decode_hyper(p, &res->afiles);
985 /* ignore invarsec */
990 * Decode FSINFO reply
993 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
997 status = ntohl(*p++);
999 p = xdr_decode_post_op_attr(p, res->fattr);
1001 return -nfs_stat_to_errno(status);
1003 res->rtmax = ntohl(*p++);
1004 res->rtpref = ntohl(*p++);
1005 res->rtmult = ntohl(*p++);
1006 res->wtmax = ntohl(*p++);
1007 res->wtpref = ntohl(*p++);
1008 res->wtmult = ntohl(*p++);
1009 res->dtpref = ntohl(*p++);
1010 p = xdr_decode_hyper(p, &res->maxfilesize);
1012 /* ignore time_delta and properties */
1013 res->lease_time = 0;
1018 * Decode PATHCONF reply
1021 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
1025 status = ntohl(*p++);
1027 p = xdr_decode_post_op_attr(p, res->fattr);
1029 return -nfs_stat_to_errno(status);
1030 res->max_link = ntohl(*p++);
1031 res->max_namelen = ntohl(*p++);
1033 /* ignore remaining fields */
1038 * Decode COMMIT reply
1041 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
1045 status = ntohl(*p++);
1046 p = xdr_decode_wcc_data(p, res->fattr);
1048 return -nfs_stat_to_errno(status);
1050 res->verf->verifier[0] = *p++;
1051 res->verf->verifier[1] = *p++;
1055 #ifdef CONFIG_NFS_V3_ACL
1057 * Decode GETACL reply
1060 nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
1061 struct nfs3_getaclres *res)
1063 struct xdr_buf *buf = &req->rq_rcv_buf;
1064 int status = ntohl(*p++);
1065 struct posix_acl **acl;
1066 unsigned int *aclcnt;
1070 return -nfs_stat_to_errno(status);
1071 p = xdr_decode_post_op_attr(p, res->fattr);
1072 res->mask = ntohl(*p++);
1073 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1075 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1077 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1078 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1079 err = nfsacl_decode(buf, base, aclcnt, acl);
1081 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1082 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1084 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1085 return (err > 0) ? 0 : err;
1089 * Decode setacl reply.
1092 nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
1094 int status = ntohl(*p++);
1097 return -nfs_stat_to_errno(status);
1098 xdr_decode_post_op_attr(p, fattr);
1101 #endif /* CONFIG_NFS_V3_ACL */
1104 # define MAX(a, b) (((a) > (b))? (a) : (b))
1107 #define PROC(proc, argtype, restype, timer) \
1108 [NFS3PROC_##proc] = { \
1109 .p_proc = NFS3PROC_##proc, \
1110 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1111 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1112 .p_bufsiz = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2, \
1116 struct rpc_procinfo nfs3_procedures[] = {
1117 PROC(GETATTR, fhandle, attrstat, 1),
1118 PROC(SETATTR, sattrargs, wccstat, 0),
1119 PROC(LOOKUP, diropargs, lookupres, 2),
1120 PROC(ACCESS, accessargs, accessres, 1),
1121 PROC(READLINK, readlinkargs, readlinkres, 3),
1122 PROC(READ, readargs, readres, 3),
1123 PROC(WRITE, writeargs, writeres, 4),
1124 PROC(CREATE, createargs, createres, 0),
1125 PROC(MKDIR, mkdirargs, createres, 0),
1126 PROC(SYMLINK, symlinkargs, createres, 0),
1127 PROC(MKNOD, mknodargs, createres, 0),
1128 PROC(REMOVE, diropargs, wccstat, 0),
1129 PROC(RMDIR, diropargs, wccstat, 0),
1130 PROC(RENAME, renameargs, renameres, 0),
1131 PROC(LINK, linkargs, linkres, 0),
1132 PROC(READDIR, readdirargs, readdirres, 3),
1133 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1134 PROC(FSSTAT, fhandle, fsstatres, 0),
1135 PROC(FSINFO, fhandle, fsinfores, 0),
1136 PROC(PATHCONF, fhandle, pathconfres, 0),
1137 PROC(COMMIT, commitargs, commitres, 5),
1140 struct rpc_version nfs_version3 = {
1142 .nrprocs = sizeof(nfs3_procedures)/sizeof(nfs3_procedures[0]),
1143 .procs = nfs3_procedures
1146 #ifdef CONFIG_NFS_V3_ACL
1147 static struct rpc_procinfo nfs3_acl_procedures[] = {
1148 [ACLPROC3_GETACL] = {
1149 .p_proc = ACLPROC3_GETACL,
1150 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1151 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1152 .p_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
1155 [ACLPROC3_SETACL] = {
1156 .p_proc = ACLPROC3_SETACL,
1157 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1158 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1159 .p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
1164 struct rpc_version nfsacl_version3 = {
1166 .nrprocs = sizeof(nfs3_acl_procedures)/
1167 sizeof(nfs3_acl_procedures[0]),
1168 .procs = nfs3_acl_procedures,
1170 #endif /* CONFIG_NFS_V3_ACL */