1 /*
2 * linux/fs/nfs/nfs2xdr.c
3 *
4 * XDR functions to encode/decode NFS RPC arguments and results.
5 *
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
10 */
11
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>
26
27 /* Uncomment this to support servers requiring longword lengths */
28 #define NFS_PAD_WRITES 1
29
30 #define NFSDBG_FACILITY NFSDBG_XDR
31 /* #define NFS_PARANOIA 1 */
32
33 extern int nfs_stat_to_errno(int stat);
34
35 /* Mapping from NFS error code to "errno" error code. */
36 #define errno_NFSERR_IO EIO
37
38 /*
39 * Declare the space requirements for NFS arguments and replies as
40 * number of 32bit-words
41 */
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
49
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
61
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
71
72 /*
73 * Common NFS XDR functions as inlines
74 */
75 static inline u32 *
76 xdr_encode_fhandle(u32 *p, struct nfs_fh *fhandle)
77 {
78 memcpy(p, fhandle->data, NFS2_FHSIZE);
79 return p + XDR_QUADLEN(NFS2_FHSIZE);
80 }
81
82 static inline u32 *
83 xdr_decode_fhandle(u32 *p, struct nfs_fh *fhandle)
84 {
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);
91 }
92
93 static inline u32 *
94 xdr_decode_string2(u32 *p, char **string, unsigned int *len,
95 unsigned int maxlen)
96 {
97 *len = ntohl(*p++);
98 if (*len > maxlen)
99 return NULL;
100 *string = (char *) p;
101 return p + XDR_QUADLEN(*len);
102 }
103
104 static inline u32*
105 xdr_decode_time(u32 *p, u64 *timep)
106 {
107 u64 tmp = (u64)ntohl(*p++) << 32;
108 *timep = tmp + (u64)ntohl(*p++);
109 return p;
110 }
111
112 static inline u32 *
113 xdr_decode_fattr(u32 *p, struct nfs_fattr *fattr)
114 {
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;
134 }
135 return p;
136 }
137
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)
142 {
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);
147
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;
154 }
155
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;
162 }
163 return p;
164 }
165 #undef SATTR
166
167 /*
168 * NFS encode functions
169 */
170 /*
171 * Encode void argument
172 */
173 static int
174 nfs_xdr_enc_void(struct rpc_rqst *req, u32 *p, void *dummy)
175 {
176 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
177 return 0;
178 }
179
180 /*
181 * Encode file handle argument
182 * GETATTR, READLINK, STATFS
183 */
184 static int
185 nfs_xdr_fhandle(struct rpc_rqst *req, u32 *p, struct nfs_fh *fh)
186 {
187 p = xdr_encode_fhandle(p, fh);
188 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
189 return 0;
190 }
191
192 /*
193 * Encode SETATTR arguments
194 */
195 static int
196 nfs_xdr_sattrargs(struct rpc_rqst *req, u32 *p, struct nfs_sattrargs *args)
197 {
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;
202 }
203
204 /*
205 * Encode directory ops argument
206 * LOOKUP, REMOVE, RMDIR
207 */
208 static int
209 nfs_xdr_diropargs(struct rpc_rqst *req, u32 *p, struct nfs_diropargs *args)
210 {
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;
215 }
216
217 /*
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.
221 */
222 static int
223 nfs_xdr_readargs(struct rpc_rqst *req, u32 *p, struct nfs_readargs *args)
224 {
225 struct rpc_auth *auth = req->rq_task->tk_auth;
226 int buflen, replen;
227 unsigned int nr;
228
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);
234
235 /* Get the number of buffers in the receive iovec */
236 nr = args->nriov;
237
238 if (nr+2 > MAX_IOVEC) {
239 printk(KERN_ERR "NFS: Bad number of iov's in xdr_readargs\n");
240 return -EINVAL;
241 }
242
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));
249
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;
254
255 return 0;
256 }
257
258 /*
259 * Decode READ reply
260 */
261 static int
262 nfs_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
263 {
264 struct iovec *iov = req->rq_rvec;
265 int status, count, recvd, hdrlen;
266
267 if ((status = ntohl(*p++)))
268 return -nfs_stat_to_errno(status);
269 p = xdr_decode_fattr(p, res->fattr);
270
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;
280 }
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;
285 }
286
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;
294
295 return count;
296 }
297
298
299 /*
300 * Write arguments. Splice the buffer to be written into the iovec.
301 */
302 static int
303 nfs_xdr_writeargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
304 {
305 unsigned int nr;
306 u32 count = args->count;
307
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);
314
315 /* Get the number of buffers in the send iovec */
316 nr = args->nriov;
317
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;
322 }
323
324 /* Copy the iovec */
325 memcpy(req->rq_svec + 1, args->iov, nr * sizeof(struct iovec));
326
327 #ifdef NFS_PAD_WRITES
328 /*
329 * Some old servers require that the message length
330 * be a multiple of 4, so we pad it here if needed.
331 */
332 if (count & 3) {
333 struct iovec *iov = req->rq_svec + nr + 1;
334 int pad = 4 - (count & 3);
335
336 iov->iov_base = (void *) "\0\0\0";
337 iov->iov_len = pad;
338 count += pad;
339 nr++;
340 }
341 #endif
342 req->rq_slen += count;
343 req->rq_snr += nr;
344
345 return 0;
346 }
347
348 /*
349 * Encode create arguments
350 * CREATE, MKDIR
351 */
352 static int
353 nfs_xdr_createargs(struct rpc_rqst *req, u32 *p, struct nfs_createargs *args)
354 {
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;
360 }
361
362 /*
363 * Encode RENAME arguments
364 */
365 static int
366 nfs_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs_renameargs *args)
367 {
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;
374 }
375
376 /*
377 * Encode LINK arguments
378 */
379 static int
380 nfs_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs_linkargs *args)
381 {
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;
387 }
388
389 /*
390 * Encode SYMLINK arguments
391 */
392 static int
393 nfs_xdr_symlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_symlinkargs *args)
394 {
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;
401 }
402
403 /*
404 * Encode arguments to readdir call
405 */
406 static int
407 nfs_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs_readdirargs *args)
408 {
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;
413
414 /*
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.
417 */
418 if (task->tk_client->cl_flags & NFS_CLNTF_BUFSIZE)
419 bufsiz = bufsiz >> 2;
420
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);
425
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;
436
437 return 0;
438 }
439
440 /*
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.
446 */
447 static int
448 nfs_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs_readdirres *res)
449 {
450 struct iovec *iov = req->rq_rvec;
451 int status, nr;
452 u32 *end, *entry, len;
453
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;
460 }
461
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);
465
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;
470 }
471
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;
481 }
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;
487 }
488 }
489 return nr;
490 }
491
492 u32 *
493 nfs_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
494 {
495 if (!*p++) {
496 if (!*p)
497 return ERR_PTR(-EAGAIN);
498 entry->eof = 1;
499 return ERR_PTR(-EBADCOOKIE);
500 }
501
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];
509
510 return p;
511 }
512
513 /*
514 * NFS XDR decode functions
515 */
516 /*
517 * Decode void reply
518 */
519 static int
520 nfs_xdr_dec_void(struct rpc_rqst *req, u32 *p, void *dummy)
521 {
522 return 0;
523 }
524
525 /*
526 * Decode simple status reply
527 */
528 static int
529 nfs_xdr_stat(struct rpc_rqst *req, u32 *p, void *dummy)
530 {
531 int status;
532
533 if ((status = ntohl(*p++)) != 0)
534 status = -nfs_stat_to_errno(status);
535 return status;
536 }
537
538 /*
539 * Decode attrstat reply
540 * GETATTR, SETATTR, WRITE
541 */
542 static int
543 nfs_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
544 {
545 int status;
546
547 if ((status = ntohl(*p++)))
548 return -nfs_stat_to_errno(status);
549 xdr_decode_fattr(p, fattr);
550 return 0;
551 }
552
553 /*
554 * Decode diropres reply
555 * LOOKUP, CREATE, MKDIR
556 */
557 static int
558 nfs_xdr_diropres(struct rpc_rqst *req, u32 *p, struct nfs_diropok *res)
559 {
560 int status;
561
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;
567 }
568
569 /*
570 * Encode READLINK args
571 */
572 static int
573 nfs_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs_readlinkargs *args)
574 {
575 struct rpc_task *task = req->rq_task;
576 struct rpc_auth *auth = task->tk_auth;
577 int buflen, replen;
578
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;
591 }
592
593 /*
594 * Decode READLINK reply
595 */
596 static int
597 nfs_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_readlinkres *res)
598 {
599 u32 *strlen;
600 char *string;
601 int status;
602 unsigned int len;
603
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;
616 }
617
618 /*
619 * Decode WRITE reply
620 */
621 static int
622 nfs_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
623 {
624 res->verf->committed = NFS_FILE_SYNC;
625 return nfs_xdr_attrstat(req, p, res->fattr);
626 }
627
628 /*
629 * Decode STATFS reply
630 */
631 static int
632 nfs_xdr_statfsres(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
633 {
634 int status;
635 u32 xfer_size;
636
637 if ((status = ntohl(*p++)))
638 return -nfs_stat_to_errno(status);
639
640 /* For NFSv2, we more or less have to guess the preferred
641 * read/write/readdir sizes from the single 'transfer size'
642 * value.
643 */
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++);
654
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;
662
663 return 0;
664 }
665
666 /*
667 * We need to translate between nfs status return values and
668 * the local errno values which may not be the same.
669 */
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 }
708 };
709
710 /*
711 * Convert an NFS error code to a local one.
712 * This one is used jointly by NFSv2 and NFSv3.
713 */
714 int
715 nfs_stat_to_errno(int stat)
716 {
717 int i;
718
719 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
720 if (nfs_errtbl[i].stat == stat)
721 return nfs_errtbl[i].errno;
722 }
723 printk(KERN_ERR "nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
724 return nfs_errtbl[i].errno;
725 }
726
727 #ifndef MAX
728 # define MAX(a, b) (((a) > (b))? (a) : (b))
729 #endif
730
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, \
736 0 \
737 }
738
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),
758 };
759
760 struct rpc_version nfs_version2 = {
761 2,
762 sizeof(nfs_procedures)/sizeof(nfs_procedures[0]),
763 nfs_procedures
764 };
765
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.