2 * linux/fs/nfs/nfs2xdr.c
4 * XDR functions to encode/decode NFS RPC arguments and results.
6 * Copyright (C) 1992, 1993, 1994 Rick Sladkey
7 * Copyright (C) 1996 Olaf Kirch
8 * 04 Aug 1998 Ion Badulescu <ionut@cs.columbia.edu>
9 * FIFO's need special handling in NFSv2
12 #include <linux/param.h>
13 #include <linux/time.h>
15 #include <linux/slab.h>
16 #include <linux/utsname.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
20 #include <linux/pagemap.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sunrpc/clnt.h>
23 #include <linux/nfs.h>
24 #include <linux/nfs2.h>
25 #include <linux/nfs_fs.h>
28 #define NFSDBG_FACILITY NFSDBG_XDR
29 /* #define NFS_PARANOIA 1 */
31 /* Mapping from NFS error code to "errno" error code. */
32 #define errno_NFSERR_IO EIO
35 * Declare the space requirements for NFS arguments and replies as
36 * number of 32bit-words
38 #define NFS_fhandle_sz (8)
39 #define NFS_sattr_sz (8)
40 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
41 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
42 #define NFS_fattr_sz (17)
43 #define NFS_info_sz (5)
44 #define NFS_entry_sz (NFS_filename_sz+3)
46 #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
47 #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
48 #define NFS_readlinkargs_sz (NFS_fhandle_sz)
49 #define NFS_readargs_sz (NFS_fhandle_sz+3)
50 #define NFS_writeargs_sz (NFS_fhandle_sz+4)
51 #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
52 #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
53 #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
54 #define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz)
55 #define NFS_readdirargs_sz (NFS_fhandle_sz+2)
57 #define NFS_attrstat_sz (1+NFS_fattr_sz)
58 #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
59 #define NFS_readlinkres_sz (2)
60 #define NFS_readres_sz (1+NFS_fattr_sz+1)
61 #define NFS_writeres_sz (NFS_attrstat_sz)
62 #define NFS_stat_sz (1)
63 #define NFS_readdirres_sz (1)
64 #define NFS_statfsres_sz (1+NFS_info_sz)
67 * Common NFS XDR functions as inlines
69 static inline __be32 *
70 xdr_encode_fhandle(__be32 *p, struct nfs_fh *fhandle)
72 memcpy(p, fhandle->data, NFS2_FHSIZE);
73 return p + XDR_QUADLEN(NFS2_FHSIZE);
76 static inline __be32 *
77 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
79 /* NFSv2 handles have a fixed length */
80 fhandle->size = NFS2_FHSIZE;
81 memcpy(fhandle->data, p, NFS2_FHSIZE);
82 return p + XDR_QUADLEN(NFS2_FHSIZE);
86 xdr_encode_time(__be32 *p, struct timespec *timep)
88 *p++ = htonl(timep->tv_sec);
89 /* Convert nanoseconds into microseconds */
90 *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0);
95 xdr_encode_current_server_time(__be32 *p, struct timespec *timep)
98 * Passing the invalid value useconds=1000000 is a
99 * Sun convention for "set to current server time".
100 * It's needed to make permissions checks for the
101 * "touch" program across v2 mounts to Solaris and
102 * Irix boxes work correctly. See description of
103 * sattr in section 6.1 of "NFS Illustrated" by
104 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
106 *p++ = htonl(timep->tv_sec);
107 *p++ = htonl(1000000);
111 static inline __be32*
112 xdr_decode_time(__be32 *p, struct timespec *timep)
114 timep->tv_sec = ntohl(*p++);
115 /* Convert microseconds into nanoseconds */
116 timep->tv_nsec = ntohl(*p++) * 1000;
121 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
124 fattr->type = (enum nfs_ftype) ntohl(*p++);
125 fattr->mode = ntohl(*p++);
126 fattr->nlink = ntohl(*p++);
127 fattr->uid = ntohl(*p++);
128 fattr->gid = ntohl(*p++);
129 fattr->size = ntohl(*p++);
130 fattr->du.nfs2.blocksize = ntohl(*p++);
132 fattr->du.nfs2.blocks = ntohl(*p++);
133 fattr->fsid.major = ntohl(*p++);
134 fattr->fsid.minor = 0;
135 fattr->fileid = ntohl(*p++);
136 p = xdr_decode_time(p, &fattr->atime);
137 p = xdr_decode_time(p, &fattr->mtime);
138 p = xdr_decode_time(p, &fattr->ctime);
139 fattr->valid |= NFS_ATTR_FATTR;
140 fattr->rdev = new_decode_dev(rdev);
141 if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) {
142 fattr->type = NFFIFO;
143 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
149 static inline __be32 *
150 xdr_encode_sattr(__be32 *p, struct iattr *attr)
152 const __be32 not_set = __constant_htonl(0xFFFFFFFF);
154 *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
155 *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
156 *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
157 *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
159 if (attr->ia_valid & ATTR_ATIME_SET) {
160 p = xdr_encode_time(p, &attr->ia_atime);
161 } else if (attr->ia_valid & ATTR_ATIME) {
162 p = xdr_encode_current_server_time(p, &attr->ia_atime);
168 if (attr->ia_valid & ATTR_MTIME_SET) {
169 p = xdr_encode_time(p, &attr->ia_mtime);
170 } else if (attr->ia_valid & ATTR_MTIME) {
171 p = xdr_encode_current_server_time(p, &attr->ia_mtime);
180 * NFS encode functions
183 * Encode file handle argument
184 * GETATTR, READLINK, STATFS
187 nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
189 p = xdr_encode_fhandle(p, fh);
190 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
195 * Encode SETATTR arguments
198 nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
200 p = xdr_encode_fhandle(p, args->fh);
201 p = xdr_encode_sattr(p, args->sattr);
202 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
207 * Encode directory ops argument
208 * LOOKUP, REMOVE, RMDIR
211 nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
213 p = xdr_encode_fhandle(p, args->fh);
214 p = xdr_encode_array(p, args->name, args->len);
215 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
220 * Arguments to a READ call. Since we read data directly into the page
221 * cache, we also set up the reply iovec here so that iov[1] points
222 * exactly to the page we want to fetch.
225 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
227 struct rpc_auth *auth = req->rq_task->tk_auth;
229 u32 offset = (u32)args->offset;
230 u32 count = args->count;
232 p = xdr_encode_fhandle(p, args->fh);
233 *p++ = htonl(offset);
236 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
238 /* Inline the page array */
239 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
240 xdr_inline_pages(&req->rq_rcv_buf, replen,
241 args->pages, args->pgbase, count);
249 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
251 struct kvec *iov = req->rq_rcv_buf.head;
252 int status, count, recvd, hdrlen;
254 if ((status = ntohl(*p++)))
255 return -nfs_stat_to_errno(status);
256 p = xdr_decode_fattr(p, res->fattr);
260 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
261 if (iov->iov_len < hdrlen) {
262 printk(KERN_WARNING "NFS: READ reply header overflowed:"
263 "length %d > %Zu\n", hdrlen, iov->iov_len);
264 return -errno_NFSERR_IO;
265 } else if (iov->iov_len != hdrlen) {
266 dprintk("NFS: READ header is short. iovec will be shifted.\n");
267 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
270 recvd = req->rq_rcv_buf.len - hdrlen;
272 printk(KERN_WARNING "NFS: server cheating in read reply: "
273 "count %d > recvd %d\n", count, recvd);
277 dprintk("RPC: readres OK count %d\n", count);
278 if (count < res->count)
286 * Write arguments. Splice the buffer to be written into the iovec.
289 nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
291 struct xdr_buf *sndbuf = &req->rq_snd_buf;
292 u32 offset = (u32)args->offset;
293 u32 count = args->count;
295 p = xdr_encode_fhandle(p, args->fh);
296 *p++ = htonl(offset);
297 *p++ = htonl(offset);
300 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
302 /* Copy the page array */
303 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
308 * Encode create arguments
312 nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
314 p = xdr_encode_fhandle(p, args->fh);
315 p = xdr_encode_array(p, args->name, args->len);
316 p = xdr_encode_sattr(p, args->sattr);
317 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
322 * Encode RENAME arguments
325 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
327 p = xdr_encode_fhandle(p, args->fromfh);
328 p = xdr_encode_array(p, args->fromname, args->fromlen);
329 p = xdr_encode_fhandle(p, args->tofh);
330 p = xdr_encode_array(p, args->toname, args->tolen);
331 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
336 * Encode LINK arguments
339 nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
341 p = xdr_encode_fhandle(p, args->fromfh);
342 p = xdr_encode_fhandle(p, args->tofh);
343 p = xdr_encode_array(p, args->toname, args->tolen);
344 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
349 * Encode SYMLINK arguments
352 nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args)
354 struct xdr_buf *sndbuf = &req->rq_snd_buf;
357 p = xdr_encode_fhandle(p, args->fromfh);
358 p = xdr_encode_array(p, args->fromname, args->fromlen);
359 *p++ = htonl(args->pathlen);
360 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
362 xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);
365 * xdr_encode_pages may have added a few bytes to ensure the
366 * pathname ends on a 4-byte boundary. Start encoding the
367 * attributes after the pad bytes.
369 pad = sndbuf->tail->iov_len;
372 p = xdr_encode_sattr(p, args->sattr);
373 sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
378 * Encode arguments to readdir call
381 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
383 struct rpc_task *task = req->rq_task;
384 struct rpc_auth *auth = task->tk_auth;
386 u32 count = args->count;
388 p = xdr_encode_fhandle(p, args->fh);
389 *p++ = htonl(args->cookie);
390 *p++ = htonl(count); /* see above */
391 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
393 /* Inline the page array */
394 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
395 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
400 * Decode the result of a readdir call.
401 * We're not really decoding anymore, we just leave the buffer untouched
402 * and only check that it is syntactically correct.
403 * The real decoding happens in nfs_decode_entry below, called directly
404 * from nfs_readdir for each entry.
407 nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
409 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
410 struct kvec *iov = rcvbuf->head;
414 unsigned int len, pglen;
415 __be32 *end, *entry, *kaddr;
417 if ((status = ntohl(*p++)))
418 return -nfs_stat_to_errno(status);
420 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
421 if (iov->iov_len < hdrlen) {
422 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
423 "length %d > %Zu\n", hdrlen, iov->iov_len);
424 return -errno_NFSERR_IO;
425 } else if (iov->iov_len != hdrlen) {
426 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
427 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
430 pglen = rcvbuf->page_len;
431 recvd = rcvbuf->len - hdrlen;
434 page = rcvbuf->pages;
435 kaddr = p = kmap_atomic(*page, KM_USER0);
436 end = (__be32 *)((char *)p + pglen);
438 for (nr = 0; *p++; nr++) {
443 p += XDR_QUADLEN(len) + 1; /* name plus cookie */
444 if (len > NFS2_MAXNAMLEN) {
445 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n",
453 if (!nr && (entry[0] != 0 || entry[1] == 0))
456 kunmap_atomic(kaddr, KM_USER0);
459 entry[0] = entry[1] = 0;
460 /* truncate listing ? */
462 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
467 nr = -errno_NFSERR_IO;
472 nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
476 return ERR_PTR(-EAGAIN);
478 return ERR_PTR(-EBADCOOKIE);
481 entry->ino = ntohl(*p++);
482 entry->len = ntohl(*p++);
483 entry->name = (const char *) p;
484 p += XDR_QUADLEN(entry->len);
485 entry->prev_cookie = entry->cookie;
486 entry->cookie = ntohl(*p++);
487 entry->eof = !p[0] && p[1];
493 * NFS XDR decode functions
496 * Decode simple status reply
499 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
503 if ((status = ntohl(*p++)) != 0)
504 status = -nfs_stat_to_errno(status);
509 * Decode attrstat reply
510 * GETATTR, SETATTR, WRITE
513 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
517 if ((status = ntohl(*p++)))
518 return -nfs_stat_to_errno(status);
519 xdr_decode_fattr(p, fattr);
524 * Decode diropres reply
525 * LOOKUP, CREATE, MKDIR
528 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
532 if ((status = ntohl(*p++)))
533 return -nfs_stat_to_errno(status);
534 p = xdr_decode_fhandle(p, res->fh);
535 xdr_decode_fattr(p, res->fattr);
540 * Encode READLINK args
543 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
545 struct rpc_auth *auth = req->rq_task->tk_auth;
548 p = xdr_encode_fhandle(p, args->fh);
549 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
551 /* Inline the page array */
552 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
553 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
558 * Decode READLINK reply
561 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
563 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
564 struct kvec *iov = rcvbuf->head;
565 int hdrlen, len, recvd;
569 if ((status = ntohl(*p++)))
570 return -nfs_stat_to_errno(status);
571 /* Convert length of symlink */
573 if (len >= rcvbuf->page_len || len <= 0) {
574 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
575 return -ENAMETOOLONG;
577 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
578 if (iov->iov_len < hdrlen) {
579 printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
580 "length %d > %Zu\n", hdrlen, iov->iov_len);
581 return -errno_NFSERR_IO;
582 } else if (iov->iov_len != hdrlen) {
583 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
584 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
586 recvd = req->rq_rcv_buf.len - hdrlen;
588 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
589 "count %u > recvd %u\n", len, recvd);
593 /* NULL terminate the string we got */
594 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
595 kaddr[len+rcvbuf->page_base] = '\0';
596 kunmap_atomic(kaddr, KM_USER0);
604 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
606 res->verf->committed = NFS_FILE_SYNC;
607 return nfs_xdr_attrstat(req, p, res->fattr);
611 * Decode STATFS reply
614 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
618 if ((status = ntohl(*p++)))
619 return -nfs_stat_to_errno(status);
621 res->tsize = ntohl(*p++);
622 res->bsize = ntohl(*p++);
623 res->blocks = ntohl(*p++);
624 res->bfree = ntohl(*p++);
625 res->bavail = ntohl(*p++);
630 * We need to translate between nfs status return values and
631 * the local errno values which may not be the same.
638 { NFSERR_PERM, EPERM },
639 { NFSERR_NOENT, ENOENT },
640 { NFSERR_IO, errno_NFSERR_IO },
641 { NFSERR_NXIO, ENXIO },
642 /* { NFSERR_EAGAIN, EAGAIN }, */
643 { NFSERR_ACCES, EACCES },
644 { NFSERR_EXIST, EEXIST },
645 { NFSERR_XDEV, EXDEV },
646 { NFSERR_NODEV, ENODEV },
647 { NFSERR_NOTDIR, ENOTDIR },
648 { NFSERR_ISDIR, EISDIR },
649 { NFSERR_INVAL, EINVAL },
650 { NFSERR_FBIG, EFBIG },
651 { NFSERR_NOSPC, ENOSPC },
652 { NFSERR_ROFS, EROFS },
653 { NFSERR_MLINK, EMLINK },
654 { NFSERR_NAMETOOLONG, ENAMETOOLONG },
655 { NFSERR_NOTEMPTY, ENOTEMPTY },
656 { NFSERR_DQUOT, EDQUOT },
657 { NFSERR_STALE, ESTALE },
658 { NFSERR_REMOTE, EREMOTE },
660 { NFSERR_WFLUSH, EWFLUSH },
662 { NFSERR_BADHANDLE, EBADHANDLE },
663 { NFSERR_NOT_SYNC, ENOTSYNC },
664 { NFSERR_BAD_COOKIE, EBADCOOKIE },
665 { NFSERR_NOTSUPP, ENOTSUPP },
666 { NFSERR_TOOSMALL, ETOOSMALL },
667 { NFSERR_SERVERFAULT, ESERVERFAULT },
668 { NFSERR_BADTYPE, EBADTYPE },
669 { NFSERR_JUKEBOX, EJUKEBOX },
674 * Convert an NFS error code to a local one.
675 * This one is used jointly by NFSv2 and NFSv3.
678 nfs_stat_to_errno(int stat)
682 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
683 if (nfs_errtbl[i].stat == stat)
684 return nfs_errtbl[i].errno;
686 printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
687 return nfs_errtbl[i].errno;
691 # define MAX(a, b) (((a) > (b))? (a) : (b))
694 #define PROC(proc, argtype, restype, timer) \
695 [NFSPROC_##proc] = { \
696 .p_proc = NFSPROC_##proc, \
697 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \
698 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \
699 .p_bufsiz = MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
701 .p_statidx = NFSPROC_##proc, \
704 struct rpc_procinfo nfs_procedures[] = {
705 PROC(GETATTR, fhandle, attrstat, 1),
706 PROC(SETATTR, sattrargs, attrstat, 0),
707 PROC(LOOKUP, diropargs, diropres, 2),
708 PROC(READLINK, readlinkargs, readlinkres, 3),
709 PROC(READ, readargs, readres, 3),
710 PROC(WRITE, writeargs, writeres, 4),
711 PROC(CREATE, createargs, diropres, 0),
712 PROC(REMOVE, diropargs, stat, 0),
713 PROC(RENAME, renameargs, stat, 0),
714 PROC(LINK, linkargs, stat, 0),
715 PROC(SYMLINK, symlinkargs, stat, 0),
716 PROC(MKDIR, createargs, diropres, 0),
717 PROC(RMDIR, diropargs, stat, 0),
718 PROC(READDIR, readdirargs, readdirres, 3),
719 PROC(STATFS, fhandle, statfsres, 0),
722 struct rpc_version nfs_version2 = {
724 .nrprocs = ARRAY_SIZE(nfs_procedures),
725 .procs = nfs_procedures