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/errno.h>
17 #include <linux/string.h>
19 #include <linux/pagemap.h>
20 #include <linux/proc_fs.h>
21 #include <linux/sunrpc/clnt.h>
22 #include <linux/nfs.h>
23 #include <linux/nfs2.h>
24 #include <linux/nfs_fs.h>
27 #define NFSDBG_FACILITY NFSDBG_XDR
29 /* Mapping from NFS error code to "errno" error code. */
30 #define errno_NFSERR_IO EIO
33 * Declare the space requirements for NFS arguments and replies as
34 * number of 32bit-words
36 #define NFS_fhandle_sz (8)
37 #define NFS_sattr_sz (8)
38 #define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
39 #define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
40 #define NFS_fattr_sz (17)
41 #define NFS_info_sz (5)
42 #define NFS_entry_sz (NFS_filename_sz+3)
44 #define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
45 #define NFS_removeargs_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+1+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
68 static inline __be32
*
69 xdr_encode_fhandle(__be32
*p
, const struct nfs_fh
*fhandle
)
71 memcpy(p
, fhandle
->data
, NFS2_FHSIZE
);
72 return p
+ XDR_QUADLEN(NFS2_FHSIZE
);
75 static inline __be32
*
76 xdr_decode_fhandle(__be32
*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(__be32
*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(__be32
*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);
110 static inline __be32
*
111 xdr_decode_time(__be32
*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(__be32
*p
, struct nfs_fattr
*fattr
)
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_V2
;
139 fattr
->rdev
= new_decode_dev(rdev
);
140 if (type
== NFCHR
&& rdev
== NFS2_FIFO_DEV
) {
141 fattr
->mode
= (fattr
->mode
& ~S_IFMT
) | S_IFIFO
;
147 static inline __be32
*
148 xdr_encode_sattr(__be32
*p
, struct iattr
*attr
)
150 const __be32 not_set
= __constant_htonl(0xFFFFFFFF);
152 *p
++ = (attr
->ia_valid
& ATTR_MODE
) ? htonl(attr
->ia_mode
) : not_set
;
153 *p
++ = (attr
->ia_valid
& ATTR_UID
) ? htonl(attr
->ia_uid
) : not_set
;
154 *p
++ = (attr
->ia_valid
& ATTR_GID
) ? htonl(attr
->ia_gid
) : not_set
;
155 *p
++ = (attr
->ia_valid
& ATTR_SIZE
) ? htonl(attr
->ia_size
) : not_set
;
157 if (attr
->ia_valid
& ATTR_ATIME_SET
) {
158 p
= xdr_encode_time(p
, &attr
->ia_atime
);
159 } else if (attr
->ia_valid
& ATTR_ATIME
) {
160 p
= xdr_encode_current_server_time(p
, &attr
->ia_atime
);
166 if (attr
->ia_valid
& ATTR_MTIME_SET
) {
167 p
= xdr_encode_time(p
, &attr
->ia_mtime
);
168 } else if (attr
->ia_valid
& ATTR_MTIME
) {
169 p
= xdr_encode_current_server_time(p
, &attr
->ia_mtime
);
178 * NFS encode functions
181 * Encode file handle argument
182 * GETATTR, READLINK, STATFS
185 nfs_xdr_fhandle(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fh
*fh
)
187 p
= xdr_encode_fhandle(p
, fh
);
188 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
193 * Encode SETATTR arguments
196 nfs_xdr_sattrargs(struct rpc_rqst
*req
, __be32
*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
);
205 * Encode directory ops argument
209 nfs_xdr_diropargs(struct rpc_rqst
*req
, __be32
*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
);
218 * Encode REMOVE argument
221 nfs_xdr_removeargs(struct rpc_rqst
*req
, __be32
*p
, const struct nfs_removeargs
*args
)
223 p
= xdr_encode_fhandle(p
, args
->fh
);
224 p
= xdr_encode_array(p
, args
->name
.name
, args
->name
.len
);
225 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
230 * Arguments to a READ call. Since we read data directly into the page
231 * cache, we also set up the reply iovec here so that iov[1] points
232 * exactly to the page we want to fetch.
235 nfs_xdr_readargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readargs
*args
)
237 struct rpc_auth
*auth
= req
->rq_task
->tk_msg
.rpc_cred
->cr_auth
;
239 u32 offset
= (u32
)args
->offset
;
240 u32 count
= args
->count
;
242 p
= xdr_encode_fhandle(p
, args
->fh
);
243 *p
++ = htonl(offset
);
246 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
248 /* Inline the page array */
249 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS_readres_sz
) << 2;
250 xdr_inline_pages(&req
->rq_rcv_buf
, replen
,
251 args
->pages
, args
->pgbase
, count
);
252 req
->rq_rcv_buf
.flags
|= XDRBUF_READ
;
260 nfs_xdr_readres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readres
*res
)
262 struct kvec
*iov
= req
->rq_rcv_buf
.head
;
267 if ((status
= ntohl(*p
++)))
268 return nfs_stat_to_errno(status
);
269 p
= xdr_decode_fattr(p
, res
->fattr
);
273 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
274 if (iov
->iov_len
< hdrlen
) {
275 dprintk("NFS: READ reply header overflowed:"
276 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
277 return -errno_NFSERR_IO
;
278 } else if (iov
->iov_len
!= hdrlen
) {
279 dprintk("NFS: READ header is short. iovec will be shifted.\n");
280 xdr_shift_buf(&req
->rq_rcv_buf
, iov
->iov_len
- hdrlen
);
283 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
285 dprintk("NFS: server cheating in read reply: "
286 "count %u > recvd %u\n", count
, recvd
);
290 dprintk("RPC: readres OK count %u\n", count
);
291 if (count
< res
->count
)
299 * Write arguments. Splice the buffer to be written into the iovec.
302 nfs_xdr_writeargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeargs
*args
)
304 struct xdr_buf
*sndbuf
= &req
->rq_snd_buf
;
305 u32 offset
= (u32
)args
->offset
;
306 u32 count
= args
->count
;
308 p
= xdr_encode_fhandle(p
, args
->fh
);
309 *p
++ = htonl(offset
);
310 *p
++ = htonl(offset
);
313 sndbuf
->len
= xdr_adjust_iovec(sndbuf
->head
, p
);
315 /* Copy the page array */
316 xdr_encode_pages(sndbuf
, args
->pages
, args
->pgbase
, count
);
317 sndbuf
->flags
|= XDRBUF_WRITE
;
322 * Encode create arguments
326 nfs_xdr_createargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_createargs
*args
)
328 p
= xdr_encode_fhandle(p
, args
->fh
);
329 p
= xdr_encode_array(p
, args
->name
, args
->len
);
330 p
= xdr_encode_sattr(p
, args
->sattr
);
331 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
336 * Encode RENAME arguments
339 nfs_xdr_renameargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_renameargs
*args
)
341 p
= xdr_encode_fhandle(p
, args
->fromfh
);
342 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
343 p
= xdr_encode_fhandle(p
, args
->tofh
);
344 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
345 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
350 * Encode LINK arguments
353 nfs_xdr_linkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_linkargs
*args
)
355 p
= xdr_encode_fhandle(p
, args
->fromfh
);
356 p
= xdr_encode_fhandle(p
, args
->tofh
);
357 p
= xdr_encode_array(p
, args
->toname
, args
->tolen
);
358 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
363 * Encode SYMLINK arguments
366 nfs_xdr_symlinkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_symlinkargs
*args
)
368 struct xdr_buf
*sndbuf
= &req
->rq_snd_buf
;
371 p
= xdr_encode_fhandle(p
, args
->fromfh
);
372 p
= xdr_encode_array(p
, args
->fromname
, args
->fromlen
);
373 *p
++ = htonl(args
->pathlen
);
374 sndbuf
->len
= xdr_adjust_iovec(sndbuf
->head
, p
);
376 xdr_encode_pages(sndbuf
, args
->pages
, 0, args
->pathlen
);
379 * xdr_encode_pages may have added a few bytes to ensure the
380 * pathname ends on a 4-byte boundary. Start encoding the
381 * attributes after the pad bytes.
383 pad
= sndbuf
->tail
->iov_len
;
386 p
= xdr_encode_sattr(p
, args
->sattr
);
387 sndbuf
->len
+= xdr_adjust_iovec(sndbuf
->tail
, p
) - pad
;
392 * Encode arguments to readdir call
395 nfs_xdr_readdirargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readdirargs
*args
)
397 struct rpc_task
*task
= req
->rq_task
;
398 struct rpc_auth
*auth
= task
->tk_msg
.rpc_cred
->cr_auth
;
400 u32 count
= args
->count
;
402 p
= xdr_encode_fhandle(p
, args
->fh
);
403 *p
++ = htonl(args
->cookie
);
404 *p
++ = htonl(count
); /* see above */
405 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
407 /* Inline the page array */
408 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS_readdirres_sz
) << 2;
409 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, 0, count
);
414 * Decode the result of a readdir call.
415 * We're not really decoding anymore, we just leave the buffer untouched
416 * and only check that it is syntactically correct.
417 * The real decoding happens in nfs_decode_entry below, called directly
418 * from nfs_readdir for each entry.
421 nfs_xdr_readdirres(struct rpc_rqst
*req
, __be32
*p
, void *dummy
)
423 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
424 struct kvec
*iov
= rcvbuf
->head
;
427 unsigned int pglen
, recvd
;
430 __be32
*end
, *entry
, *kaddr
;
432 if ((status
= ntohl(*p
++)))
433 return nfs_stat_to_errno(status
);
435 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
436 if (iov
->iov_len
< hdrlen
) {
437 dprintk("NFS: READDIR reply header overflowed:"
438 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
439 return -errno_NFSERR_IO
;
440 } else if (iov
->iov_len
!= hdrlen
) {
441 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
442 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
445 pglen
= rcvbuf
->page_len
;
446 recvd
= rcvbuf
->len
- hdrlen
;
449 page
= rcvbuf
->pages
;
450 kaddr
= p
= kmap_atomic(*page
, KM_USER0
);
451 end
= (__be32
*)((char *)p
+ pglen
);
454 /* Make sure the packet actually has a value_follows and EOF entry */
455 if ((entry
+ 1) > end
)
463 p
+= XDR_QUADLEN(len
) + 1; /* name plus cookie */
464 if (len
> NFS2_MAXNAMLEN
) {
465 dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
475 * Apparently some server sends responses that are a valid size, but
476 * contain no entries, and have value_follows==0 and EOF==0. For
477 * those, just set the EOF marker.
479 if (!nr
&& entry
[1] == 0) {
480 dprintk("NFS: readdir reply truncated!\n");
484 kunmap_atomic(kaddr
, KM_USER0
);
488 * When we get a short packet there are 2 possibilities. We can
489 * return an error, or fix up the response to look like a valid
490 * response and return what we have so far. If there are no
491 * entries and the packet was short, then return -EIO. If there
492 * are valid entries in the response, return them and pretend that
493 * the call was successful, but incomplete. The caller can retry the
494 * readdir starting at the last cookie.
496 entry
[0] = entry
[1] = 0;
498 nr
= -errno_NFSERR_IO
;
501 nr
= -errno_NFSERR_IO
;
506 nfs_decode_dirent(__be32
*p
, struct nfs_entry
*entry
, int plus
)
510 return ERR_PTR(-EAGAIN
);
512 return ERR_PTR(-EBADCOOKIE
);
515 entry
->ino
= ntohl(*p
++);
516 entry
->len
= ntohl(*p
++);
517 entry
->name
= (const char *) p
;
518 p
+= XDR_QUADLEN(entry
->len
);
519 entry
->prev_cookie
= entry
->cookie
;
520 entry
->cookie
= ntohl(*p
++);
521 entry
->eof
= !p
[0] && p
[1];
527 * NFS XDR decode functions
530 * Decode simple status reply
533 nfs_xdr_stat(struct rpc_rqst
*req
, __be32
*p
, void *dummy
)
537 if ((status
= ntohl(*p
++)) != 0)
538 status
= nfs_stat_to_errno(status
);
543 * Decode attrstat reply
544 * GETATTR, SETATTR, WRITE
547 nfs_xdr_attrstat(struct rpc_rqst
*req
, __be32
*p
, struct nfs_fattr
*fattr
)
551 if ((status
= ntohl(*p
++)))
552 return nfs_stat_to_errno(status
);
553 xdr_decode_fattr(p
, fattr
);
558 * Decode diropres reply
559 * LOOKUP, CREATE, MKDIR
562 nfs_xdr_diropres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_diropok
*res
)
566 if ((status
= ntohl(*p
++)))
567 return nfs_stat_to_errno(status
);
568 p
= xdr_decode_fhandle(p
, res
->fh
);
569 xdr_decode_fattr(p
, res
->fattr
);
574 * Encode READLINK args
577 nfs_xdr_readlinkargs(struct rpc_rqst
*req
, __be32
*p
, struct nfs_readlinkargs
*args
)
579 struct rpc_auth
*auth
= req
->rq_task
->tk_msg
.rpc_cred
->cr_auth
;
582 p
= xdr_encode_fhandle(p
, args
->fh
);
583 req
->rq_slen
= xdr_adjust_iovec(req
->rq_svec
, p
);
585 /* Inline the page array */
586 replen
= (RPC_REPHDRSIZE
+ auth
->au_rslack
+ NFS_readlinkres_sz
) << 2;
587 xdr_inline_pages(&req
->rq_rcv_buf
, replen
, args
->pages
, args
->pgbase
, args
->pglen
);
592 * Decode READLINK reply
595 nfs_xdr_readlinkres(struct rpc_rqst
*req
, __be32
*p
, void *dummy
)
597 struct xdr_buf
*rcvbuf
= &req
->rq_rcv_buf
;
598 struct kvec
*iov
= rcvbuf
->head
;
604 if ((status
= ntohl(*p
++)))
605 return nfs_stat_to_errno(status
);
606 /* Convert length of symlink */
608 if (len
>= rcvbuf
->page_len
) {
609 dprintk("nfs: server returned giant symlink!\n");
610 return -ENAMETOOLONG
;
612 hdrlen
= (u8
*) p
- (u8
*) iov
->iov_base
;
613 if (iov
->iov_len
< hdrlen
) {
614 dprintk("NFS: READLINK reply header overflowed:"
615 "length %Zu > %Zu\n", hdrlen
, iov
->iov_len
);
616 return -errno_NFSERR_IO
;
617 } else if (iov
->iov_len
!= hdrlen
) {
618 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
619 xdr_shift_buf(rcvbuf
, iov
->iov_len
- hdrlen
);
621 recvd
= req
->rq_rcv_buf
.len
- hdrlen
;
623 dprintk("NFS: server cheating in readlink reply: "
624 "count %u > recvd %u\n", len
, recvd
);
628 /* NULL terminate the string we got */
629 kaddr
= (char *)kmap_atomic(rcvbuf
->pages
[0], KM_USER0
);
630 kaddr
[len
+rcvbuf
->page_base
] = '\0';
631 kunmap_atomic(kaddr
, KM_USER0
);
639 nfs_xdr_writeres(struct rpc_rqst
*req
, __be32
*p
, struct nfs_writeres
*res
)
641 res
->verf
->committed
= NFS_FILE_SYNC
;
642 return nfs_xdr_attrstat(req
, p
, res
->fattr
);
646 * Decode STATFS reply
649 nfs_xdr_statfsres(struct rpc_rqst
*req
, __be32
*p
, struct nfs2_fsstat
*res
)
653 if ((status
= ntohl(*p
++)))
654 return nfs_stat_to_errno(status
);
656 res
->tsize
= ntohl(*p
++);
657 res
->bsize
= ntohl(*p
++);
658 res
->blocks
= ntohl(*p
++);
659 res
->bfree
= ntohl(*p
++);
660 res
->bavail
= ntohl(*p
++);
665 * We need to translate between nfs status return values and
666 * the local errno values which may not be the same.
673 { NFSERR_PERM
, -EPERM
},
674 { NFSERR_NOENT
, -ENOENT
},
675 { NFSERR_IO
, -errno_NFSERR_IO
},
676 { NFSERR_NXIO
, -ENXIO
},
677 /* { NFSERR_EAGAIN, -EAGAIN }, */
678 { NFSERR_ACCES
, -EACCES
},
679 { NFSERR_EXIST
, -EEXIST
},
680 { NFSERR_XDEV
, -EXDEV
},
681 { NFSERR_NODEV
, -ENODEV
},
682 { NFSERR_NOTDIR
, -ENOTDIR
},
683 { NFSERR_ISDIR
, -EISDIR
},
684 { NFSERR_INVAL
, -EINVAL
},
685 { NFSERR_FBIG
, -EFBIG
},
686 { NFSERR_NOSPC
, -ENOSPC
},
687 { NFSERR_ROFS
, -EROFS
},
688 { NFSERR_MLINK
, -EMLINK
},
689 { NFSERR_NAMETOOLONG
, -ENAMETOOLONG
},
690 { NFSERR_NOTEMPTY
, -ENOTEMPTY
},
691 { NFSERR_DQUOT
, -EDQUOT
},
692 { NFSERR_STALE
, -ESTALE
},
693 { NFSERR_REMOTE
, -EREMOTE
},
695 { NFSERR_WFLUSH
, -EWFLUSH
},
697 { NFSERR_BADHANDLE
, -EBADHANDLE
},
698 { NFSERR_NOT_SYNC
, -ENOTSYNC
},
699 { NFSERR_BAD_COOKIE
, -EBADCOOKIE
},
700 { NFSERR_NOTSUPP
, -ENOTSUPP
},
701 { NFSERR_TOOSMALL
, -ETOOSMALL
},
702 { NFSERR_SERVERFAULT
, -ESERVERFAULT
},
703 { NFSERR_BADTYPE
, -EBADTYPE
},
704 { NFSERR_JUKEBOX
, -EJUKEBOX
},
709 * Convert an NFS error code to a local one.
710 * This one is used jointly by NFSv2 and NFSv3.
713 nfs_stat_to_errno(int stat
)
717 for (i
= 0; nfs_errtbl
[i
].stat
!= -1; i
++) {
718 if (nfs_errtbl
[i
].stat
== stat
)
719 return nfs_errtbl
[i
].errno
;
721 dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat
);
722 return nfs_errtbl
[i
].errno
;
725 #define PROC(proc, argtype, restype, timer) \
726 [NFSPROC_##proc] = { \
727 .p_proc = NFSPROC_##proc, \
728 .p_encode = (kxdrproc_t) nfs_xdr_##argtype, \
729 .p_decode = (kxdrproc_t) nfs_xdr_##restype, \
730 .p_arglen = NFS_##argtype##_sz, \
731 .p_replen = NFS_##restype##_sz, \
733 .p_statidx = NFSPROC_##proc, \
736 struct rpc_procinfo nfs_procedures
[] = {
737 PROC(GETATTR
, fhandle
, attrstat
, 1),
738 PROC(SETATTR
, sattrargs
, attrstat
, 0),
739 PROC(LOOKUP
, diropargs
, diropres
, 2),
740 PROC(READLINK
, readlinkargs
, readlinkres
, 3),
741 PROC(READ
, readargs
, readres
, 3),
742 PROC(WRITE
, writeargs
, writeres
, 4),
743 PROC(CREATE
, createargs
, diropres
, 0),
744 PROC(REMOVE
, removeargs
, stat
, 0),
745 PROC(RENAME
, renameargs
, stat
, 0),
746 PROC(LINK
, linkargs
, stat
, 0),
747 PROC(SYMLINK
, symlinkargs
, stat
, 0),
748 PROC(MKDIR
, createargs
, diropres
, 0),
749 PROC(RMDIR
, diropargs
, stat
, 0),
750 PROC(READDIR
, readdirargs
, readdirres
, 3),
751 PROC(STATFS
, fhandle
, statfsres
, 0),
754 struct rpc_version nfs_version2
= {
756 .nrprocs
= ARRAY_SIZE(nfs_procedures
),
757 .procs
= nfs_procedures