]> Pileus Git - ~andy/linux/blob - fs/nfs/nfs3xdr.c
NFS: Convert printk's to dprintk's in fs/nfs/nfs?xdr.c
[~andy/linux] / fs / nfs / nfs3xdr.c
1 /*
2  * linux/fs/nfs/nfs3xdr.c
3  *
4  * XDR functions to encode/decode NFSv3 RPC arguments and results.
5  *
6  * Copyright (C) 1996, 1997 Olaf Kirch
7  */
8
9 #include <linux/param.h>
10 #include <linux/time.h>
11 #include <linux/mm.h>
12 #include <linux/slab.h>
13 #include <linux/utsname.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/in.h>
17 #include <linux/pagemap.h>
18 #include <linux/proc_fs.h>
19 #include <linux/kdev_t.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs3.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/nfsacl.h>
25 #include "internal.h"
26
27 #define NFSDBG_FACILITY         NFSDBG_XDR
28
29 /* Mapping from NFS error code to "errno" error code. */
30 #define errno_NFSERR_IO         EIO
31
32 /*
33  * Declare the space requirements for NFS arguments and replies as
34  * number of 32bit-words
35  */
36 #define NFS3_fhandle_sz         (1+16)
37 #define NFS3_fh_sz              (NFS3_fhandle_sz)       /* shorthand */
38 #define NFS3_sattr_sz           (15)
39 #define NFS3_filename_sz        (1+(NFS3_MAXNAMLEN>>2))
40 #define NFS3_path_sz            (1+(NFS3_MAXPATHLEN>>2))
41 #define NFS3_fattr_sz           (21)
42 #define NFS3_wcc_attr_sz                (6)
43 #define NFS3_pre_op_attr_sz     (1+NFS3_wcc_attr_sz)
44 #define NFS3_post_op_attr_sz    (1+NFS3_fattr_sz)
45 #define NFS3_wcc_data_sz                (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
46 #define NFS3_fsstat_sz          
47 #define NFS3_fsinfo_sz          
48 #define NFS3_pathconf_sz                
49 #define NFS3_entry_sz           (NFS3_filename_sz+3)
50
51 #define NFS3_sattrargs_sz       (NFS3_fh_sz+NFS3_sattr_sz+3)
52 #define NFS3_diropargs_sz       (NFS3_fh_sz+NFS3_filename_sz)
53 #define NFS3_removeargs_sz      (NFS3_fh_sz+NFS3_filename_sz)
54 #define NFS3_accessargs_sz      (NFS3_fh_sz+1)
55 #define NFS3_readlinkargs_sz    (NFS3_fh_sz)
56 #define NFS3_readargs_sz        (NFS3_fh_sz+3)
57 #define NFS3_writeargs_sz       (NFS3_fh_sz+5)
58 #define NFS3_createargs_sz      (NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_mkdirargs_sz       (NFS3_diropargs_sz+NFS3_sattr_sz)
60 #define NFS3_symlinkargs_sz     (NFS3_diropargs_sz+1+NFS3_sattr_sz)
61 #define NFS3_mknodargs_sz       (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62 #define NFS3_renameargs_sz      (NFS3_diropargs_sz+NFS3_diropargs_sz)
63 #define NFS3_linkargs_sz                (NFS3_fh_sz+NFS3_diropargs_sz)
64 #define NFS3_readdirargs_sz     (NFS3_fh_sz+2)
65 #define NFS3_commitargs_sz      (NFS3_fh_sz+3)
66
67 #define NFS3_attrstat_sz        (1+NFS3_fattr_sz)
68 #define NFS3_wccstat_sz         (1+NFS3_wcc_data_sz)
69 #define NFS3_removeres_sz       (NFS3_wccstat_sz)
70 #define NFS3_lookupres_sz       (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
71 #define NFS3_accessres_sz       (1+NFS3_post_op_attr_sz+1)
72 #define NFS3_readlinkres_sz     (1+NFS3_post_op_attr_sz+1)
73 #define NFS3_readres_sz         (1+NFS3_post_op_attr_sz+3)
74 #define NFS3_writeres_sz        (1+NFS3_wcc_data_sz+4)
75 #define NFS3_createres_sz       (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76 #define NFS3_renameres_sz       (1+(2 * NFS3_wcc_data_sz))
77 #define NFS3_linkres_sz         (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78 #define NFS3_readdirres_sz      (1+NFS3_post_op_attr_sz+2)
79 #define NFS3_fsstatres_sz       (1+NFS3_post_op_attr_sz+13)
80 #define NFS3_fsinfores_sz       (1+NFS3_post_op_attr_sz+12)
81 #define NFS3_pathconfres_sz     (1+NFS3_post_op_attr_sz+6)
82 #define NFS3_commitres_sz       (1+NFS3_wcc_data_sz+2)
83
84 #define ACL3_getaclargs_sz      (NFS3_fh_sz+1)
85 #define ACL3_setaclargs_sz      (NFS3_fh_sz+1+2*(2+5*3))
86 #define ACL3_getaclres_sz       (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
87 #define ACL3_setaclres_sz       (1+NFS3_post_op_attr_sz)
88
89 /*
90  * Map file type to S_IFMT bits
91  */
92 static struct {
93         unsigned int    mode;
94         unsigned int    nfs2type;
95 } nfs_type2fmt[] = {
96       { 0,              NFNON   },
97       { S_IFREG,        NFREG   },
98       { S_IFDIR,        NFDIR   },
99       { S_IFBLK,        NFBLK   },
100       { S_IFCHR,        NFCHR   },
101       { S_IFLNK,        NFLNK   },
102       { S_IFSOCK,       NFSOCK  },
103       { S_IFIFO,        NFFIFO  },
104       { 0,              NFBAD   }
105 };
106
107 /*
108  * Common NFS XDR functions as inlines
109  */
110 static inline __be32 *
111 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
112 {
113         return xdr_encode_array(p, fh->data, fh->size);
114 }
115
116 static inline __be32 *
117 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
118 {
119         if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
120                 memcpy(fh->data, p, fh->size);
121                 return p + XDR_QUADLEN(fh->size);
122         }
123         return NULL;
124 }
125
126 /*
127  * Encode/decode time.
128  */
129 static inline __be32 *
130 xdr_encode_time3(__be32 *p, struct timespec *timep)
131 {
132         *p++ = htonl(timep->tv_sec);
133         *p++ = htonl(timep->tv_nsec);
134         return p;
135 }
136
137 static inline __be32 *
138 xdr_decode_time3(__be32 *p, struct timespec *timep)
139 {
140         timep->tv_sec = ntohl(*p++);
141         timep->tv_nsec = ntohl(*p++);
142         return p;
143 }
144
145 static __be32 *
146 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
147 {
148         unsigned int    type, major, minor;
149         int             fmode;
150
151         type = ntohl(*p++);
152         if (type >= NF3BAD)
153                 type = NF3BAD;
154         fmode = nfs_type2fmt[type].mode;
155         fattr->type = nfs_type2fmt[type].nfs2type;
156         fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
157         fattr->nlink = ntohl(*p++);
158         fattr->uid = ntohl(*p++);
159         fattr->gid = ntohl(*p++);
160         p = xdr_decode_hyper(p, &fattr->size);
161         p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
162
163         /* Turn remote device info into Linux-specific dev_t */
164         major = ntohl(*p++);
165         minor = ntohl(*p++);
166         fattr->rdev = MKDEV(major, minor);
167         if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
168                 fattr->rdev = 0;
169
170         p = xdr_decode_hyper(p, &fattr->fsid.major);
171         fattr->fsid.minor = 0;
172         p = xdr_decode_hyper(p, &fattr->fileid);
173         p = xdr_decode_time3(p, &fattr->atime);
174         p = xdr_decode_time3(p, &fattr->mtime);
175         p = xdr_decode_time3(p, &fattr->ctime);
176
177         /* Update the mode bits */
178         fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
179         return p;
180 }
181
182 static inline __be32 *
183 xdr_encode_sattr(__be32 *p, struct iattr *attr)
184 {
185         if (attr->ia_valid & ATTR_MODE) {
186                 *p++ = xdr_one;
187                 *p++ = htonl(attr->ia_mode & S_IALLUGO);
188         } else {
189                 *p++ = xdr_zero;
190         }
191         if (attr->ia_valid & ATTR_UID) {
192                 *p++ = xdr_one;
193                 *p++ = htonl(attr->ia_uid);
194         } else {
195                 *p++ = xdr_zero;
196         }
197         if (attr->ia_valid & ATTR_GID) {
198                 *p++ = xdr_one;
199                 *p++ = htonl(attr->ia_gid);
200         } else {
201                 *p++ = xdr_zero;
202         }
203         if (attr->ia_valid & ATTR_SIZE) {
204                 *p++ = xdr_one;
205                 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
206         } else {
207                 *p++ = xdr_zero;
208         }
209         if (attr->ia_valid & ATTR_ATIME_SET) {
210                 *p++ = xdr_two;
211                 p = xdr_encode_time3(p, &attr->ia_atime);
212         } else if (attr->ia_valid & ATTR_ATIME) {
213                 *p++ = xdr_one;
214         } else {
215                 *p++ = xdr_zero;
216         }
217         if (attr->ia_valid & ATTR_MTIME_SET) {
218                 *p++ = xdr_two;
219                 p = xdr_encode_time3(p, &attr->ia_mtime);
220         } else if (attr->ia_valid & ATTR_MTIME) {
221                 *p++ = xdr_one;
222         } else {
223                 *p++ = xdr_zero;
224         }
225         return p;
226 }
227
228 static inline __be32 *
229 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
230 {
231         p = xdr_decode_hyper(p, &fattr->pre_size);
232         p = xdr_decode_time3(p, &fattr->pre_mtime);
233         p = xdr_decode_time3(p, &fattr->pre_ctime);
234         fattr->valid |= NFS_ATTR_WCC;
235         return p;
236 }
237
238 static inline __be32 *
239 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
240 {
241         if (*p++)
242                 p = xdr_decode_fattr(p, fattr);
243         return p;
244 }
245
246 static inline __be32 *
247 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
248 {
249         if (*p++)
250                 return xdr_decode_wcc_attr(p, fattr);
251         return p;
252 }
253
254
255 static inline __be32 *
256 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
257 {
258         p = xdr_decode_pre_op_attr(p, fattr);
259         return xdr_decode_post_op_attr(p, fattr);
260 }
261
262 /*
263  * NFS encode functions
264  */
265
266 /*
267  * Encode file handle argument
268  */
269 static int
270 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
271 {
272         p = xdr_encode_fhandle(p, fh);
273         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
274         return 0;
275 }
276
277 /*
278  * Encode SETATTR arguments
279  */
280 static int
281 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
282 {
283         p = xdr_encode_fhandle(p, args->fh);
284         p = xdr_encode_sattr(p, args->sattr);
285         *p++ = htonl(args->guard);
286         if (args->guard)
287                 p = xdr_encode_time3(p, &args->guardtime);
288         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
289         return 0;
290 }
291
292 /*
293  * Encode directory ops argument
294  */
295 static int
296 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
297 {
298         p = xdr_encode_fhandle(p, args->fh);
299         p = xdr_encode_array(p, args->name, args->len);
300         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
301         return 0;
302 }
303
304 /*
305  * Encode REMOVE argument
306  */
307 static int
308 nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
309 {
310         p = xdr_encode_fhandle(p, args->fh);
311         p = xdr_encode_array(p, args->name.name, args->name.len);
312         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
313         return 0;
314 }
315
316 /*
317  * Encode access() argument
318  */
319 static int
320 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
321 {
322         p = xdr_encode_fhandle(p, args->fh);
323         *p++ = htonl(args->access);
324         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
325         return 0;
326 }
327
328 /*
329  * Arguments to a READ call. Since we read data directly into the page
330  * cache, we also set up the reply iovec here so that iov[1] points
331  * exactly to the page we want to fetch.
332  */
333 static int
334 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
335 {
336         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
337         unsigned int replen;
338         u32 count = args->count;
339
340         p = xdr_encode_fhandle(p, args->fh);
341         p = xdr_encode_hyper(p, args->offset);
342         *p++ = htonl(count);
343         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
344
345         /* Inline the page array */
346         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
347         xdr_inline_pages(&req->rq_rcv_buf, replen,
348                          args->pages, args->pgbase, count);
349         return 0;
350 }
351
352 /*
353  * Write arguments. Splice the buffer to be written into the iovec.
354  */
355 static int
356 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
357 {
358         struct xdr_buf *sndbuf = &req->rq_snd_buf;
359         u32 count = args->count;
360
361         p = xdr_encode_fhandle(p, args->fh);
362         p = xdr_encode_hyper(p, args->offset);
363         *p++ = htonl(count);
364         *p++ = htonl(args->stable);
365         *p++ = htonl(count);
366         sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
367
368         /* Copy the page array */
369         xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
370         return 0;
371 }
372
373 /*
374  * Encode CREATE arguments
375  */
376 static int
377 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
378 {
379         p = xdr_encode_fhandle(p, args->fh);
380         p = xdr_encode_array(p, args->name, args->len);
381
382         *p++ = htonl(args->createmode);
383         if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
384                 *p++ = args->verifier[0];
385                 *p++ = args->verifier[1];
386         } else
387                 p = xdr_encode_sattr(p, args->sattr);
388
389         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
390         return 0;
391 }
392
393 /*
394  * Encode MKDIR arguments
395  */
396 static int
397 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
398 {
399         p = xdr_encode_fhandle(p, args->fh);
400         p = xdr_encode_array(p, args->name, args->len);
401         p = xdr_encode_sattr(p, args->sattr);
402         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
403         return 0;
404 }
405
406 /*
407  * Encode SYMLINK arguments
408  */
409 static int
410 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
411 {
412         p = xdr_encode_fhandle(p, args->fromfh);
413         p = xdr_encode_array(p, args->fromname, args->fromlen);
414         p = xdr_encode_sattr(p, args->sattr);
415         *p++ = htonl(args->pathlen);
416         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
417
418         /* Copy the page */
419         xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
420         return 0;
421 }
422
423 /*
424  * Encode MKNOD arguments
425  */
426 static int
427 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
428 {
429         p = xdr_encode_fhandle(p, args->fh);
430         p = xdr_encode_array(p, args->name, args->len);
431         *p++ = htonl(args->type);
432         p = xdr_encode_sattr(p, args->sattr);
433         if (args->type == NF3CHR || args->type == NF3BLK) {
434                 *p++ = htonl(MAJOR(args->rdev));
435                 *p++ = htonl(MINOR(args->rdev));
436         }
437
438         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
439         return 0;
440 }
441
442 /*
443  * Encode RENAME arguments
444  */
445 static int
446 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
447 {
448         p = xdr_encode_fhandle(p, args->fromfh);
449         p = xdr_encode_array(p, args->fromname, args->fromlen);
450         p = xdr_encode_fhandle(p, args->tofh);
451         p = xdr_encode_array(p, args->toname, args->tolen);
452         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
453         return 0;
454 }
455
456 /*
457  * Encode LINK arguments
458  */
459 static int
460 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
461 {
462         p = xdr_encode_fhandle(p, args->fromfh);
463         p = xdr_encode_fhandle(p, args->tofh);
464         p = xdr_encode_array(p, args->toname, args->tolen);
465         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
466         return 0;
467 }
468
469 /*
470  * Encode arguments to readdir call
471  */
472 static int
473 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
474 {
475         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
476         unsigned int replen;
477         u32 count = args->count;
478
479         p = xdr_encode_fhandle(p, args->fh);
480         p = xdr_encode_hyper(p, args->cookie);
481         *p++ = args->verf[0];
482         *p++ = args->verf[1];
483         if (args->plus) {
484                 /* readdirplus: need dircount + buffer size.
485                  * We just make sure we make dircount big enough */
486                 *p++ = htonl(count >> 3);
487         }
488         *p++ = htonl(count);
489         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
490
491         /* Inline the page array */
492         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
493         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
494         return 0;
495 }
496
497 /*
498  * Decode the result of a readdir call.
499  * We just check for syntactical correctness.
500  */
501 static int
502 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
503 {
504         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
505         struct kvec *iov = rcvbuf->head;
506         struct page **page;
507         int hdrlen, recvd;
508         int status, nr;
509         unsigned int len, pglen;
510         __be32 *entry, *end, *kaddr;
511
512         status = ntohl(*p++);
513         /* Decode post_op_attrs */
514         p = xdr_decode_post_op_attr(p, res->dir_attr);
515         if (status)
516                 return -nfs_stat_to_errno(status);
517         /* Decode verifier cookie */
518         if (res->verf) {
519                 res->verf[0] = *p++;
520                 res->verf[1] = *p++;
521         } else {
522                 p += 2;
523         }
524
525         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
526         if (iov->iov_len < hdrlen) {
527                 dprintk("NFS: READDIR reply header overflowed:"
528                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
529                 return -errno_NFSERR_IO;
530         } else if (iov->iov_len != hdrlen) {
531                 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
532                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
533         }
534
535         pglen = rcvbuf->page_len;
536         recvd = rcvbuf->len - hdrlen;
537         if (pglen > recvd)
538                 pglen = recvd;
539         page = rcvbuf->pages;
540         kaddr = p = kmap_atomic(*page, KM_USER0);
541         end = (__be32 *)((char *)p + pglen);
542         entry = p;
543         for (nr = 0; *p++; nr++) {
544                 if (p + 3 > end)
545                         goto short_pkt;
546                 p += 2;                         /* inode # */
547                 len = ntohl(*p++);              /* string length */
548                 p += XDR_QUADLEN(len) + 2;      /* name + cookie */
549                 if (len > NFS3_MAXNAMLEN) {
550                         dprintk("NFS: giant filename in readdir (len %x)!\n",
551                                                 len);
552                         goto err_unmap;
553                 }
554
555                 if (res->plus) {
556                         /* post_op_attr */
557                         if (p + 2 > end)
558                                 goto short_pkt;
559                         if (*p++) {
560                                 p += 21;
561                                 if (p + 1 > end)
562                                         goto short_pkt;
563                         }
564                         /* post_op_fh3 */
565                         if (*p++) {
566                                 if (p + 1 > end)
567                                         goto short_pkt;
568                                 len = ntohl(*p++);
569                                 if (len > NFS3_FHSIZE) {
570                                         dprintk("NFS: giant filehandle in "
571                                                 "readdir (len %x)!\n", len);
572                                         goto err_unmap;
573                                 }
574                                 p += XDR_QUADLEN(len);
575                         }
576                 }
577
578                 if (p + 2 > end)
579                         goto short_pkt;
580                 entry = p;
581         }
582         if (!nr && (entry[0] != 0 || entry[1] == 0))
583                 goto short_pkt;
584  out:
585         kunmap_atomic(kaddr, KM_USER0);
586         return nr;
587  short_pkt:
588         entry[0] = entry[1] = 0;
589         /* truncate listing ? */
590         if (!nr) {
591                 dprintk("NFS: readdir reply truncated!\n");
592                 entry[1] = 1;
593         }
594         goto out;
595 err_unmap:
596         nr = -errno_NFSERR_IO;
597         goto out;
598 }
599
600 __be32 *
601 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
602 {
603         struct nfs_entry old = *entry;
604
605         if (!*p++) {
606                 if (!*p)
607                         return ERR_PTR(-EAGAIN);
608                 entry->eof = 1;
609                 return ERR_PTR(-EBADCOOKIE);
610         }
611
612         p = xdr_decode_hyper(p, &entry->ino);
613         entry->len  = ntohl(*p++);
614         entry->name = (const char *) p;
615         p += XDR_QUADLEN(entry->len);
616         entry->prev_cookie = entry->cookie;
617         p = xdr_decode_hyper(p, &entry->cookie);
618
619         if (plus) {
620                 entry->fattr->valid = 0;
621                 p = xdr_decode_post_op_attr(p, entry->fattr);
622                 /* In fact, a post_op_fh3: */
623                 if (*p++) {
624                         p = xdr_decode_fhandle(p, entry->fh);
625                         /* Ugh -- server reply was truncated */
626                         if (p == NULL) {
627                                 dprintk("NFS: FH truncated\n");
628                                 *entry = old;
629                                 return ERR_PTR(-EAGAIN);
630                         }
631                 } else
632                         memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
633         }
634
635         entry->eof = !p[0] && p[1];
636         return p;
637 }
638
639 /*
640  * Encode COMMIT arguments
641  */
642 static int
643 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
644 {
645         p = xdr_encode_fhandle(p, args->fh);
646         p = xdr_encode_hyper(p, args->offset);
647         *p++ = htonl(args->count);
648         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
649         return 0;
650 }
651
652 #ifdef CONFIG_NFS_V3_ACL
653 /*
654  * Encode GETACL arguments
655  */
656 static int
657 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
658                     struct nfs3_getaclargs *args)
659 {
660         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
661         unsigned int replen;
662
663         p = xdr_encode_fhandle(p, args->fh);
664         *p++ = htonl(args->mask);
665         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
666
667         if (args->mask & (NFS_ACL | NFS_DFACL)) {
668                 /* Inline the page array */
669                 replen = (RPC_REPHDRSIZE + auth->au_rslack +
670                           ACL3_getaclres_sz) << 2;
671                 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
672                                  NFSACL_MAXPAGES << PAGE_SHIFT);
673         }
674         return 0;
675 }
676
677 /*
678  * Encode SETACL arguments
679  */
680 static int
681 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
682                    struct nfs3_setaclargs *args)
683 {
684         struct xdr_buf *buf = &req->rq_snd_buf;
685         unsigned int base, len_in_head, len = nfsacl_size(
686                 (args->mask & NFS_ACL)   ? args->acl_access  : NULL,
687                 (args->mask & NFS_DFACL) ? args->acl_default : NULL);
688         int count, err;
689
690         p = xdr_encode_fhandle(p, NFS_FH(args->inode));
691         *p++ = htonl(args->mask);
692         base = (char *)p - (char *)buf->head->iov_base;
693         /* put as much of the acls into head as possible. */
694         len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
695         len -= len_in_head;
696         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
697
698         for (count = 0; (count << PAGE_SHIFT) < len; count++) {
699                 args->pages[count] = alloc_page(GFP_KERNEL);
700                 if (!args->pages[count]) {
701                         while (count)
702                                 __free_page(args->pages[--count]);
703                         return -ENOMEM;
704                 }
705         }
706         xdr_encode_pages(buf, args->pages, 0, len);
707
708         err = nfsacl_encode(buf, base, args->inode,
709                             (args->mask & NFS_ACL) ?
710                             args->acl_access : NULL, 1, 0);
711         if (err > 0)
712                 err = nfsacl_encode(buf, base + err, args->inode,
713                                     (args->mask & NFS_DFACL) ?
714                                     args->acl_default : NULL, 1,
715                                     NFS_ACL_DEFAULT);
716         return (err > 0) ? 0 : err;
717 }
718 #endif  /* CONFIG_NFS_V3_ACL */
719
720 /*
721  * NFS XDR decode functions
722  */
723
724 /*
725  * Decode attrstat reply.
726  */
727 static int
728 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
729 {
730         int     status;
731
732         if ((status = ntohl(*p++)))
733                 return -nfs_stat_to_errno(status);
734         xdr_decode_fattr(p, fattr);
735         return 0;
736 }
737
738 /*
739  * Decode status+wcc_data reply
740  * SATTR, REMOVE, RMDIR
741  */
742 static int
743 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
744 {
745         int     status;
746
747         if ((status = ntohl(*p++)))
748                 status = -nfs_stat_to_errno(status);
749         xdr_decode_wcc_data(p, fattr);
750         return status;
751 }
752
753 static int
754 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
755 {
756         return nfs3_xdr_wccstat(req, p, &res->dir_attr);
757 }
758
759 /*
760  * Decode LOOKUP reply
761  */
762 static int
763 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
764 {
765         int     status;
766
767         if ((status = ntohl(*p++))) {
768                 status = -nfs_stat_to_errno(status);
769         } else {
770                 if (!(p = xdr_decode_fhandle(p, res->fh)))
771                         return -errno_NFSERR_IO;
772                 p = xdr_decode_post_op_attr(p, res->fattr);
773         }
774         xdr_decode_post_op_attr(p, res->dir_attr);
775         return status;
776 }
777
778 /*
779  * Decode ACCESS reply
780  */
781 static int
782 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
783 {
784         int     status = ntohl(*p++);
785
786         p = xdr_decode_post_op_attr(p, res->fattr);
787         if (status)
788                 return -nfs_stat_to_errno(status);
789         res->access = ntohl(*p++);
790         return 0;
791 }
792
793 static int
794 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
795 {
796         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
797         unsigned int replen;
798
799         p = xdr_encode_fhandle(p, args->fh);
800         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
801
802         /* Inline the page array */
803         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
804         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
805         return 0;
806 }
807
808 /*
809  * Decode READLINK reply
810  */
811 static int
812 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
813 {
814         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
815         struct kvec *iov = rcvbuf->head;
816         int hdrlen, len, recvd;
817         char    *kaddr;
818         int     status;
819
820         status = ntohl(*p++);
821         p = xdr_decode_post_op_attr(p, fattr);
822
823         if (status != 0)
824                 return -nfs_stat_to_errno(status);
825
826         /* Convert length of symlink */
827         len = ntohl(*p++);
828         if (len >= rcvbuf->page_len || len <= 0) {
829                 dprintk("nfs: server returned giant symlink!\n");
830                 return -ENAMETOOLONG;
831         }
832
833         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
834         if (iov->iov_len < hdrlen) {
835                 dprintk("NFS: READLINK reply header overflowed:"
836                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
837                 return -errno_NFSERR_IO;
838         } else if (iov->iov_len != hdrlen) {
839                 dprintk("NFS: READLINK header is short. "
840                         "iovec will be shifted.\n");
841                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
842         }
843         recvd = req->rq_rcv_buf.len - hdrlen;
844         if (recvd < len) {
845                 dprintk("NFS: server cheating in readlink reply: "
846                                 "count %u > recvd %u\n", len, recvd);
847                 return -EIO;
848         }
849
850         /* NULL terminate the string we got */
851         kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
852         kaddr[len+rcvbuf->page_base] = '\0';
853         kunmap_atomic(kaddr, KM_USER0);
854         return 0;
855 }
856
857 /*
858  * Decode READ reply
859  */
860 static int
861 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
862 {
863         struct kvec *iov = req->rq_rcv_buf.head;
864         int     status, count, ocount, recvd, hdrlen;
865
866         status = ntohl(*p++);
867         p = xdr_decode_post_op_attr(p, res->fattr);
868
869         if (status != 0)
870                 return -nfs_stat_to_errno(status);
871
872         /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
873          * in that it puts the count both in the res struct and in the
874          * opaque data count. */
875         count    = ntohl(*p++);
876         res->eof = ntohl(*p++);
877         ocount   = ntohl(*p++);
878
879         if (ocount != count) {
880                 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
881                 return -errno_NFSERR_IO;
882         }
883
884         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
885         if (iov->iov_len < hdrlen) {
886                 dprintk("NFS: READ reply header overflowed:"
887                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
888                 return -errno_NFSERR_IO;
889         } else if (iov->iov_len != hdrlen) {
890                 dprintk("NFS: READ header is short. iovec will be shifted.\n");
891                 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
892         }
893
894         recvd = req->rq_rcv_buf.len - hdrlen;
895         if (count > recvd) {
896                 dprintk("NFS: server cheating in read reply: "
897                         "count %d > recvd %d\n", count, recvd);
898                 count = recvd;
899                 res->eof = 0;
900         }
901
902         if (count < res->count)
903                 res->count = count;
904
905         return count;
906 }
907
908 /*
909  * Decode WRITE response
910  */
911 static int
912 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
913 {
914         int     status;
915
916         status = ntohl(*p++);
917         p = xdr_decode_wcc_data(p, res->fattr);
918
919         if (status != 0)
920                 return -nfs_stat_to_errno(status);
921
922         res->count = ntohl(*p++);
923         res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
924         res->verf->verifier[0] = *p++;
925         res->verf->verifier[1] = *p++;
926
927         return res->count;
928 }
929
930 /*
931  * Decode a CREATE response
932  */
933 static int
934 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
935 {
936         int     status;
937
938         status = ntohl(*p++);
939         if (status == 0) {
940                 if (*p++) {
941                         if (!(p = xdr_decode_fhandle(p, res->fh)))
942                                 return -errno_NFSERR_IO;
943                         p = xdr_decode_post_op_attr(p, res->fattr);
944                 } else {
945                         memset(res->fh, 0, sizeof(*res->fh));
946                         /* Do decode post_op_attr but set it to NULL */
947                         p = xdr_decode_post_op_attr(p, res->fattr);
948                         res->fattr->valid = 0;
949                 }
950         } else {
951                 status = -nfs_stat_to_errno(status);
952         }
953         p = xdr_decode_wcc_data(p, res->dir_attr);
954         return status;
955 }
956
957 /*
958  * Decode RENAME reply
959  */
960 static int
961 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
962 {
963         int     status;
964
965         if ((status = ntohl(*p++)) != 0)
966                 status = -nfs_stat_to_errno(status);
967         p = xdr_decode_wcc_data(p, res->fromattr);
968         p = xdr_decode_wcc_data(p, res->toattr);
969         return status;
970 }
971
972 /*
973  * Decode LINK reply
974  */
975 static int
976 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
977 {
978         int     status;
979
980         if ((status = ntohl(*p++)) != 0)
981                 status = -nfs_stat_to_errno(status);
982         p = xdr_decode_post_op_attr(p, res->fattr);
983         p = xdr_decode_wcc_data(p, res->dir_attr);
984         return status;
985 }
986
987 /*
988  * Decode FSSTAT reply
989  */
990 static int
991 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
992 {
993         int             status;
994
995         status = ntohl(*p++);
996
997         p = xdr_decode_post_op_attr(p, res->fattr);
998         if (status != 0)
999                 return -nfs_stat_to_errno(status);
1000
1001         p = xdr_decode_hyper(p, &res->tbytes);
1002         p = xdr_decode_hyper(p, &res->fbytes);
1003         p = xdr_decode_hyper(p, &res->abytes);
1004         p = xdr_decode_hyper(p, &res->tfiles);
1005         p = xdr_decode_hyper(p, &res->ffiles);
1006         p = xdr_decode_hyper(p, &res->afiles);
1007
1008         /* ignore invarsec */
1009         return 0;
1010 }
1011
1012 /*
1013  * Decode FSINFO reply
1014  */
1015 static int
1016 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1017 {
1018         int             status;
1019
1020         status = ntohl(*p++);
1021
1022         p = xdr_decode_post_op_attr(p, res->fattr);
1023         if (status != 0)
1024                 return -nfs_stat_to_errno(status);
1025
1026         res->rtmax  = ntohl(*p++);
1027         res->rtpref = ntohl(*p++);
1028         res->rtmult = ntohl(*p++);
1029         res->wtmax  = ntohl(*p++);
1030         res->wtpref = ntohl(*p++);
1031         res->wtmult = ntohl(*p++);
1032         res->dtpref = ntohl(*p++);
1033         p = xdr_decode_hyper(p, &res->maxfilesize);
1034
1035         /* ignore time_delta and properties */
1036         res->lease_time = 0;
1037         return 0;
1038 }
1039
1040 /*
1041  * Decode PATHCONF reply
1042  */
1043 static int
1044 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1045 {
1046         int             status;
1047
1048         status = ntohl(*p++);
1049
1050         p = xdr_decode_post_op_attr(p, res->fattr);
1051         if (status != 0)
1052                 return -nfs_stat_to_errno(status);
1053         res->max_link = ntohl(*p++);
1054         res->max_namelen = ntohl(*p++);
1055
1056         /* ignore remaining fields */
1057         return 0;
1058 }
1059
1060 /*
1061  * Decode COMMIT reply
1062  */
1063 static int
1064 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1065 {
1066         int             status;
1067
1068         status = ntohl(*p++);
1069         p = xdr_decode_wcc_data(p, res->fattr);
1070         if (status != 0)
1071                 return -nfs_stat_to_errno(status);
1072
1073         res->verf->verifier[0] = *p++;
1074         res->verf->verifier[1] = *p++;
1075         return 0;
1076 }
1077
1078 #ifdef CONFIG_NFS_V3_ACL
1079 /*
1080  * Decode GETACL reply
1081  */
1082 static int
1083 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1084                    struct nfs3_getaclres *res)
1085 {
1086         struct xdr_buf *buf = &req->rq_rcv_buf;
1087         int status = ntohl(*p++);
1088         struct posix_acl **acl;
1089         unsigned int *aclcnt;
1090         int err, base;
1091
1092         if (status != 0)
1093                 return -nfs_stat_to_errno(status);
1094         p = xdr_decode_post_op_attr(p, res->fattr);
1095         res->mask = ntohl(*p++);
1096         if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1097                 return -EINVAL;
1098         base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1099
1100         acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1101         aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1102         err = nfsacl_decode(buf, base, aclcnt, acl);
1103
1104         acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1105         aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1106         if (err > 0)
1107                 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1108         return (err > 0) ? 0 : err;
1109 }
1110
1111 /*
1112  * Decode setacl reply.
1113  */
1114 static int
1115 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1116 {
1117         int status = ntohl(*p++);
1118
1119         if (status)
1120                 return -nfs_stat_to_errno(status);
1121         xdr_decode_post_op_attr(p, fattr);
1122         return 0;
1123 }
1124 #endif  /* CONFIG_NFS_V3_ACL */
1125
1126 #define PROC(proc, argtype, restype, timer)                             \
1127 [NFS3PROC_##proc] = {                                                   \
1128         .p_proc      = NFS3PROC_##proc,                                 \
1129         .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,                 \
1130         .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                 \
1131         .p_arglen    = NFS3_##argtype##_sz,                             \
1132         .p_replen    = NFS3_##restype##_sz,                             \
1133         .p_timer     = timer,                                           \
1134         .p_statidx   = NFS3PROC_##proc,                                 \
1135         .p_name      = #proc,                                           \
1136         }
1137
1138 struct rpc_procinfo     nfs3_procedures[] = {
1139   PROC(GETATTR,         fhandle,        attrstat, 1),
1140   PROC(SETATTR,         sattrargs,      wccstat, 0),
1141   PROC(LOOKUP,          diropargs,      lookupres, 2),
1142   PROC(ACCESS,          accessargs,     accessres, 1),
1143   PROC(READLINK,        readlinkargs,   readlinkres, 3),
1144   PROC(READ,            readargs,       readres, 3),
1145   PROC(WRITE,           writeargs,      writeres, 4),
1146   PROC(CREATE,          createargs,     createres, 0),
1147   PROC(MKDIR,           mkdirargs,      createres, 0),
1148   PROC(SYMLINK,         symlinkargs,    createres, 0),
1149   PROC(MKNOD,           mknodargs,      createres, 0),
1150   PROC(REMOVE,          removeargs,     removeres, 0),
1151   PROC(RMDIR,           diropargs,      wccstat, 0),
1152   PROC(RENAME,          renameargs,     renameres, 0),
1153   PROC(LINK,            linkargs,       linkres, 0),
1154   PROC(READDIR,         readdirargs,    readdirres, 3),
1155   PROC(READDIRPLUS,     readdirargs,    readdirres, 3),
1156   PROC(FSSTAT,          fhandle,        fsstatres, 0),
1157   PROC(FSINFO,          fhandle,        fsinfores, 0),
1158   PROC(PATHCONF,        fhandle,        pathconfres, 0),
1159   PROC(COMMIT,          commitargs,     commitres, 5),
1160 };
1161
1162 struct rpc_version              nfs_version3 = {
1163         .number                 = 3,
1164         .nrprocs                = ARRAY_SIZE(nfs3_procedures),
1165         .procs                  = nfs3_procedures
1166 };
1167
1168 #ifdef CONFIG_NFS_V3_ACL
1169 static struct rpc_procinfo      nfs3_acl_procedures[] = {
1170         [ACLPROC3_GETACL] = {
1171                 .p_proc = ACLPROC3_GETACL,
1172                 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1173                 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1174                 .p_arglen = ACL3_getaclargs_sz,
1175                 .p_replen = ACL3_getaclres_sz,
1176                 .p_timer = 1,
1177                 .p_name = "GETACL",
1178         },
1179         [ACLPROC3_SETACL] = {
1180                 .p_proc = ACLPROC3_SETACL,
1181                 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1182                 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1183                 .p_arglen = ACL3_setaclargs_sz,
1184                 .p_replen = ACL3_setaclres_sz,
1185                 .p_timer = 0,
1186                 .p_name = "SETACL",
1187         },
1188 };
1189
1190 struct rpc_version              nfsacl_version3 = {
1191         .number                 = 3,
1192         .nrprocs                = sizeof(nfs3_acl_procedures)/
1193                                   sizeof(nfs3_acl_procedures[0]),
1194         .procs                  = nfs3_acl_procedures,
1195 };
1196 #endif  /* CONFIG_NFS_V3_ACL */