1
2
3
4
5
6
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/errno.h>
14#include <linux/string.h>
15#include <linux/in.h>
16#include <linux/pagemap.h>
17#include <linux/proc_fs.h>
18#include <linux/kdev_t.h>
19#include <linux/sunrpc/clnt.h>
20#include <linux/nfs.h>
21#include <linux/nfs3.h>
22#include <linux/nfs_fs.h>
23#include <linux/nfsacl.h>
24#include "internal.h"
25
26#define NFSDBG_FACILITY NFSDBG_XDR
27
28
29#define errno_NFSERR_IO EIO
30
31
32
33
34
35#define NFS3_fhandle_sz (1+16)
36#define NFS3_fh_sz (NFS3_fhandle_sz)
37#define NFS3_sattr_sz (15)
38#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
39#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
40#define NFS3_fattr_sz (21)
41#define NFS3_wcc_attr_sz (6)
42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
45#define NFS3_fsstat_sz
46#define NFS3_fsinfo_sz
47#define NFS3_pathconf_sz
48#define NFS3_entry_sz (NFS3_filename_sz+3)
49
50#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
51#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
52#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
53#define NFS3_accessargs_sz (NFS3_fh_sz+1)
54#define NFS3_readlinkargs_sz (NFS3_fh_sz)
55#define NFS3_readargs_sz (NFS3_fh_sz+3)
56#define NFS3_writeargs_sz (NFS3_fh_sz+5)
57#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
60#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
61#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
62#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
63#define NFS3_readdirargs_sz (NFS3_fh_sz+2)
64#define NFS3_commitargs_sz (NFS3_fh_sz+3)
65
66#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
67#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
68#define NFS3_removeres_sz (NFS3_wccstat_sz)
69#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
70#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
71#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
72#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
73#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
74#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
75#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
76#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
77#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
78#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
79#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
80#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
81#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
82
83#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
84#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
85 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
86#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
87 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
88#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
89
90
91
92
93static const umode_t nfs_type2fmt[] = {
94 [NF3BAD] = 0,
95 [NF3REG] = S_IFREG,
96 [NF3DIR] = S_IFDIR,
97 [NF3BLK] = S_IFBLK,
98 [NF3CHR] = S_IFCHR,
99 [NF3LNK] = S_IFLNK,
100 [NF3SOCK] = S_IFSOCK,
101 [NF3FIFO] = S_IFIFO,
102};
103
104
105
106
107static inline __be32 *
108xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
109{
110 return xdr_encode_array(p, fh->data, fh->size);
111}
112
113static inline __be32 *
114xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
115{
116 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
117 memcpy(fh->data, p, fh->size);
118 return p + XDR_QUADLEN(fh->size);
119 }
120 return NULL;
121}
122
123
124
125
126static inline __be32 *
127xdr_encode_time3(__be32 *p, struct timespec *timep)
128{
129 *p++ = htonl(timep->tv_sec);
130 *p++ = htonl(timep->tv_nsec);
131 return p;
132}
133
134static inline __be32 *
135xdr_decode_time3(__be32 *p, struct timespec *timep)
136{
137 timep->tv_sec = ntohl(*p++);
138 timep->tv_nsec = ntohl(*p++);
139 return p;
140}
141
142static __be32 *
143xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
144{
145 unsigned int type, major, minor;
146 umode_t fmode;
147
148 type = ntohl(*p++);
149 if (type > NF3FIFO)
150 type = NF3NON;
151 fmode = nfs_type2fmt[type];
152 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
153 fattr->nlink = ntohl(*p++);
154 fattr->uid = ntohl(*p++);
155 fattr->gid = ntohl(*p++);
156 p = xdr_decode_hyper(p, &fattr->size);
157 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
158
159
160 major = ntohl(*p++);
161 minor = ntohl(*p++);
162 fattr->rdev = MKDEV(major, minor);
163 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
164 fattr->rdev = 0;
165
166 p = xdr_decode_hyper(p, &fattr->fsid.major);
167 fattr->fsid.minor = 0;
168 p = xdr_decode_hyper(p, &fattr->fileid);
169 p = xdr_decode_time3(p, &fattr->atime);
170 p = xdr_decode_time3(p, &fattr->mtime);
171 p = xdr_decode_time3(p, &fattr->ctime);
172
173
174 fattr->valid |= NFS_ATTR_FATTR_V3;
175 return p;
176}
177
178static inline __be32 *
179xdr_encode_sattr(__be32 *p, struct iattr *attr)
180{
181 if (attr->ia_valid & ATTR_MODE) {
182 *p++ = xdr_one;
183 *p++ = htonl(attr->ia_mode & S_IALLUGO);
184 } else {
185 *p++ = xdr_zero;
186 }
187 if (attr->ia_valid & ATTR_UID) {
188 *p++ = xdr_one;
189 *p++ = htonl(attr->ia_uid);
190 } else {
191 *p++ = xdr_zero;
192 }
193 if (attr->ia_valid & ATTR_GID) {
194 *p++ = xdr_one;
195 *p++ = htonl(attr->ia_gid);
196 } else {
197 *p++ = xdr_zero;
198 }
199 if (attr->ia_valid & ATTR_SIZE) {
200 *p++ = xdr_one;
201 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
202 } else {
203 *p++ = xdr_zero;
204 }
205 if (attr->ia_valid & ATTR_ATIME_SET) {
206 *p++ = xdr_two;
207 p = xdr_encode_time3(p, &attr->ia_atime);
208 } else if (attr->ia_valid & ATTR_ATIME) {
209 *p++ = xdr_one;
210 } else {
211 *p++ = xdr_zero;
212 }
213 if (attr->ia_valid & ATTR_MTIME_SET) {
214 *p++ = xdr_two;
215 p = xdr_encode_time3(p, &attr->ia_mtime);
216 } else if (attr->ia_valid & ATTR_MTIME) {
217 *p++ = xdr_one;
218 } else {
219 *p++ = xdr_zero;
220 }
221 return p;
222}
223
224static inline __be32 *
225xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
226{
227 p = xdr_decode_hyper(p, &fattr->pre_size);
228 p = xdr_decode_time3(p, &fattr->pre_mtime);
229 p = xdr_decode_time3(p, &fattr->pre_ctime);
230 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
231 | NFS_ATTR_FATTR_PREMTIME
232 | NFS_ATTR_FATTR_PRECTIME;
233 return p;
234}
235
236static inline __be32 *
237xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
238{
239 if (*p++)
240 p = xdr_decode_fattr(p, fattr);
241 return p;
242}
243
244static inline __be32 *
245xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
246{
247 if (*p++)
248 return xdr_decode_wcc_attr(p, fattr);
249 return p;
250}
251
252
253static inline __be32 *
254xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
255{
256 p = xdr_decode_pre_op_attr(p, fattr);
257 return xdr_decode_post_op_attr(p, fattr);
258}
259
260
261
262
263
264
265
266
267static int
268nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
269{
270 p = xdr_encode_fhandle(p, fh);
271 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
272 return 0;
273}
274
275
276
277
278static int
279nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
280{
281 p = xdr_encode_fhandle(p, args->fh);
282 p = xdr_encode_sattr(p, args->sattr);
283 *p++ = htonl(args->guard);
284 if (args->guard)
285 p = xdr_encode_time3(p, &args->guardtime);
286 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
287 return 0;
288}
289
290
291
292
293static int
294nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
295{
296 p = xdr_encode_fhandle(p, args->fh);
297 p = xdr_encode_array(p, args->name, args->len);
298 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
299 return 0;
300}
301
302
303
304
305static int
306nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
307{
308 p = xdr_encode_fhandle(p, args->fh);
309 p = xdr_encode_array(p, args->name.name, args->name.len);
310 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
311 return 0;
312}
313
314
315
316
317static int
318nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
319{
320 p = xdr_encode_fhandle(p, args->fh);
321 *p++ = htonl(args->access);
322 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
323 return 0;
324}
325
326
327
328
329
330
331static int
332nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
333{
334 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
335 unsigned int replen;
336 u32 count = args->count;
337
338 p = xdr_encode_fhandle(p, args->fh);
339 p = xdr_encode_hyper(p, args->offset);
340 *p++ = htonl(count);
341 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
342
343
344 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
345 xdr_inline_pages(&req->rq_rcv_buf, replen,
346 args->pages, args->pgbase, count);
347 req->rq_rcv_buf.flags |= XDRBUF_READ;
348 return 0;
349}
350
351
352
353
354static int
355nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
356{
357 struct xdr_buf *sndbuf = &req->rq_snd_buf;
358 u32 count = args->count;
359
360 p = xdr_encode_fhandle(p, args->fh);
361 p = xdr_encode_hyper(p, args->offset);
362 *p++ = htonl(count);
363 *p++ = htonl(args->stable);
364 *p++ = htonl(count);
365 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
366
367
368 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
369 sndbuf->flags |= XDRBUF_WRITE;
370 return 0;
371}
372
373
374
375
376static int
377nfs3_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
395
396static int
397nfs3_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
408
409static int
410nfs3_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
419 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
420 return 0;
421}
422
423
424
425
426static int
427nfs3_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
444
445static int
446nfs3_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
458
459static int
460nfs3_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
471
472static int
473nfs3_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
485
486 *p++ = htonl(count >> 3);
487 }
488 *p++ = htonl(count);
489 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
490
491
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
499
500
501static int
502nfs3_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 size_t hdrlen;
508 u32 len, recvd, pglen;
509 int status, nr = 0;
510 __be32 *entry, *end, *kaddr;
511
512 status = ntohl(*p++);
513
514 p = xdr_decode_post_op_attr(p, res->dir_attr);
515 if (status)
516 return nfs_stat_to_errno(status);
517
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 %Zu > %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
544
545 if ((entry + 1) > end)
546 goto short_pkt;
547
548 for (; *p++; nr++) {
549 if (p + 3 > end)
550 goto short_pkt;
551 p += 2;
552 len = ntohl(*p++);
553 p += XDR_QUADLEN(len) + 2;
554 if (len > NFS3_MAXNAMLEN) {
555 dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
556 len);
557 goto err_unmap;
558 }
559
560 if (res->plus) {
561
562 if (p + 2 > end)
563 goto short_pkt;
564 if (*p++) {
565 p += 21;
566 if (p + 1 > end)
567 goto short_pkt;
568 }
569
570 if (*p++) {
571 if (p + 1 > end)
572 goto short_pkt;
573 len = ntohl(*p++);
574 if (len > NFS3_FHSIZE) {
575 dprintk("NFS: giant filehandle in "
576 "readdir (len 0x%x)!\n", len);
577 goto err_unmap;
578 }
579 p += XDR_QUADLEN(len);
580 }
581 }
582
583 if (p + 2 > end)
584 goto short_pkt;
585 entry = p;
586 }
587
588
589
590
591
592
593 if (!nr && entry[1] == 0) {
594 dprintk("NFS: readdir reply truncated!\n");
595 entry[1] = 1;
596 }
597 out:
598 kunmap_atomic(kaddr, KM_USER0);
599 return nr;
600 short_pkt:
601
602
603
604
605
606
607
608
609
610 entry[0] = entry[1] = 0;
611 if (!nr)
612 nr = -errno_NFSERR_IO;
613 goto out;
614err_unmap:
615 nr = -errno_NFSERR_IO;
616 goto out;
617}
618
619__be32 *
620nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
621{
622 struct nfs_entry old = *entry;
623
624 if (!*p++) {
625 if (!*p)
626 return ERR_PTR(-EAGAIN);
627 entry->eof = 1;
628 return ERR_PTR(-EBADCOOKIE);
629 }
630
631 p = xdr_decode_hyper(p, &entry->ino);
632 entry->len = ntohl(*p++);
633 entry->name = (const char *) p;
634 p += XDR_QUADLEN(entry->len);
635 entry->prev_cookie = entry->cookie;
636 p = xdr_decode_hyper(p, &entry->cookie);
637
638 if (plus) {
639 entry->fattr->valid = 0;
640 p = xdr_decode_post_op_attr(p, entry->fattr);
641
642 if (*p++) {
643 p = xdr_decode_fhandle(p, entry->fh);
644
645 if (p == NULL) {
646 dprintk("NFS: FH truncated\n");
647 *entry = old;
648 return ERR_PTR(-EAGAIN);
649 }
650 } else
651 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
652 }
653
654 entry->eof = !p[0] && p[1];
655 return p;
656}
657
658
659
660
661static int
662nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
663{
664 p = xdr_encode_fhandle(p, args->fh);
665 p = xdr_encode_hyper(p, args->offset);
666 *p++ = htonl(args->count);
667 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
668 return 0;
669}
670
671#ifdef CONFIG_NFS_V3_ACL
672
673
674
675static int
676nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
677 struct nfs3_getaclargs *args)
678{
679 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
680 unsigned int replen;
681
682 p = xdr_encode_fhandle(p, args->fh);
683 *p++ = htonl(args->mask);
684 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
685
686 if (args->mask & (NFS_ACL | NFS_DFACL)) {
687
688 replen = (RPC_REPHDRSIZE + auth->au_rslack +
689 ACL3_getaclres_sz) << 2;
690 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
691 NFSACL_MAXPAGES << PAGE_SHIFT);
692 }
693 return 0;
694}
695
696
697
698
699static int
700nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
701 struct nfs3_setaclargs *args)
702{
703 struct xdr_buf *buf = &req->rq_snd_buf;
704 unsigned int base;
705 int err;
706
707 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
708 *p++ = htonl(args->mask);
709 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
710 base = req->rq_slen;
711
712 if (args->npages != 0)
713 xdr_encode_pages(buf, args->pages, 0, args->len);
714 else
715 req->rq_slen = xdr_adjust_iovec(req->rq_svec,
716 p + XDR_QUADLEN(args->len));
717
718 err = nfsacl_encode(buf, base, args->inode,
719 (args->mask & NFS_ACL) ?
720 args->acl_access : NULL, 1, 0);
721 if (err > 0)
722 err = nfsacl_encode(buf, base + err, args->inode,
723 (args->mask & NFS_DFACL) ?
724 args->acl_default : NULL, 1,
725 NFS_ACL_DEFAULT);
726 return (err > 0) ? 0 : err;
727}
728#endif
729
730
731
732
733
734
735
736
737static int
738nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
739{
740 int status;
741
742 if ((status = ntohl(*p++)))
743 return nfs_stat_to_errno(status);
744 xdr_decode_fattr(p, fattr);
745 return 0;
746}
747
748
749
750
751
752static int
753nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
754{
755 int status;
756
757 if ((status = ntohl(*p++)))
758 status = nfs_stat_to_errno(status);
759 xdr_decode_wcc_data(p, fattr);
760 return status;
761}
762
763static int
764nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
765{
766 return nfs3_xdr_wccstat(req, p, &res->dir_attr);
767}
768
769
770
771
772static int
773nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
774{
775 int status;
776
777 if ((status = ntohl(*p++))) {
778 status = nfs_stat_to_errno(status);
779 } else {
780 if (!(p = xdr_decode_fhandle(p, res->fh)))
781 return -errno_NFSERR_IO;
782 p = xdr_decode_post_op_attr(p, res->fattr);
783 }
784 xdr_decode_post_op_attr(p, res->dir_attr);
785 return status;
786}
787
788
789
790
791static int
792nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
793{
794 int status = ntohl(*p++);
795
796 p = xdr_decode_post_op_attr(p, res->fattr);
797 if (status)
798 return nfs_stat_to_errno(status);
799 res->access = ntohl(*p++);
800 return 0;
801}
802
803static int
804nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
805{
806 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
807 unsigned int replen;
808
809 p = xdr_encode_fhandle(p, args->fh);
810 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
811
812
813 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
814 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
815 return 0;
816}
817
818
819
820
821static int
822nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
823{
824 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
825 struct kvec *iov = rcvbuf->head;
826 size_t hdrlen;
827 u32 len, recvd;
828 char *kaddr;
829 int status;
830
831 status = ntohl(*p++);
832 p = xdr_decode_post_op_attr(p, fattr);
833
834 if (status != 0)
835 return nfs_stat_to_errno(status);
836
837
838 len = ntohl(*p++);
839 if (len >= rcvbuf->page_len) {
840 dprintk("nfs: server returned giant symlink!\n");
841 return -ENAMETOOLONG;
842 }
843
844 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
845 if (iov->iov_len < hdrlen) {
846 dprintk("NFS: READLINK reply header overflowed:"
847 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
848 return -errno_NFSERR_IO;
849 } else if (iov->iov_len != hdrlen) {
850 dprintk("NFS: READLINK header is short. "
851 "iovec will be shifted.\n");
852 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
853 }
854 recvd = req->rq_rcv_buf.len - hdrlen;
855 if (recvd < len) {
856 dprintk("NFS: server cheating in readlink reply: "
857 "count %u > recvd %u\n", len, recvd);
858 return -EIO;
859 }
860
861
862 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
863 kaddr[len+rcvbuf->page_base] = '\0';
864 kunmap_atomic(kaddr, KM_USER0);
865 return 0;
866}
867
868
869
870
871static int
872nfs3_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
886
887
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
923
924static int
925nfs3_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
945
946static int
947nfs3_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
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
972
973static int
974nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_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->fromattr);
981 p = xdr_decode_wcc_data(p, res->toattr);
982 return status;
983}
984
985
986
987
988static int
989nfs3_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
1002
1003static int
1004nfs3_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
1022 return 0;
1023}
1024
1025
1026
1027
1028static int
1029nfs3_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
1048
1049 res->lease_time = 0;
1050 return 0;
1051}
1052
1053
1054
1055
1056static int
1057nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1058{
1059 int status;
1060
1061 status = ntohl(*p++);
1062
1063 p = xdr_decode_post_op_attr(p, res->fattr);
1064 if (status != 0)
1065 return nfs_stat_to_errno(status);
1066 res->max_link = ntohl(*p++);
1067 res->max_namelen = ntohl(*p++);
1068
1069
1070 return 0;
1071}
1072
1073
1074
1075
1076static int
1077nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1078{
1079 int status;
1080
1081 status = ntohl(*p++);
1082 p = xdr_decode_wcc_data(p, res->fattr);
1083 if (status != 0)
1084 return nfs_stat_to_errno(status);
1085
1086 res->verf->verifier[0] = *p++;
1087 res->verf->verifier[1] = *p++;
1088 return 0;
1089}
1090
1091#ifdef CONFIG_NFS_V3_ACL
1092
1093
1094
1095static int
1096nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1097 struct nfs3_getaclres *res)
1098{
1099 struct xdr_buf *buf = &req->rq_rcv_buf;
1100 int status = ntohl(*p++);
1101 struct posix_acl **acl;
1102 unsigned int *aclcnt;
1103 int err, base;
1104
1105 if (status != 0)
1106 return nfs_stat_to_errno(status);
1107 p = xdr_decode_post_op_attr(p, res->fattr);
1108 res->mask = ntohl(*p++);
1109 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1110 return -EINVAL;
1111 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1112
1113 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1114 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1115 err = nfsacl_decode(buf, base, aclcnt, acl);
1116
1117 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1118 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1119 if (err > 0)
1120 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1121 return (err > 0) ? 0 : err;
1122}
1123
1124
1125
1126
1127static int
1128nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1129{
1130 int status = ntohl(*p++);
1131
1132 if (status)
1133 return nfs_stat_to_errno(status);
1134 xdr_decode_post_op_attr(p, fattr);
1135 return 0;
1136}
1137#endif
1138
1139#define PROC(proc, argtype, restype, timer) \
1140[NFS3PROC_##proc] = { \
1141 .p_proc = NFS3PROC_##proc, \
1142 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1143 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
1144 .p_arglen = NFS3_##argtype##_sz, \
1145 .p_replen = NFS3_##restype##_sz, \
1146 .p_timer = timer, \
1147 .p_statidx = NFS3PROC_##proc, \
1148 .p_name = #proc, \
1149 }
1150
1151struct rpc_procinfo nfs3_procedures[] = {
1152 PROC(GETATTR, fhandle, attrstat, 1),
1153 PROC(SETATTR, sattrargs, wccstat, 0),
1154 PROC(LOOKUP, diropargs, lookupres, 2),
1155 PROC(ACCESS, accessargs, accessres, 1),
1156 PROC(READLINK, readlinkargs, readlinkres, 3),
1157 PROC(READ, readargs, readres, 3),
1158 PROC(WRITE, writeargs, writeres, 4),
1159 PROC(CREATE, createargs, createres, 0),
1160 PROC(MKDIR, mkdirargs, createres, 0),
1161 PROC(SYMLINK, symlinkargs, createres, 0),
1162 PROC(MKNOD, mknodargs, createres, 0),
1163 PROC(REMOVE, removeargs, removeres, 0),
1164 PROC(RMDIR, diropargs, wccstat, 0),
1165 PROC(RENAME, renameargs, renameres, 0),
1166 PROC(LINK, linkargs, linkres, 0),
1167 PROC(READDIR, readdirargs, readdirres, 3),
1168 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1169 PROC(FSSTAT, fhandle, fsstatres, 0),
1170 PROC(FSINFO, fhandle, fsinfores, 0),
1171 PROC(PATHCONF, fhandle, pathconfres, 0),
1172 PROC(COMMIT, commitargs, commitres, 5),
1173};
1174
1175struct rpc_version nfs_version3 = {
1176 .number = 3,
1177 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1178 .procs = nfs3_procedures
1179};
1180
1181#ifdef CONFIG_NFS_V3_ACL
1182static struct rpc_procinfo nfs3_acl_procedures[] = {
1183 [ACLPROC3_GETACL] = {
1184 .p_proc = ACLPROC3_GETACL,
1185 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1186 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1187 .p_arglen = ACL3_getaclargs_sz,
1188 .p_replen = ACL3_getaclres_sz,
1189 .p_timer = 1,
1190 .p_name = "GETACL",
1191 },
1192 [ACLPROC3_SETACL] = {
1193 .p_proc = ACLPROC3_SETACL,
1194 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1195 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1196 .p_arglen = ACL3_setaclargs_sz,
1197 .p_replen = ACL3_setaclres_sz,
1198 .p_timer = 0,
1199 .p_name = "SETACL",
1200 },
1201};
1202
1203struct rpc_version nfsacl_version3 = {
1204 .number = 3,
1205 .nrprocs = sizeof(nfs3_acl_procedures)/
1206 sizeof(nfs3_acl_procedures[0]),
1207 .procs = nfs3_acl_procedures,
1208};
1209#endif
1210