- Linus: drop support for old-style Makefiles entirely. Big.
[davej-history.git] / fs / nfs / nfs2xdr.c
blob7fef7da99b81cefe7ecb7052775577603c2b470a
1 /*
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/sched.h>
14 #include <linux/mm.h>
15 #include <linux/malloc.h>
16 #include <linux/utsname.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
19 #include <linux/in.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 /* Uncomment this to support servers requiring longword lengths */
28 #define NFS_PAD_WRITES 1
30 #define NFSDBG_FACILITY NFSDBG_XDR
31 /* #define NFS_PARANOIA 1 */
33 extern int nfs_stat_to_errno(int stat);
35 /* Mapping from NFS error code to "errno" error code. */
36 #define errno_NFSERR_IO EIO
39 * Declare the space requirements for NFS arguments and replies as
40 * number of 32bit-words
42 #define NFS_fhandle_sz 8
43 #define NFS_sattr_sz 8
44 #define NFS_filename_sz 1+(NFS2_MAXNAMLEN>>2)
45 #define NFS_path_sz 1+(NFS2_MAXPATHLEN>>2)
46 #define NFS_fattr_sz 17
47 #define NFS_info_sz 5
48 #define NFS_entry_sz NFS_filename_sz+3
50 #define NFS_enc_void_sz 0
51 #define NFS_diropargs_sz NFS_fhandle_sz+NFS_filename_sz
52 #define NFS_sattrargs_sz NFS_fhandle_sz+NFS_sattr_sz
53 #define NFS_readlinkargs_sz NFS_fhandle_sz
54 #define NFS_readargs_sz NFS_fhandle_sz+3
55 #define NFS_writeargs_sz NFS_fhandle_sz+4
56 #define NFS_createargs_sz NFS_diropargs_sz+NFS_sattr_sz
57 #define NFS_renameargs_sz NFS_diropargs_sz+NFS_diropargs_sz
58 #define NFS_linkargs_sz NFS_fhandle_sz+NFS_diropargs_sz
59 #define NFS_symlinkargs_sz NFS_diropargs_sz+NFS_path_sz+NFS_sattr_sz
60 #define NFS_readdirargs_sz NFS_fhandle_sz+2
62 #define NFS_dec_void_sz 0
63 #define NFS_attrstat_sz 1+NFS_fattr_sz
64 #define NFS_diropres_sz 1+NFS_fhandle_sz+NFS_fattr_sz
65 #define NFS_readlinkres_sz 1
66 #define NFS_readres_sz 1+NFS_fattr_sz+1
67 #define NFS_writeres_sz NFS_attrstat_sz
68 #define NFS_stat_sz 1
69 #define NFS_readdirres_sz 1
70 #define NFS_statfsres_sz 1+NFS_info_sz
73 * Common NFS XDR functions as inlines
75 static inline u32 *
76 xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
78 memcpy(p, fhandle->data, NFS2_FHSIZE);
79 return p + XDR_QUADLEN(NFS2_FHSIZE);
82 static inline u32 *
83 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
85 /* Zero handle first to allow comparisons */
86 memset(fhandle, 0, sizeof(*fhandle));
87 /* NFSv2 handles have a fixed length */
88 fhandle->size = NFS2_FHSIZE;
89 memcpy(fhandle->data, p, NFS2_FHSIZE);
90 return p + XDR_QUADLEN(NFS2_FHSIZE);
93 static inline u32 *
94 xdr_decode_string2(u32 *p, char **string, unsigned int *len,
95 unsigned int maxlen)
97 *len = ntohl(*p++);
98 if (*len > maxlen)
99 return NULL;
100 *string = (char *) p;
101 return p + XDR_QUADLEN(*len);
104 static inline u32*
105 xdr_decode_time(u32 *p, u64 *timep)
107 u64 tmp = (u64)ntohl(*p++) << 32;
108 *timep = tmp + (u64)ntohl(*p++);
109 return p;
112 static inline u32 *
113 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
115 fattr->type = (enum nfs_ftype) ntohl(*p++);
116 fattr->mode = ntohl(*p++);
117 fattr->nlink = ntohl(*p++);
118 fattr->uid = ntohl(*p++);
119 fattr->gid = ntohl(*p++);
120 fattr->size = ntohl(*p++);
121 fattr->du.nfs2.blocksize = ntohl(*p++);
122 fattr->rdev = ntohl(*p++);
123 fattr->du.nfs2.blocks = ntohl(*p++);
124 fattr->fsid = ntohl(*p++);
125 fattr->fileid = ntohl(*p++);
126 p = xdr_decode_time(p, &fattr->atime);
127 p = xdr_decode_time(p, &fattr->mtime);
128 p = xdr_decode_time(p, &fattr->ctime);
129 fattr->valid |= NFS_ATTR_FATTR;
130 if (fattr->type == NFCHR && fattr->rdev == NFS2_FIFO_DEV) {
131 fattr->type = NFFIFO;
132 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
133 fattr->rdev = 0;
135 return p;
138 #define SATTR(p, attr, flag, field) \
139 *p++ = (attr->ia_valid & flag) ? htonl(attr->field) : ~(u32) 0
140 static inline u32 *
141 xdr_encode_sattr(u32 *p, struct iattr *attr)
143 SATTR(p, attr, ATTR_MODE, ia_mode);
144 SATTR(p, attr, ATTR_UID, ia_uid);
145 SATTR(p, attr, ATTR_GID, ia_gid);
146 SATTR(p, attr, ATTR_SIZE, ia_size);
148 if (attr->ia_valid & (ATTR_ATIME|ATTR_ATIME_SET)) {
149 *p++ = htonl(attr->ia_atime);
150 *p++ = 0;
151 } else {
152 *p++ = ~(u32) 0;
153 *p++ = ~(u32) 0;
156 if (attr->ia_valid & (ATTR_MTIME|ATTR_MTIME_SET)) {
157 *p++ = htonl(attr->ia_mtime);
158 *p++ = 0;
159 } else {
160 *p++ = ~(u32) 0;
161 *p++ = ~(u32) 0;
163 return p;
165 #undef SATTR
168 * NFS encode functions
171 * Encode void argument
173 static int
174 nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
176 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
177 return 0;
181 * Encode file handle argument
182 * GETATTR, READLINK, STATFS
184 static int
185 nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
187 p = xdr_encode_fhandle(p, fh);
188 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
189 return 0;
193 * Encode SETATTR arguments
195 static int
196 nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
198 p = xdr_encode_fhandle(p, args->fh);
199 p = xdr_encode_sattr(p, args->sattr);
200 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
201 return 0;
205 * Encode directory ops argument
206 * LOOKUP, REMOVE, RMDIR
208 static int
209 nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
211 p = xdr_encode_fhandle(p, args->fh);
212 p = xdr_encode_array(p, args->name, args->len);
213 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
214 return 0;
218 * Arguments to a READ call. Since we read data directly into the page
219 * cache, we also set up the reply iovec here so that iov[1] points
220 * exactly to the page we want to fetch.
222 static int
223 nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
225 struct rpc_auth *auth = req->rq_task->tk_auth;
226 int buflen, replen;
227 unsigned int nr;
229 p = xdr_encode_fhandle(p, args->fh);
230 *p++ = htonl(args->offset);
231 *p++ = htonl(args->count);
232 *p++ = htonl(args->count);
233 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
235 /* Get the number of buffers in the receive iovec */
236 nr = args->nriov;
238 if (nr+2 > MAX_IOVEC) {
239 printk(KERN_ERR "NFS: Bad number of iov's in xdr_readargs\n");
240 return -EINVAL;
243 /* set up reply iovec */
244 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
245 buflen = req->rq_rvec[0].iov_len;
246 req->rq_rvec[0].iov_len = replen;
247 /* Copy the iovec */
248 memcpy(req->rq_rvec + 1, args->iov, nr * sizeof(struct iovec));
250 req->rq_rvec[nr+1].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
251 req->rq_rvec[nr+1].iov_len = buflen - replen;
252 req->rq_rlen = args->count + buflen;
253 req->rq_rnr += nr+1;
255 return 0;
259 * Decode READ reply
261 static int
262 nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
264 struct iovec *iov = req->rq_rvec;
265 int status, count, recvd, hdrlen;
267 if ((status = ntohl(*p++)))
268 return -nfs_stat_to_errno(status);
269 p = xdr_decode_fattr(p, res->fattr);
271 count = ntohl(*p++);
272 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
273 recvd = req->rq_rlen - hdrlen;
274 if (p != iov[req->rq_rnr-1].iov_base) {
275 /* Unexpected reply header size. Punt.
276 * XXX: Move iovec contents to align data on page
277 * boundary and adjust RPC header size guess */
278 printk(KERN_WARNING "NFS: Odd RPC header size in read reply: %d\n", hdrlen);
279 return -errno_NFSERR_IO;
281 if (count > recvd) {
282 printk(KERN_WARNING "NFS: server cheating in read reply: "
283 "count %d > recvd %d\n", count, recvd);
284 count = recvd;
287 dprintk("RPC: readres OK count %d\n", count);
288 if (count < res->count) {
289 xdr_zero_iovec(iov+1, req->rq_rnr-2, res->count - count);
290 res->count = count;
291 res->eof = 1; /* Silly NFSv3ism which can't be helped */
292 } else
293 res->eof = 0;
295 return count;
300 * Write arguments. Splice the buffer to be written into the iovec.
302 static int
303 nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
305 unsigned int nr;
306 u32 count = args->count;
308 p = xdr_encode_fhandle(p, args->fh);
309 *p++ = htonl(args->offset);
310 *p++ = htonl(args->offset);
311 *p++ = htonl(count);
312 *p++ = htonl(count);
313 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
315 /* Get the number of buffers in the send iovec */
316 nr = args->nriov;
318 if (nr+2 > MAX_IOVEC) {
319 printk(KERN_ERR "NFS: Bad number of iov's in xdr_writeargs "
320 "(nr %d max %d)\n", nr, MAX_IOVEC);
321 return -EINVAL;
324 /* Copy the iovec */
325 memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec));
327 #ifdef NFS_PAD_WRITES
329 * Some old servers require that the message length
330 * be a multiple of 4, so we pad it here if needed.
332 if (count & 3) {
333 struct iovec *iov = req->rq_svec + nr + 1;
334 int pad = 4 - (count & 3);
336 iov->iov_base = (void *) "\0\0\0";
337 iov->iov_len = pad;
338 count += pad;
339 nr++;
341 #endif
342 req->rq_slen += count;
343 req->rq_snr += nr;
345 return 0;
349 * Encode create arguments
350 * CREATE, MKDIR
352 static int
353 nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
355 p = xdr_encode_fhandle(p, args->fh);
356 p = xdr_encode_array(p, args->name, args->len);
357 p = xdr_encode_sattr(p, args->sattr);
358 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
359 return 0;
363 * Encode RENAME arguments
365 static int
366 nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
368 p = xdr_encode_fhandle(p, args->fromfh);
369 p = xdr_encode_array(p, args->fromname, args->fromlen);
370 p = xdr_encode_fhandle(p, args->tofh);
371 p = xdr_encode_array(p, args->toname, args->tolen);
372 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
373 return 0;
377 * Encode LINK arguments
379 static int
380 nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
382 p = xdr_encode_fhandle(p, args->fromfh);
383 p = xdr_encode_fhandle(p, args->tofh);
384 p = xdr_encode_array(p, args->toname, args->tolen);
385 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
386 return 0;
390 * Encode SYMLINK arguments
392 static int
393 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
395 p = xdr_encode_fhandle(p, args->fromfh);
396 p = xdr_encode_array(p, args->fromname, args->fromlen);
397 p = xdr_encode_array(p, args->topath, args->tolen);
398 p = xdr_encode_sattr(p, args->sattr);
399 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
400 return 0;
404 * Encode arguments to readdir call
406 static int
407 nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
409 struct rpc_task *task = req->rq_task;
410 struct rpc_auth *auth = task->tk_auth;
411 u32 bufsiz = args->bufsiz;
412 int buflen, replen;
415 * Some servers (e.g. HP OS 9.5) seem to expect the buffer size
416 * to be in longwords ... check whether to convert the size.
418 if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE)
419 bufsiz = bufsiz >> 2;
421 p = xdr_encode_fhandle(p, args->fh);
422 *p++ = htonl(args->cookie);
423 *p++ = htonl(bufsiz); /* see above */
424 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
426 /* set up reply iovec */
427 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
428 buflen = req->rq_rvec[0].iov_len;
429 req->rq_rvec[0].iov_len = replen;
430 req->rq_rvec[1].iov_base = args->buffer;
431 req->rq_rvec[1].iov_len = args->bufsiz;
432 req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
433 req->rq_rvec[2].iov_len = buflen - replen;
434 req->rq_rlen = buflen + args->bufsiz;
435 req->rq_rnr += 2;
437 return 0;
441 * Decode the result of a readdir call.
442 * We're not really decoding anymore, we just leave the buffer untouched
443 * and only check that it is syntactically correct.
444 * The real decoding happens in nfs_decode_entry below, called directly
445 * from nfs_readdir for each entry.
447 static int
448 nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res)
450 struct iovec *iov = req->rq_rvec;
451 int status, nr;
452 u32 *end, *entry, len;
454 if ((status = ntohl(*p++)))
455 return -nfs_stat_to_errno(status);
456 if ((void *) p != ((u8 *) iov->iov_base+iov->iov_len)) {
457 /* Unexpected reply header size. Punt. */
458 printk(KERN_WARNING "NFS: Odd RPC header size in readdirres reply\n");
459 return -errno_NFSERR_IO;
462 /* Get start and end address of XDR data */
463 p = (u32 *) iov[1].iov_base;
464 end = (u32 *) ((u8 *) p + iov[1].iov_len);
466 /* Get start and end of dirent buffer */
467 if (res->buffer != p) {
468 printk(KERN_ERR "NFS: Bad result buffer in readdir\n");
469 return -errno_NFSERR_IO;
472 for (nr = 0; *p++; nr++) {
473 entry = p - 1;
474 p++; /* fileid */
475 len = ntohl(*p++);
476 p += XDR_QUADLEN(len) + 1; /* name plus cookie */
477 if (len > NFS2_MAXNAMLEN) {
478 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)!\n",
479 len);
480 return -errno_NFSERR_IO;
482 if (p + 2 > end) {
483 printk(KERN_NOTICE
484 "NFS: short packet in readdir reply!\n");
485 entry[0] = entry[1] = 0;
486 break;
489 return nr;
492 u32 *
493 nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
495 if (!*p++) {
496 if (!*p)
497 return ERR_PTR(-EAGAIN);
498 entry->eof = 1;
499 return ERR_PTR(-EBADCOOKIE);
502 entry->ino = ntohl(*p++);
503 entry->len = ntohl(*p++);
504 entry->name = (const char *) p;
505 p += XDR_QUADLEN(entry->len);
506 entry->prev_cookie = entry->cookie;
507 entry->cookie = ntohl(*p++);
508 entry->eof = !p[0] && p[1];
510 return p;
514 * NFS XDR decode functions
517 * Decode void reply
519 static int
520 nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
522 return 0;
526 * Decode simple status reply
528 static int
529 nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
531 int status;
533 if ((status = ntohl(*p++)) != 0)
534 status = -nfs_stat_to_errno(status);
535 return status;
539 * Decode attrstat reply
540 * GETATTR, SETATTR, WRITE
542 static int
543 nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
545 int status;
547 if ((status = ntohl(*p++)))
548 return -nfs_stat_to_errno(status);
549 xdr_decode_fattr(p, fattr);
550 return 0;
554 * Decode diropres reply
555 * LOOKUP, CREATE, MKDIR
557 static int
558 nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
560 int status;
562 if ((status = ntohl(*p++)))
563 return -nfs_stat_to_errno(status);
564 p = xdr_decode_fhandle(p, res->fh);
565 xdr_decode_fattr(p, res->fattr);
566 return 0;
570 * Encode READLINK args
572 static int
573 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
575 struct rpc_task *task = req->rq_task;
576 struct rpc_auth *auth = task->tk_auth;
577 int buflen, replen;
579 p = xdr_encode_fhandle(p, args->fh);
580 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
581 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
582 buflen = req->rq_rvec[0].iov_len;
583 req->rq_rvec[0].iov_len = replen;
584 req->rq_rvec[1].iov_base = args->buffer;
585 req->rq_rvec[1].iov_len = args->bufsiz;
586 req->rq_rvec[2].iov_base = (u8 *) req->rq_rvec[0].iov_base + replen;
587 req->rq_rvec[2].iov_len = buflen - replen;
588 req->rq_rlen = buflen + args->bufsiz;
589 req->rq_rnr += 2;
590 return 0;
594 * Decode READLINK reply
596 static int
597 nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res)
599 u32 *strlen;
600 char *string;
601 int status;
602 unsigned int len;
604 if ((status = ntohl(*p++)))
605 return -nfs_stat_to_errno(status);
606 strlen = (u32*)res->buffer;
607 /* Convert length of symlink */
608 len = ntohl(*strlen);
609 if (len > res->bufsiz - 5)
610 len = res->bufsiz - 5;
611 *strlen = len;
612 /* NULL terminate the string we got */
613 string = (char *)(strlen + 1);
614 string[len] = 0;
615 return 0;
619 * Decode WRITE reply
621 static int
622 nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
624 res->verf->committed = NFS_FILE_SYNC;
625 return nfs_xdr_attrstat(req, p, res->fattr);
629 * Decode STATFS reply
631 static int
632 nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
634 int status;
635 u32 xfer_size;
637 if ((status = ntohl(*p++)))
638 return -nfs_stat_to_errno(status);
640 /* For NFSv2, we more or less have to guess the preferred
641 * read/write/readdir sizes from the single 'transfer size'
642 * value.
644 xfer_size = ntohl(*p++); /* tsize */
645 res->rtmax = 8 * 1024;
646 res->rtpref = xfer_size;
647 res->rtmult = xfer_size;
648 res->wtmax = 8 * 1024;
649 res->wtpref = xfer_size;
650 res->wtmult = xfer_size;
651 res->dtpref = PAGE_CACHE_SIZE;
652 res->maxfilesize = 0x7FFFFFFF; /* just a guess */
653 res->bsize = ntohl(*p++);
655 res->tbytes = ntohl(*p++) * res->bsize;
656 res->fbytes = ntohl(*p++) * res->bsize;
657 res->abytes = ntohl(*p++) * res->bsize;
658 res->tfiles = 0;
659 res->ffiles = 0;
660 res->afiles = 0;
661 res->namelen = 0;
663 return 0;
667 * We need to translate between nfs status return values and
668 * the local errno values which may not be the same.
670 static struct {
671 int stat;
672 int errno;
673 } nfs_errtbl[] = {
674 { NFS_OK, 0 },
675 { NFSERR_PERM, EPERM },
676 { NFSERR_NOENT, ENOENT },
677 { NFSERR_IO, errno_NFSERR_IO },
678 { NFSERR_NXIO, ENXIO },
679 /* { NFSERR_EAGAIN, EAGAIN }, */
680 { NFSERR_ACCES, EACCES },
681 { NFSERR_EXIST, EEXIST },
682 { NFSERR_XDEV, EXDEV },
683 { NFSERR_NODEV, ENODEV },
684 { NFSERR_NOTDIR, ENOTDIR },
685 { NFSERR_ISDIR, EISDIR },
686 { NFSERR_INVAL, EINVAL },
687 { NFSERR_FBIG, EFBIG },
688 { NFSERR_NOSPC, ENOSPC },
689 { NFSERR_ROFS, EROFS },
690 { NFSERR_MLINK, EMLINK },
691 { NFSERR_NAMETOOLONG, ENAMETOOLONG },
692 { NFSERR_NOTEMPTY, ENOTEMPTY },
693 { NFSERR_DQUOT, EDQUOT },
694 { NFSERR_STALE, ESTALE },
695 { NFSERR_REMOTE, EREMOTE },
696 #ifdef EWFLUSH
697 { NFSERR_WFLUSH, EWFLUSH },
698 #endif
699 { NFSERR_BADHANDLE, EBADHANDLE },
700 { NFSERR_NOT_SYNC, ENOTSYNC },
701 { NFSERR_BAD_COOKIE, EBADCOOKIE },
702 { NFSERR_NOTSUPP, ENOTSUPP },
703 { NFSERR_TOOSMALL, ETOOSMALL },
704 { NFSERR_SERVERFAULT, ESERVERFAULT },
705 { NFSERR_BADTYPE, EBADTYPE },
706 { NFSERR_JUKEBOX, EJUKEBOX },
707 { -1, EIO }
711 * Convert an NFS error code to a local one.
712 * This one is used jointly by NFSv2 and NFSv3.
715 nfs_stat_to_errno(int stat)
717 int i;
719 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
720 if (nfs_errtbl[i].stat == stat)
721 return nfs_errtbl[i].errno;
723 printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
724 return nfs_errtbl[i].errno;
727 #ifndef MAX
728 # define MAX(a, b) (((a) > (b))? (a) : (b))
729 #endif
731 #define PROC(proc, argtype, restype) \
732 { "nfs_" #proc, \
733 (kxdrproc_t) nfs_xdr_##argtype, \
734 (kxdrproc_t) nfs_xdr_##restype, \
735 MAX(NFS_##argtype##_sz,NFS_##restype##_sz) << 2, \
739 static struct rpc_procinfo nfs_procedures[18] = {
740 PROC(null, enc_void, dec_void),
741 PROC(getattr, fhandle, attrstat),
742 PROC(setattr, sattrargs, attrstat),
743 PROC(root, enc_void, dec_void),
744 PROC(lookup, diropargs, diropres),
745 PROC(readlink, readlinkargs, readlinkres),
746 PROC(read, readargs, readres),
747 PROC(writecache, enc_void, dec_void),
748 PROC(write, writeargs, writeres),
749 PROC(create, createargs, diropres),
750 PROC(remove, diropargs, stat),
751 PROC(rename, renameargs, stat),
752 PROC(link, linkargs, stat),
753 PROC(symlink, symlinkargs, stat),
754 PROC(mkdir, createargs, diropres),
755 PROC(rmdir, diropargs, stat),
756 PROC(readdir, readdirargs, readdirres),
757 PROC(statfs, fhandle, statfsres),
760 struct rpc_version nfs_version2 = {
762 sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
763 nfs_procedures