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>
27 #define NFSDBG_FACILITY NFSDBG_XDR
28 /* #define NFS_PARANOIA 1 */
30 /* Mapping from NFS error code to "errno" error code. */
31 #define errno_NFSERR_IO EIO
34 * Declare the space requirements for NFS arguments and replies as
35 * number of 32bit-words
37 #define NFS_fhandle_sz (8)
38 #define NFS_sattr_sz (8)
39 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
40 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
41 #define NFS_fattr_sz (17)
42 #define NFS_info_sz (5)
43 #define NFS_entry_sz (NFS_filename_sz+3)
45 #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
46 #define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
47 #define NFS_readlinkargs_sz (NFS_fhandle_sz)
48 #define NFS_readargs_sz (NFS_fhandle_sz+3)
49 #define NFS_writeargs_sz (NFS_fhandle_sz+4)
50 #define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
51 #define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
52 #define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
53 #define NFS_symlinkargs_sz (NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz)
54 #define NFS_readdirargs_sz (NFS_fhandle_sz+2)
56 #define NFS_attrstat_sz (1+NFS_fattr_sz)
57 #define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
58 #define NFS_readlinkres_sz (2)
59 #define NFS_readres_sz (1+NFS_fattr_sz+1)
60 #define NFS_writeres_sz (NFS_attrstat_sz)
61 #define NFS_stat_sz (1)
62 #define NFS_readdirres_sz (1)
63 #define NFS_statfsres_sz (1+NFS_info_sz)
66 * Common NFS XDR functions as inlines
69 xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
71 memcpy(p, fhandle->data, NFS2_FHSIZE);
72 return p + XDR_QUADLEN(NFS2_FHSIZE);
76 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
78 /* NFSv2 handles have a fixed length */
79 fhandle->size = NFS2_FHSIZE;
80 memcpy(fhandle->data, p, NFS2_FHSIZE);
81 return p + XDR_QUADLEN(NFS2_FHSIZE);
85 xdr_encode_time(u32 *p, struct timespec *timep)
87 *p++ = htonl(timep->tv_sec);
88 /* Convert nanoseconds into microseconds */
89 *p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0);
94 xdr_encode_current_server_time(u32 *p, struct timespec *timep)
97 * Passing the invalid value useconds=1000000 is a
98 * Sun convention for "set to current server time".
99 * It's needed to make permissions checks for the
100 * "touch" program across v2 mounts to Solaris and
101 * Irix boxes work correctly. See description of
102 * sattr in section 6.1 of "NFS Illustrated" by
103 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
105 *p++ = htonl(timep->tv_sec);
106 *p++ = htonl(1000000);
111 xdr_decode_time(u32 *p, struct timespec *timep)
113 timep->tv_sec = ntohl(*p++);
114 /* Convert microseconds into nanoseconds */
115 timep->tv_nsec = ntohl(*p++) * 1000;
120 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
123 fattr->type = (enum nfs_ftype) ntohl(*p++);
124 fattr->mode = ntohl(*p++);
125 fattr->nlink = ntohl(*p++);
126 fattr->uid = ntohl(*p++);
127 fattr->gid = ntohl(*p++);
128 fattr->size = ntohl(*p++);
129 fattr->du.nfs2.blocksize = ntohl(*p++);
131 fattr->du.nfs2.blocks = ntohl(*p++);
132 fattr->fsid.major = ntohl(*p++);
133 fattr->fsid.minor = 0;
134 fattr->fileid = ntohl(*p++);
135 p = xdr_decode_time(p, &fattr->atime);
136 p = xdr_decode_time(p, &fattr->mtime);
137 p = xdr_decode_time(p, &fattr->ctime);
138 fattr->valid |= NFS_ATTR_FATTR;
139 fattr->rdev = new_decode_dev(rdev);
140 if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) {
141 fattr->type = NFFIFO;
142 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
149 xdr_encode_sattr(u32 *p, struct iattr *attr)
151 const u32 not_set = __constant_htonl(0xFFFFFFFF);
153 *p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
154 *p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
155 *p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
156 *p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
158 if (attr->ia_valid & ATTR_ATIME_SET) {
159 p = xdr_encode_time(p, &attr->ia_atime);
160 } else if (attr->ia_valid & ATTR_ATIME) {
161 p = xdr_encode_current_server_time(p, &attr->ia_atime);
167 if (attr->ia_valid & ATTR_MTIME_SET) {
168 p = xdr_encode_time(p, &attr->ia_mtime);
169 } else if (attr->ia_valid & ATTR_MTIME) {
170 p = xdr_encode_current_server_time(p, &attr->ia_mtime);
179 * NFS encode functions
182 * Encode file handle argument
183 * GETATTR, READLINK, STATFS
186 nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
188 p = xdr_encode_fhandle(p, fh);
189 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
194 * Encode SETATTR arguments
197 nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
199 p = xdr_encode_fhandle(p, args->fh);
200 p = xdr_encode_sattr(p, args->sattr);
201 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
206 * Encode directory ops argument
207 * LOOKUP, REMOVE, RMDIR
210 nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
212 p = xdr_encode_fhandle(p, args->fh);
213 p = xdr_encode_array(p, args->name, args->len);
214 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
219 * Arguments to a READ call. Since we read data directly into the page
220 * cache, we also set up the reply iovec here so that iov[1] points
221 * exactly to the page we want to fetch.
224 nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
226 struct rpc_auth *auth = req->rq_task->tk_auth;
228 u32 offset = (u32)args->offset;
229 u32 count = args->count;
231 p = xdr_encode_fhandle(p, args->fh);
232 *p++ = htonl(offset);
235 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
237 /* Inline the page array */
238 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
239 xdr_inline_pages(&req->rq_rcv_buf, replen,
240 args->pages, args->pgbase, count);
248 nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
250 struct kvec *iov = req->rq_rcv_buf.head;
251 int status, count, recvd, hdrlen;
253 if ((status = ntohl(*p++)))
254 return -nfs_stat_to_errno(status);
255 p = xdr_decode_fattr(p, res->fattr);
259 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
260 if (iov->iov_len < hdrlen) {
261 printk(KERN_WARNING "NFS: READ reply header overflowed:"
262 "length %d > %Zu\n", hdrlen, iov->iov_len);
263 return -errno_NFSERR_IO;
264 } else if (iov->iov_len != hdrlen) {
265 dprintk("NFS: READ header is short. iovec will be shifted.\n");
266 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
269 recvd = req->rq_rcv_buf.len - hdrlen;
271 printk(KERN_WARNING "NFS: server cheating in read reply: "
272 "count %d > recvd %d\n", count, recvd);
276 dprintk("RPC: readres OK count %d\n", count);
277 if (count < res->count)
285 * Write arguments. Splice the buffer to be written into the iovec.
288 nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
290 struct xdr_buf *sndbuf = &req->rq_snd_buf;
291 u32 offset = (u32)args->offset;
292 u32 count = args->count;
294 p = xdr_encode_fhandle(p, args->fh);
295 *p++ = htonl(offset);
296 *p++ = htonl(offset);
299 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
301 /* Copy the page array */
302 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
307 * Encode create arguments
311 nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
313 p = xdr_encode_fhandle(p, args->fh);
314 p = xdr_encode_array(p, args->name, args->len);
315 p = xdr_encode_sattr(p, args->sattr);
316 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
321 * Encode RENAME arguments
324 nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
326 p = xdr_encode_fhandle(p, args->fromfh);
327 p = xdr_encode_array(p, args->fromname, args->fromlen);
328 p = xdr_encode_fhandle(p, args->tofh);
329 p = xdr_encode_array(p, args->toname, args->tolen);
330 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
335 * Encode LINK arguments
338 nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
340 p = xdr_encode_fhandle(p, args->fromfh);
341 p = xdr_encode_fhandle(p, args->tofh);
342 p = xdr_encode_array(p, args->toname, args->tolen);
343 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
348 * Encode SYMLINK arguments
351 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
353 p = xdr_encode_fhandle(p, args->fromfh);
354 p = xdr_encode_array(p, args->fromname, args->fromlen);
355 p = xdr_encode_array(p, args->topath, args->tolen);
356 p = xdr_encode_sattr(p, args->sattr);
357 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
362 * Encode arguments to readdir call
365 nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
367 struct rpc_task *task = req->rq_task;
368 struct rpc_auth *auth = task->tk_auth;
370 u32 count = args->count;
372 p = xdr_encode_fhandle(p, args->fh);
373 *p++ = htonl(args->cookie);
374 *p++ = htonl(count); /* see above */
375 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
377 /* Inline the page array */
378 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
379 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
384 * Decode the result of a readdir call.
385 * We're not really decoding anymore, we just leave the buffer untouched
386 * and only check that it is syntactically correct.
387 * The real decoding happens in nfs_decode_entry below, called directly
388 * from nfs_readdir for each entry.
391 nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, void *dummy)
393 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
394 struct kvec *iov = rcvbuf->head;
398 unsigned int len, pglen;
399 u32 *end, *entry, *kaddr;
401 if ((status = ntohl(*p++)))
402 return -nfs_stat_to_errno(status);
404 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
405 if (iov->iov_len < hdrlen) {
406 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
407 "length %d > %Zu\n", hdrlen, iov->iov_len);
408 return -errno_NFSERR_IO;
409 } else if (iov->iov_len != hdrlen) {
410 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
411 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
414 pglen = rcvbuf->page_len;
415 recvd = rcvbuf->len - hdrlen;
418 page = rcvbuf->pages;
419 kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
420 end = (u32 *)((char *)p + pglen);
422 for (nr = 0; *p++; nr++) {
427 p += XDR_QUADLEN(len) + 1; /* name plus cookie */
428 if (len > NFS2_MAXNAMLEN) {
429 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n",
437 if (!nr && (entry[0] != 0 || entry[1] == 0))
440 kunmap_atomic(kaddr, KM_USER0);
443 entry[0] = entry[1] = 0;
444 /* truncate listing ? */
446 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
451 nr = -errno_NFSERR_IO;
456 nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
460 return ERR_PTR(-EAGAIN);
462 return ERR_PTR(-EBADCOOKIE);
465 entry->ino = ntohl(*p++);
466 entry->len = ntohl(*p++);
467 entry->name = (const char *) p;
468 p += XDR_QUADLEN(entry->len);
469 entry->prev_cookie = entry->cookie;
470 entry->cookie = ntohl(*p++);
471 entry->eof = !p[0] && p[1];
477 * NFS XDR decode functions
480 * Decode simple status reply
483 nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
487 if ((status = ntohl(*p++)) != 0)
488 status = -nfs_stat_to_errno(status);
493 * Decode attrstat reply
494 * GETATTR, SETATTR, WRITE
497 nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
501 if ((status = ntohl(*p++)))
502 return -nfs_stat_to_errno(status);
503 xdr_decode_fattr(p, fattr);
508 * Decode diropres reply
509 * LOOKUP, CREATE, MKDIR
512 nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
516 if ((status = ntohl(*p++)))
517 return -nfs_stat_to_errno(status);
518 p = xdr_decode_fhandle(p, res->fh);
519 xdr_decode_fattr(p, res->fattr);
524 * Encode READLINK args
527 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
529 struct rpc_auth *auth = req->rq_task->tk_auth;
532 p = xdr_encode_fhandle(p, args->fh);
533 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
535 /* Inline the page array */
536 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
537 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
542 * Decode READLINK reply
545 nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, void *dummy)
547 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
548 struct kvec *iov = rcvbuf->head;
549 int hdrlen, len, recvd;
553 if ((status = ntohl(*p++)))
554 return -nfs_stat_to_errno(status);
555 /* Convert length of symlink */
557 if (len >= rcvbuf->page_len || len <= 0) {
558 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
559 return -ENAMETOOLONG;
561 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
562 if (iov->iov_len < hdrlen) {
563 printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
564 "length %d > %Zu\n", hdrlen, iov->iov_len);
565 return -errno_NFSERR_IO;
566 } else if (iov->iov_len != hdrlen) {
567 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
568 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
570 recvd = req->rq_rcv_buf.len - hdrlen;
572 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
573 "count %u > recvd %u\n", len, recvd);
577 /* NULL terminate the string we got */
578 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
579 kaddr[len+rcvbuf->page_base] = '\0';
580 kunmap_atomic(kaddr, KM_USER0);
588 nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
590 res->verf->committed = NFS_FILE_SYNC;
591 return nfs_xdr_attrstat(req, p, res->fattr);
595 * Decode STATFS reply
598 nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs2_fsstat *res)
602 if ((status = ntohl(*p++)))
603 return -nfs_stat_to_errno(status);
605 res->tsize = ntohl(*p++);
606 res->bsize = ntohl(*p++);
607 res->blocks = ntohl(*p++);
608 res->bfree = ntohl(*p++);
609 res->bavail = ntohl(*p++);
614 * We need to translate between nfs status return values and
615 * the local errno values which may not be the same.
622 { NFSERR_PERM, EPERM },
623 { NFSERR_NOENT, ENOENT },
624 { NFSERR_IO, errno_NFSERR_IO },
625 { NFSERR_NXIO, ENXIO },
626 /* { NFSERR_EAGAIN, EAGAIN }, */
627 { NFSERR_ACCES, EACCES },
628 { NFSERR_EXIST, EEXIST },
629 { NFSERR_XDEV, EXDEV },
630 { NFSERR_NODEV, ENODEV },
631 { NFSERR_NOTDIR, ENOTDIR },
632 { NFSERR_ISDIR, EISDIR },
633 { NFSERR_INVAL, EINVAL },
634 { NFSERR_FBIG, EFBIG },
635 { NFSERR_NOSPC, ENOSPC },
636 { NFSERR_ROFS, EROFS },
637 { NFSERR_MLINK, EMLINK },
638 { NFSERR_NAMETOOLONG, ENAMETOOLONG },
639 { NFSERR_NOTEMPTY, ENOTEMPTY },
640 { NFSERR_DQUOT, EDQUOT },
641 { NFSERR_STALE, ESTALE },
642 { NFSERR_REMOTE, EREMOTE },
644 { NFSERR_WFLUSH, EWFLUSH },
646 { NFSERR_BADHANDLE, EBADHANDLE },
647 { NFSERR_NOT_SYNC, ENOTSYNC },
648 { NFSERR_BAD_COOKIE, EBADCOOKIE },
649 { NFSERR_NOTSUPP, ENOTSUPP },
650 { NFSERR_TOOSMALL, ETOOSMALL },
651 { NFSERR_SERVERFAULT, ESERVERFAULT },
652 { NFSERR_BADTYPE, EBADTYPE },
653 { NFSERR_JUKEBOX, EJUKEBOX },
658 * Convert an NFS error code to a local one.
659 * This one is used jointly by NFSv2 and NFSv3.
662 nfs_stat_to_errno(int stat)
666 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
667 if (nfs_errtbl[i].stat == stat)
668 return nfs_errtbl[i].errno;
670 printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
671 return nfs_errtbl[i].errno;
675 # define MAX(a, b) (((a) > (b))? (a) : (b))
678 #define PROC(proc, argtype, restype, timer) \
679 [NFSPROC_##proc] = { \
680 .p_proc = NFSPROC_##proc, \
681 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \
682 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \
683 .p_bufsiz = MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
685 .p_statidx = NFSPROC_##proc, \
688 struct rpc_procinfo nfs_procedures[] = {
689 PROC(GETATTR, fhandle, attrstat, 1),
690 PROC(SETATTR, sattrargs, attrstat, 0),
691 PROC(LOOKUP, diropargs, diropres, 2),
692 PROC(READLINK, readlinkargs, readlinkres, 3),
693 PROC(READ, readargs, readres, 3),
694 PROC(WRITE, writeargs, writeres, 4),
695 PROC(CREATE, createargs, diropres, 0),
696 PROC(REMOVE, diropargs, stat, 0),
697 PROC(RENAME, renameargs, stat, 0),
698 PROC(LINK, linkargs, stat, 0),
699 PROC(SYMLINK, symlinkargs, stat, 0),
700 PROC(MKDIR, createargs, diropres, 0),
701 PROC(RMDIR, diropargs, stat, 0),
702 PROC(READDIR, readdirargs, readdirres, 3),
703 PROC(STATFS, fhandle, statfsres, 0),
706 struct rpc_version nfs_version2 = {
708 .nrprocs = ARRAY_SIZE(nfs_procedures),
709 .procs = nfs_procedures