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