1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36#include <linux/file.h>
37#include <linux/slab.h>
38#include <linux/namei.h>
39#include <linux/statfs.h>
40#include <linux/utsname.h>
41#include <linux/pagemap.h>
42#include <linux/sunrpc/svcauth_gss.h>
43
44#include "idmap.h"
45#include "acl.h"
46#include "xdr4.h"
47#include "vfs.h"
48#include "state.h"
49#include "cache.h"
50#include "netns.h"
51#include "pnfs.h"
52#include "filecache.h"
53
54#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
55#include <linux/security.h>
56#endif
57
58
59#define NFSDDBG_FACILITY NFSDDBG_XDR
60
61const u32 nfsd_suppattrs[3][3] = {
62 {NFSD4_SUPPORTED_ATTRS_WORD0,
63 NFSD4_SUPPORTED_ATTRS_WORD1,
64 NFSD4_SUPPORTED_ATTRS_WORD2},
65
66 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
67 NFSD4_1_SUPPORTED_ATTRS_WORD1,
68 NFSD4_1_SUPPORTED_ATTRS_WORD2},
69
70 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
71 NFSD4_1_SUPPORTED_ATTRS_WORD1,
72 NFSD4_2_SUPPORTED_ATTRS_WORD2},
73};
74
75
76
77
78
79
80#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
81#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
82
83static __be32
84check_filename(char *str, int len)
85{
86 int i;
87
88 if (len == 0)
89 return nfserr_inval;
90 if (isdotent(str, len))
91 return nfserr_badname;
92 for (i = 0; i < len; i++)
93 if (str[i] == '/')
94 return nfserr_badname;
95 return 0;
96}
97
98#define DECODE_HEAD \
99 __be32 *p; \
100 __be32 status
101#define DECODE_TAIL \
102 status = 0; \
103out: \
104 return status; \
105xdr_error: \
106 dprintk("NFSD: xdr error (%s:%d)\n", \
107 __FILE__, __LINE__); \
108 status = nfserr_bad_xdr; \
109 goto out
110
111#define READMEM(x,nbytes) do { \
112 x = (char *)p; \
113 p += XDR_QUADLEN(nbytes); \
114} while (0)
115#define SAVEMEM(x,nbytes) do { \
116 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
117 savemem(argp, p, nbytes) : \
118 (char *)p)) { \
119 dprintk("NFSD: xdr error (%s:%d)\n", \
120 __FILE__, __LINE__); \
121 goto xdr_error; \
122 } \
123 p += XDR_QUADLEN(nbytes); \
124} while (0)
125#define COPYMEM(x,nbytes) do { \
126 memcpy((x), p, nbytes); \
127 p += XDR_QUADLEN(nbytes); \
128} while (0)
129
130
131#define READ_BUF(nbytes) do { \
132 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
133 p = argp->p; \
134 argp->p += XDR_QUADLEN(nbytes); \
135 } else if (!(p = read_buf(argp, nbytes))) { \
136 dprintk("NFSD: xdr error (%s:%d)\n", \
137 __FILE__, __LINE__); \
138 goto xdr_error; \
139 } \
140} while (0)
141
142static void next_decode_page(struct nfsd4_compoundargs *argp)
143{
144 argp->p = page_address(argp->pagelist[0]);
145 argp->pagelist++;
146 if (argp->pagelen < PAGE_SIZE) {
147 argp->end = argp->p + XDR_QUADLEN(argp->pagelen);
148 argp->pagelen = 0;
149 } else {
150 argp->end = argp->p + (PAGE_SIZE>>2);
151 argp->pagelen -= PAGE_SIZE;
152 }
153}
154
155static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
156{
157
158
159
160 unsigned int avail = (char *)argp->end - (char *)argp->p;
161 __be32 *p;
162
163 if (argp->pagelen == 0) {
164 struct kvec *vec = &argp->rqstp->rq_arg.tail[0];
165
166 if (!argp->tail) {
167 argp->tail = true;
168 avail = vec->iov_len;
169 argp->p = vec->iov_base;
170 argp->end = vec->iov_base + avail;
171 }
172
173 if (avail < nbytes)
174 return NULL;
175
176 p = argp->p;
177 argp->p += XDR_QUADLEN(nbytes);
178 return p;
179 }
180
181 if (avail + argp->pagelen < nbytes)
182 return NULL;
183 if (avail + PAGE_SIZE < nbytes)
184 return NULL;
185
186 if (nbytes <= sizeof(argp->tmp))
187 p = argp->tmp;
188 else {
189 kfree(argp->tmpp);
190 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
191 if (!p)
192 return NULL;
193
194 }
195
196
197
198
199
200 memcpy(p, argp->p, avail);
201 next_decode_page(argp);
202 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
203 argp->p += XDR_QUADLEN(nbytes - avail);
204 return p;
205}
206
207static unsigned int compoundargs_bytes_left(struct nfsd4_compoundargs *argp)
208{
209 unsigned int this = (char *)argp->end - (char *)argp->p;
210
211 return this + argp->pagelen;
212}
213
214static int zero_clientid(clientid_t *clid)
215{
216 return (clid->cl_boot == 0) && (clid->cl_id == 0);
217}
218
219
220
221
222
223
224
225
226
227static void *
228svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, u32 len)
229{
230 struct svcxdr_tmpbuf *tb;
231
232 tb = kmalloc(sizeof(*tb) + len, GFP_KERNEL);
233 if (!tb)
234 return NULL;
235 tb->next = argp->to_free;
236 argp->to_free = tb;
237 return tb->buf;
238}
239
240
241
242
243
244
245
246
247static char *
248svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
249{
250 char *p = svcxdr_tmpalloc(argp, len + 1);
251
252 if (!p)
253 return NULL;
254 memcpy(p, buf, len);
255 p[len] = '\0';
256 return p;
257}
258
259
260
261
262
263
264
265
266
267
268
269static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
270{
271 void *ret;
272
273 ret = svcxdr_tmpalloc(argp, nbytes);
274 if (!ret)
275 return NULL;
276 memcpy(ret, p, nbytes);
277 return ret;
278}
279
280static __be32
281nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec64 *tv)
282{
283 DECODE_HEAD;
284
285 READ_BUF(12);
286 p = xdr_decode_hyper(p, &tv->tv_sec);
287 tv->tv_nsec = be32_to_cpup(p++);
288 if (tv->tv_nsec >= (u32)1000000000)
289 return nfserr_inval;
290
291 DECODE_TAIL;
292}
293
294static __be32
295nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
296{
297 u32 bmlen;
298 DECODE_HEAD;
299
300 bmval[0] = 0;
301 bmval[1] = 0;
302 bmval[2] = 0;
303
304 READ_BUF(4);
305 bmlen = be32_to_cpup(p++);
306 if (bmlen > 1000)
307 goto xdr_error;
308
309 READ_BUF(bmlen << 2);
310 if (bmlen > 0)
311 bmval[0] = be32_to_cpup(p++);
312 if (bmlen > 1)
313 bmval[1] = be32_to_cpup(p++);
314 if (bmlen > 2)
315 bmval[2] = be32_to_cpup(p++);
316
317 DECODE_TAIL;
318}
319
320static __be32
321nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
322 struct iattr *iattr, struct nfs4_acl **acl,
323 struct xdr_netobj *label, int *umask)
324{
325 int expected_len, len = 0;
326 u32 dummy32;
327 char *buf;
328
329 DECODE_HEAD;
330 iattr->ia_valid = 0;
331 if ((status = nfsd4_decode_bitmap(argp, bmval)))
332 return status;
333
334 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
335 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
336 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) {
337 if (nfsd_attrs_supported(argp->minorversion, bmval))
338 return nfserr_inval;
339 return nfserr_attrnotsupp;
340 }
341
342 READ_BUF(4);
343 expected_len = be32_to_cpup(p++);
344
345 if (bmval[0] & FATTR4_WORD0_SIZE) {
346 READ_BUF(8);
347 len += 8;
348 p = xdr_decode_hyper(p, &iattr->ia_size);
349 iattr->ia_valid |= ATTR_SIZE;
350 }
351 if (bmval[0] & FATTR4_WORD0_ACL) {
352 u32 nace;
353 struct nfs4_ace *ace;
354
355 READ_BUF(4); len += 4;
356 nace = be32_to_cpup(p++);
357
358 if (nace > compoundargs_bytes_left(argp)/20)
359
360
361
362
363
364 return nfserr_fbig;
365
366 *acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(nace));
367 if (*acl == NULL)
368 return nfserr_jukebox;
369
370 (*acl)->naces = nace;
371 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
372 READ_BUF(16); len += 16;
373 ace->type = be32_to_cpup(p++);
374 ace->flag = be32_to_cpup(p++);
375 ace->access_mask = be32_to_cpup(p++);
376 dummy32 = be32_to_cpup(p++);
377 READ_BUF(dummy32);
378 len += XDR_QUADLEN(dummy32) << 2;
379 READMEM(buf, dummy32);
380 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
381 status = nfs_ok;
382 if (ace->whotype != NFS4_ACL_WHO_NAMED)
383 ;
384 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
385 status = nfsd_map_name_to_gid(argp->rqstp,
386 buf, dummy32, &ace->who_gid);
387 else
388 status = nfsd_map_name_to_uid(argp->rqstp,
389 buf, dummy32, &ace->who_uid);
390 if (status)
391 return status;
392 }
393 } else
394 *acl = NULL;
395 if (bmval[1] & FATTR4_WORD1_MODE) {
396 READ_BUF(4);
397 len += 4;
398 iattr->ia_mode = be32_to_cpup(p++);
399 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
400 iattr->ia_valid |= ATTR_MODE;
401 }
402 if (bmval[1] & FATTR4_WORD1_OWNER) {
403 READ_BUF(4);
404 len += 4;
405 dummy32 = be32_to_cpup(p++);
406 READ_BUF(dummy32);
407 len += (XDR_QUADLEN(dummy32) << 2);
408 READMEM(buf, dummy32);
409 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
410 return status;
411 iattr->ia_valid |= ATTR_UID;
412 }
413 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
414 READ_BUF(4);
415 len += 4;
416 dummy32 = be32_to_cpup(p++);
417 READ_BUF(dummy32);
418 len += (XDR_QUADLEN(dummy32) << 2);
419 READMEM(buf, dummy32);
420 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
421 return status;
422 iattr->ia_valid |= ATTR_GID;
423 }
424 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
425 READ_BUF(4);
426 len += 4;
427 dummy32 = be32_to_cpup(p++);
428 switch (dummy32) {
429 case NFS4_SET_TO_CLIENT_TIME:
430 len += 12;
431 status = nfsd4_decode_time(argp, &iattr->ia_atime);
432 if (status)
433 return status;
434 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
435 break;
436 case NFS4_SET_TO_SERVER_TIME:
437 iattr->ia_valid |= ATTR_ATIME;
438 break;
439 default:
440 goto xdr_error;
441 }
442 }
443 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
444 READ_BUF(4);
445 len += 4;
446 dummy32 = be32_to_cpup(p++);
447 switch (dummy32) {
448 case NFS4_SET_TO_CLIENT_TIME:
449 len += 12;
450 status = nfsd4_decode_time(argp, &iattr->ia_mtime);
451 if (status)
452 return status;
453 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
454 break;
455 case NFS4_SET_TO_SERVER_TIME:
456 iattr->ia_valid |= ATTR_MTIME;
457 break;
458 default:
459 goto xdr_error;
460 }
461 }
462
463 label->len = 0;
464 if (IS_ENABLED(CONFIG_NFSD_V4_SECURITY_LABEL) &&
465 bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
466 READ_BUF(4);
467 len += 4;
468 dummy32 = be32_to_cpup(p++);
469 READ_BUF(4);
470 len += 4;
471 dummy32 = be32_to_cpup(p++);
472 READ_BUF(4);
473 len += 4;
474 dummy32 = be32_to_cpup(p++);
475 READ_BUF(dummy32);
476 if (dummy32 > NFS4_MAXLABELLEN)
477 return nfserr_badlabel;
478 len += (XDR_QUADLEN(dummy32) << 2);
479 READMEM(buf, dummy32);
480 label->len = dummy32;
481 label->data = svcxdr_dupstr(argp, buf, dummy32);
482 if (!label->data)
483 return nfserr_jukebox;
484 }
485 if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
486 if (!umask)
487 goto xdr_error;
488 READ_BUF(8);
489 len += 8;
490 dummy32 = be32_to_cpup(p++);
491 iattr->ia_mode = dummy32 & (S_IFMT | S_IALLUGO);
492 dummy32 = be32_to_cpup(p++);
493 *umask = dummy32 & S_IRWXUGO;
494 iattr->ia_valid |= ATTR_MODE;
495 }
496 if (len != expected_len)
497 goto xdr_error;
498
499 DECODE_TAIL;
500}
501
502static __be32
503nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
504{
505 DECODE_HEAD;
506
507 READ_BUF(sizeof(stateid_t));
508 sid->si_generation = be32_to_cpup(p++);
509 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
510
511 DECODE_TAIL;
512}
513
514static __be32
515nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
516{
517 DECODE_HEAD;
518
519 READ_BUF(4);
520 access->ac_req_access = be32_to_cpup(p++);
521
522 DECODE_TAIL;
523}
524
525static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
526{
527 DECODE_HEAD;
528 struct user_namespace *userns = nfsd_user_namespace(argp->rqstp);
529 u32 dummy, uid, gid;
530 char *machine_name;
531 int i;
532 int nr_secflavs;
533
534
535 READ_BUF(4);
536 nr_secflavs = be32_to_cpup(p++);
537 if (nr_secflavs)
538 cbs->flavor = (u32)(-1);
539 else
540
541 cbs->flavor = 0;
542 for (i = 0; i < nr_secflavs; ++i) {
543 READ_BUF(4);
544 dummy = be32_to_cpup(p++);
545 switch (dummy) {
546 case RPC_AUTH_NULL:
547
548 if (cbs->flavor == (u32)(-1))
549 cbs->flavor = RPC_AUTH_NULL;
550 break;
551 case RPC_AUTH_UNIX:
552 READ_BUF(8);
553
554 dummy = be32_to_cpup(p++);
555
556
557 dummy = be32_to_cpup(p++);
558 READ_BUF(dummy);
559 SAVEMEM(machine_name, dummy);
560
561
562 READ_BUF(8);
563 uid = be32_to_cpup(p++);
564 gid = be32_to_cpup(p++);
565
566
567 READ_BUF(4);
568 dummy = be32_to_cpup(p++);
569 READ_BUF(dummy * 4);
570 if (cbs->flavor == (u32)(-1)) {
571 kuid_t kuid = make_kuid(userns, uid);
572 kgid_t kgid = make_kgid(userns, gid);
573 if (uid_valid(kuid) && gid_valid(kgid)) {
574 cbs->uid = kuid;
575 cbs->gid = kgid;
576 cbs->flavor = RPC_AUTH_UNIX;
577 } else {
578 dprintk("RPC_AUTH_UNIX with invalid"
579 "uid or gid ignoring!\n");
580 }
581 }
582 break;
583 case RPC_AUTH_GSS:
584 dprintk("RPC_AUTH_GSS callback secflavor "
585 "not supported!\n");
586 READ_BUF(8);
587
588 dummy = be32_to_cpup(p++);
589
590 dummy = be32_to_cpup(p++);
591 READ_BUF(dummy);
592 p += XDR_QUADLEN(dummy);
593
594 READ_BUF(4);
595 dummy = be32_to_cpup(p++);
596 READ_BUF(dummy);
597 break;
598 default:
599 dprintk("Illegal callback secflavor\n");
600 return nfserr_inval;
601 }
602 }
603 DECODE_TAIL;
604}
605
606static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
607{
608 DECODE_HEAD;
609
610 READ_BUF(4);
611 bc->bc_cb_program = be32_to_cpup(p++);
612 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
613
614 DECODE_TAIL;
615}
616
617static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
618{
619 DECODE_HEAD;
620
621 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
622 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
623 bcts->dir = be32_to_cpup(p++);
624
625
626 DECODE_TAIL;
627}
628
629static __be32
630nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
631{
632 DECODE_HEAD;
633
634 READ_BUF(4);
635 close->cl_seqid = be32_to_cpup(p++);
636 return nfsd4_decode_stateid(argp, &close->cl_stateid);
637
638 DECODE_TAIL;
639}
640
641
642static __be32
643nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
644{
645 DECODE_HEAD;
646
647 READ_BUF(12);
648 p = xdr_decode_hyper(p, &commit->co_offset);
649 commit->co_count = be32_to_cpup(p++);
650
651 DECODE_TAIL;
652}
653
654static __be32
655nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
656{
657 DECODE_HEAD;
658
659 READ_BUF(4);
660 create->cr_type = be32_to_cpup(p++);
661 switch (create->cr_type) {
662 case NF4LNK:
663 READ_BUF(4);
664 create->cr_datalen = be32_to_cpup(p++);
665 READ_BUF(create->cr_datalen);
666 create->cr_data = svcxdr_dupstr(argp, p, create->cr_datalen);
667 if (!create->cr_data)
668 return nfserr_jukebox;
669 break;
670 case NF4BLK:
671 case NF4CHR:
672 READ_BUF(8);
673 create->cr_specdata1 = be32_to_cpup(p++);
674 create->cr_specdata2 = be32_to_cpup(p++);
675 break;
676 case NF4SOCK:
677 case NF4FIFO:
678 case NF4DIR:
679 default:
680 break;
681 }
682
683 READ_BUF(4);
684 create->cr_namelen = be32_to_cpup(p++);
685 READ_BUF(create->cr_namelen);
686 SAVEMEM(create->cr_name, create->cr_namelen);
687 if ((status = check_filename(create->cr_name, create->cr_namelen)))
688 return status;
689
690 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
691 &create->cr_acl, &create->cr_label,
692 &create->cr_umask);
693 if (status)
694 goto out;
695
696 DECODE_TAIL;
697}
698
699static inline __be32
700nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
701{
702 return nfsd4_decode_stateid(argp, &dr->dr_stateid);
703}
704
705static inline __be32
706nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
707{
708 return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
709}
710
711static __be32
712nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
713{
714 DECODE_HEAD;
715
716 READ_BUF(4);
717 link->li_namelen = be32_to_cpup(p++);
718 READ_BUF(link->li_namelen);
719 SAVEMEM(link->li_name, link->li_namelen);
720 if ((status = check_filename(link->li_name, link->li_namelen)))
721 return status;
722
723 DECODE_TAIL;
724}
725
726static __be32
727nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
728{
729 DECODE_HEAD;
730
731
732
733
734 READ_BUF(28);
735 lock->lk_type = be32_to_cpup(p++);
736 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
737 goto xdr_error;
738 lock->lk_reclaim = be32_to_cpup(p++);
739 p = xdr_decode_hyper(p, &lock->lk_offset);
740 p = xdr_decode_hyper(p, &lock->lk_length);
741 lock->lk_is_new = be32_to_cpup(p++);
742
743 if (lock->lk_is_new) {
744 READ_BUF(4);
745 lock->lk_new_open_seqid = be32_to_cpup(p++);
746 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
747 if (status)
748 return status;
749 READ_BUF(8 + sizeof(clientid_t));
750 lock->lk_new_lock_seqid = be32_to_cpup(p++);
751 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
752 lock->lk_new_owner.len = be32_to_cpup(p++);
753 READ_BUF(lock->lk_new_owner.len);
754 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
755 } else {
756 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
757 if (status)
758 return status;
759 READ_BUF(4);
760 lock->lk_old_lock_seqid = be32_to_cpup(p++);
761 }
762
763 DECODE_TAIL;
764}
765
766static __be32
767nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
768{
769 DECODE_HEAD;
770
771 READ_BUF(32);
772 lockt->lt_type = be32_to_cpup(p++);
773 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
774 goto xdr_error;
775 p = xdr_decode_hyper(p, &lockt->lt_offset);
776 p = xdr_decode_hyper(p, &lockt->lt_length);
777 COPYMEM(&lockt->lt_clientid, 8);
778 lockt->lt_owner.len = be32_to_cpup(p++);
779 READ_BUF(lockt->lt_owner.len);
780 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
781
782 DECODE_TAIL;
783}
784
785static __be32
786nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
787{
788 DECODE_HEAD;
789
790 READ_BUF(8);
791 locku->lu_type = be32_to_cpup(p++);
792 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
793 goto xdr_error;
794 locku->lu_seqid = be32_to_cpup(p++);
795 status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
796 if (status)
797 return status;
798 READ_BUF(16);
799 p = xdr_decode_hyper(p, &locku->lu_offset);
800 p = xdr_decode_hyper(p, &locku->lu_length);
801
802 DECODE_TAIL;
803}
804
805static __be32
806nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
807{
808 DECODE_HEAD;
809
810 READ_BUF(4);
811 lookup->lo_len = be32_to_cpup(p++);
812 READ_BUF(lookup->lo_len);
813 SAVEMEM(lookup->lo_name, lookup->lo_len);
814 if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
815 return status;
816
817 DECODE_TAIL;
818}
819
820static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
821{
822 __be32 *p;
823 u32 w;
824
825 READ_BUF(4);
826 w = be32_to_cpup(p++);
827 *share_access = w & NFS4_SHARE_ACCESS_MASK;
828 *deleg_want = w & NFS4_SHARE_WANT_MASK;
829 if (deleg_when)
830 *deleg_when = w & NFS4_SHARE_WHEN_MASK;
831
832 switch (w & NFS4_SHARE_ACCESS_MASK) {
833 case NFS4_SHARE_ACCESS_READ:
834 case NFS4_SHARE_ACCESS_WRITE:
835 case NFS4_SHARE_ACCESS_BOTH:
836 break;
837 default:
838 return nfserr_bad_xdr;
839 }
840 w &= ~NFS4_SHARE_ACCESS_MASK;
841 if (!w)
842 return nfs_ok;
843 if (!argp->minorversion)
844 return nfserr_bad_xdr;
845 switch (w & NFS4_SHARE_WANT_MASK) {
846 case NFS4_SHARE_WANT_NO_PREFERENCE:
847 case NFS4_SHARE_WANT_READ_DELEG:
848 case NFS4_SHARE_WANT_WRITE_DELEG:
849 case NFS4_SHARE_WANT_ANY_DELEG:
850 case NFS4_SHARE_WANT_NO_DELEG:
851 case NFS4_SHARE_WANT_CANCEL:
852 break;
853 default:
854 return nfserr_bad_xdr;
855 }
856 w &= ~NFS4_SHARE_WANT_MASK;
857 if (!w)
858 return nfs_ok;
859
860 if (!deleg_when)
861 return nfserr_inval;
862 switch (w) {
863 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
864 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
865 case (NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL |
866 NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED):
867 return nfs_ok;
868 }
869xdr_error:
870 return nfserr_bad_xdr;
871}
872
873static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
874{
875 __be32 *p;
876
877 READ_BUF(4);
878 *x = be32_to_cpup(p++);
879
880 if (*x & ~NFS4_SHARE_DENY_BOTH)
881 return nfserr_bad_xdr;
882 return nfs_ok;
883xdr_error:
884 return nfserr_bad_xdr;
885}
886
887static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
888{
889 __be32 *p;
890
891 READ_BUF(4);
892 o->len = be32_to_cpup(p++);
893
894 if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT)
895 return nfserr_bad_xdr;
896
897 READ_BUF(o->len);
898 SAVEMEM(o->data, o->len);
899 return nfs_ok;
900xdr_error:
901 return nfserr_bad_xdr;
902}
903
904static __be32
905nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
906{
907 DECODE_HEAD;
908 u32 dummy;
909
910 memset(open->op_bmval, 0, sizeof(open->op_bmval));
911 open->op_iattr.ia_valid = 0;
912 open->op_openowner = NULL;
913
914 open->op_xdr_error = 0;
915
916 READ_BUF(4);
917 open->op_seqid = be32_to_cpup(p++);
918
919 status = nfsd4_decode_share_access(argp, &open->op_share_access,
920 &open->op_deleg_want, &dummy);
921 if (status)
922 goto xdr_error;
923 status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
924 if (status)
925 goto xdr_error;
926 READ_BUF(sizeof(clientid_t));
927 COPYMEM(&open->op_clientid, sizeof(clientid_t));
928 status = nfsd4_decode_opaque(argp, &open->op_owner);
929 if (status)
930 goto xdr_error;
931 READ_BUF(4);
932 open->op_create = be32_to_cpup(p++);
933 switch (open->op_create) {
934 case NFS4_OPEN_NOCREATE:
935 break;
936 case NFS4_OPEN_CREATE:
937 READ_BUF(4);
938 open->op_createmode = be32_to_cpup(p++);
939 switch (open->op_createmode) {
940 case NFS4_CREATE_UNCHECKED:
941 case NFS4_CREATE_GUARDED:
942 status = nfsd4_decode_fattr(argp, open->op_bmval,
943 &open->op_iattr, &open->op_acl, &open->op_label,
944 &open->op_umask);
945 if (status)
946 goto out;
947 break;
948 case NFS4_CREATE_EXCLUSIVE:
949 READ_BUF(NFS4_VERIFIER_SIZE);
950 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
951 break;
952 case NFS4_CREATE_EXCLUSIVE4_1:
953 if (argp->minorversion < 1)
954 goto xdr_error;
955 READ_BUF(NFS4_VERIFIER_SIZE);
956 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
957 status = nfsd4_decode_fattr(argp, open->op_bmval,
958 &open->op_iattr, &open->op_acl, &open->op_label,
959 &open->op_umask);
960 if (status)
961 goto out;
962 break;
963 default:
964 goto xdr_error;
965 }
966 break;
967 default:
968 goto xdr_error;
969 }
970
971
972 READ_BUF(4);
973 open->op_claim_type = be32_to_cpup(p++);
974 switch (open->op_claim_type) {
975 case NFS4_OPEN_CLAIM_NULL:
976 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
977 READ_BUF(4);
978 open->op_fname.len = be32_to_cpup(p++);
979 READ_BUF(open->op_fname.len);
980 SAVEMEM(open->op_fname.data, open->op_fname.len);
981 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
982 return status;
983 break;
984 case NFS4_OPEN_CLAIM_PREVIOUS:
985 READ_BUF(4);
986 open->op_delegate_type = be32_to_cpup(p++);
987 break;
988 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
989 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
990 if (status)
991 return status;
992 READ_BUF(4);
993 open->op_fname.len = be32_to_cpup(p++);
994 READ_BUF(open->op_fname.len);
995 SAVEMEM(open->op_fname.data, open->op_fname.len);
996 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
997 return status;
998 break;
999 case NFS4_OPEN_CLAIM_FH:
1000 case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
1001 if (argp->minorversion < 1)
1002 goto xdr_error;
1003
1004 break;
1005 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
1006 if (argp->minorversion < 1)
1007 goto xdr_error;
1008 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
1009 if (status)
1010 return status;
1011 break;
1012 default:
1013 goto xdr_error;
1014 }
1015
1016 DECODE_TAIL;
1017}
1018
1019static __be32
1020nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
1021{
1022 DECODE_HEAD;
1023
1024 if (argp->minorversion >= 1)
1025 return nfserr_notsupp;
1026
1027 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
1028 if (status)
1029 return status;
1030 READ_BUF(4);
1031 open_conf->oc_seqid = be32_to_cpup(p++);
1032
1033 DECODE_TAIL;
1034}
1035
1036static __be32
1037nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
1038{
1039 DECODE_HEAD;
1040
1041 status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
1042 if (status)
1043 return status;
1044 READ_BUF(4);
1045 open_down->od_seqid = be32_to_cpup(p++);
1046 status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
1047 &open_down->od_deleg_want, NULL);
1048 if (status)
1049 return status;
1050 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
1051 if (status)
1052 return status;
1053 DECODE_TAIL;
1054}
1055
1056static __be32
1057nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
1058{
1059 DECODE_HEAD;
1060
1061 READ_BUF(4);
1062 putfh->pf_fhlen = be32_to_cpup(p++);
1063 if (putfh->pf_fhlen > NFS4_FHSIZE)
1064 goto xdr_error;
1065 READ_BUF(putfh->pf_fhlen);
1066 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
1067
1068 DECODE_TAIL;
1069}
1070
1071static __be32
1072nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p)
1073{
1074 if (argp->minorversion == 0)
1075 return nfs_ok;
1076 return nfserr_notsupp;
1077}
1078
1079static __be32
1080nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
1081{
1082 DECODE_HEAD;
1083
1084 status = nfsd4_decode_stateid(argp, &read->rd_stateid);
1085 if (status)
1086 return status;
1087 READ_BUF(12);
1088 p = xdr_decode_hyper(p, &read->rd_offset);
1089 read->rd_length = be32_to_cpup(p++);
1090
1091 DECODE_TAIL;
1092}
1093
1094static __be32
1095nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
1096{
1097 DECODE_HEAD;
1098
1099 READ_BUF(24);
1100 p = xdr_decode_hyper(p, &readdir->rd_cookie);
1101 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
1102 readdir->rd_dircount = be32_to_cpup(p++);
1103 readdir->rd_maxcount = be32_to_cpup(p++);
1104 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
1105 goto out;
1106
1107 DECODE_TAIL;
1108}
1109
1110static __be32
1111nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
1112{
1113 DECODE_HEAD;
1114
1115 READ_BUF(4);
1116 remove->rm_namelen = be32_to_cpup(p++);
1117 READ_BUF(remove->rm_namelen);
1118 SAVEMEM(remove->rm_name, remove->rm_namelen);
1119 if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
1120 return status;
1121
1122 DECODE_TAIL;
1123}
1124
1125static __be32
1126nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
1127{
1128 DECODE_HEAD;
1129
1130 READ_BUF(4);
1131 rename->rn_snamelen = be32_to_cpup(p++);
1132 READ_BUF(rename->rn_snamelen);
1133 SAVEMEM(rename->rn_sname, rename->rn_snamelen);
1134 READ_BUF(4);
1135 rename->rn_tnamelen = be32_to_cpup(p++);
1136 READ_BUF(rename->rn_tnamelen);
1137 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
1138 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
1139 return status;
1140 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
1141 return status;
1142
1143 DECODE_TAIL;
1144}
1145
1146static __be32
1147nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
1148{
1149 DECODE_HEAD;
1150
1151 if (argp->minorversion >= 1)
1152 return nfserr_notsupp;
1153
1154 READ_BUF(sizeof(clientid_t));
1155 COPYMEM(clientid, sizeof(clientid_t));
1156
1157 DECODE_TAIL;
1158}
1159
1160static __be32
1161nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
1162 struct nfsd4_secinfo *secinfo)
1163{
1164 DECODE_HEAD;
1165
1166 READ_BUF(4);
1167 secinfo->si_namelen = be32_to_cpup(p++);
1168 READ_BUF(secinfo->si_namelen);
1169 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
1170 status = check_filename(secinfo->si_name, secinfo->si_namelen);
1171 if (status)
1172 return status;
1173 DECODE_TAIL;
1174}
1175
1176static __be32
1177nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
1178 struct nfsd4_secinfo_no_name *sin)
1179{
1180 DECODE_HEAD;
1181
1182 READ_BUF(4);
1183 sin->sin_style = be32_to_cpup(p++);
1184 DECODE_TAIL;
1185}
1186
1187static __be32
1188nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
1189{
1190 __be32 status;
1191
1192 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
1193 if (status)
1194 return status;
1195 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
1196 &setattr->sa_acl, &setattr->sa_label, NULL);
1197}
1198
1199static __be32
1200nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
1201{
1202 DECODE_HEAD;
1203
1204 if (argp->minorversion >= 1)
1205 return nfserr_notsupp;
1206
1207 READ_BUF(NFS4_VERIFIER_SIZE);
1208 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
1209
1210 status = nfsd4_decode_opaque(argp, &setclientid->se_name);
1211 if (status)
1212 return nfserr_bad_xdr;
1213 READ_BUF(8);
1214 setclientid->se_callback_prog = be32_to_cpup(p++);
1215 setclientid->se_callback_netid_len = be32_to_cpup(p++);
1216 READ_BUF(setclientid->se_callback_netid_len);
1217 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
1218 READ_BUF(4);
1219 setclientid->se_callback_addr_len = be32_to_cpup(p++);
1220
1221 READ_BUF(setclientid->se_callback_addr_len);
1222 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
1223 READ_BUF(4);
1224 setclientid->se_callback_ident = be32_to_cpup(p++);
1225
1226 DECODE_TAIL;
1227}
1228
1229static __be32
1230nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
1231{
1232 DECODE_HEAD;
1233
1234 if (argp->minorversion >= 1)
1235 return nfserr_notsupp;
1236
1237 READ_BUF(8 + NFS4_VERIFIER_SIZE);
1238 COPYMEM(&scd_c->sc_clientid, 8);
1239 COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
1240
1241 DECODE_TAIL;
1242}
1243
1244
1245static __be32
1246nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
1247{
1248 DECODE_HEAD;
1249
1250 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
1251 goto out;
1252
1253
1254
1255
1256 READ_BUF(4);
1257 verify->ve_attrlen = be32_to_cpup(p++);
1258 READ_BUF(verify->ve_attrlen);
1259 SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
1260
1261 DECODE_TAIL;
1262}
1263
1264static __be32
1265nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1266{
1267 int avail;
1268 int len;
1269 DECODE_HEAD;
1270
1271 status = nfsd4_decode_stateid(argp, &write->wr_stateid);
1272 if (status)
1273 return status;
1274 READ_BUF(16);
1275 p = xdr_decode_hyper(p, &write->wr_offset);
1276 write->wr_stable_how = be32_to_cpup(p++);
1277 if (write->wr_stable_how > NFS_FILE_SYNC)
1278 goto xdr_error;
1279 write->wr_buflen = be32_to_cpup(p++);
1280
1281
1282
1283
1284
1285 avail = (char*)argp->end - (char*)argp->p;
1286 if (avail + argp->pagelen < write->wr_buflen) {
1287 dprintk("NFSD: xdr error (%s:%d)\n",
1288 __FILE__, __LINE__);
1289 goto xdr_error;
1290 }
1291 write->wr_head.iov_base = p;
1292 write->wr_head.iov_len = avail;
1293 write->wr_pagelist = argp->pagelist;
1294
1295 len = XDR_QUADLEN(write->wr_buflen) << 2;
1296 if (len >= avail) {
1297 int pages;
1298
1299 len -= avail;
1300
1301 pages = len >> PAGE_SHIFT;
1302 argp->pagelist += pages;
1303 argp->pagelen -= pages * PAGE_SIZE;
1304 len -= pages * PAGE_SIZE;
1305
1306 next_decode_page(argp);
1307 }
1308 argp->p += XDR_QUADLEN(len);
1309
1310 DECODE_TAIL;
1311}
1312
1313static __be32
1314nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
1315{
1316 DECODE_HEAD;
1317
1318 if (argp->minorversion >= 1)
1319 return nfserr_notsupp;
1320
1321 READ_BUF(12);
1322 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
1323 rlockowner->rl_owner.len = be32_to_cpup(p++);
1324 READ_BUF(rlockowner->rl_owner.len);
1325 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
1326
1327 if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
1328 return nfserr_inval;
1329 DECODE_TAIL;
1330}
1331
1332static __be32
1333nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
1334 struct nfsd4_exchange_id *exid)
1335{
1336 int dummy, tmp;
1337 DECODE_HEAD;
1338
1339 READ_BUF(NFS4_VERIFIER_SIZE);
1340 COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
1341
1342 status = nfsd4_decode_opaque(argp, &exid->clname);
1343 if (status)
1344 return nfserr_bad_xdr;
1345
1346 READ_BUF(4);
1347 exid->flags = be32_to_cpup(p++);
1348
1349
1350 READ_BUF(4);
1351 exid->spa_how = be32_to_cpup(p++);
1352 switch (exid->spa_how) {
1353 case SP4_NONE:
1354 break;
1355 case SP4_MACH_CRED:
1356
1357 status = nfsd4_decode_bitmap(argp,
1358 exid->spo_must_enforce);
1359 if (status)
1360 goto out;
1361
1362 status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
1363 if (status)
1364 goto out;
1365 break;
1366 case SP4_SSV:
1367
1368 READ_BUF(4);
1369 dummy = be32_to_cpup(p++);
1370 READ_BUF(dummy * 4);
1371 p += dummy;
1372
1373 READ_BUF(4);
1374 dummy = be32_to_cpup(p++);
1375 READ_BUF(dummy * 4);
1376 p += dummy;
1377
1378
1379 READ_BUF(4);
1380 tmp = be32_to_cpup(p++);
1381 while (tmp--) {
1382 READ_BUF(4);
1383 dummy = be32_to_cpup(p++);
1384 READ_BUF(dummy);
1385 p += XDR_QUADLEN(dummy);
1386 }
1387
1388
1389 READ_BUF(4);
1390 tmp = be32_to_cpup(p++);
1391 while (tmp--) {
1392 READ_BUF(4);
1393 dummy = be32_to_cpup(p++);
1394 READ_BUF(dummy);
1395 p += XDR_QUADLEN(dummy);
1396 }
1397
1398
1399 READ_BUF(8);
1400 break;
1401 default:
1402 goto xdr_error;
1403 }
1404
1405 READ_BUF(4);
1406 dummy = be32_to_cpup(p++);
1407
1408 if (dummy > 1)
1409 goto xdr_error;
1410
1411 if (dummy == 1) {
1412 status = nfsd4_decode_opaque(argp, &exid->nii_domain);
1413 if (status)
1414 goto xdr_error;
1415
1416
1417 status = nfsd4_decode_opaque(argp, &exid->nii_name);
1418 if (status)
1419 goto xdr_error;
1420
1421
1422 status = nfsd4_decode_time(argp, &exid->nii_time);
1423 if (status)
1424 goto xdr_error;
1425 }
1426 DECODE_TAIL;
1427}
1428
1429static __be32
1430nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1431 struct nfsd4_create_session *sess)
1432{
1433 DECODE_HEAD;
1434
1435 READ_BUF(16);
1436 COPYMEM(&sess->clientid, 8);
1437 sess->seqid = be32_to_cpup(p++);
1438 sess->flags = be32_to_cpup(p++);
1439
1440
1441 READ_BUF(28);
1442 p++;
1443 sess->fore_channel.maxreq_sz = be32_to_cpup(p++);
1444 sess->fore_channel.maxresp_sz = be32_to_cpup(p++);
1445 sess->fore_channel.maxresp_cached = be32_to_cpup(p++);
1446 sess->fore_channel.maxops = be32_to_cpup(p++);
1447 sess->fore_channel.maxreqs = be32_to_cpup(p++);
1448 sess->fore_channel.nr_rdma_attrs = be32_to_cpup(p++);
1449 if (sess->fore_channel.nr_rdma_attrs == 1) {
1450 READ_BUF(4);
1451 sess->fore_channel.rdma_attrs = be32_to_cpup(p++);
1452 } else if (sess->fore_channel.nr_rdma_attrs > 1) {
1453 dprintk("Too many fore channel attr bitmaps!\n");
1454 goto xdr_error;
1455 }
1456
1457
1458 READ_BUF(28);
1459 p++;
1460 sess->back_channel.maxreq_sz = be32_to_cpup(p++);
1461 sess->back_channel.maxresp_sz = be32_to_cpup(p++);
1462 sess->back_channel.maxresp_cached = be32_to_cpup(p++);
1463 sess->back_channel.maxops = be32_to_cpup(p++);
1464 sess->back_channel.maxreqs = be32_to_cpup(p++);
1465 sess->back_channel.nr_rdma_attrs = be32_to_cpup(p++);
1466 if (sess->back_channel.nr_rdma_attrs == 1) {
1467 READ_BUF(4);
1468 sess->back_channel.rdma_attrs = be32_to_cpup(p++);
1469 } else if (sess->back_channel.nr_rdma_attrs > 1) {
1470 dprintk("Too many back channel attr bitmaps!\n");
1471 goto xdr_error;
1472 }
1473
1474 READ_BUF(4);
1475 sess->callback_prog = be32_to_cpup(p++);
1476 nfsd4_decode_cb_sec(argp, &sess->cb_sec);
1477 DECODE_TAIL;
1478}
1479
1480static __be32
1481nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1482 struct nfsd4_destroy_session *destroy_session)
1483{
1484 DECODE_HEAD;
1485 READ_BUF(NFS4_MAX_SESSIONID_LEN);
1486 COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1487
1488 DECODE_TAIL;
1489}
1490
1491static __be32
1492nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
1493 struct nfsd4_free_stateid *free_stateid)
1494{
1495 DECODE_HEAD;
1496
1497 READ_BUF(sizeof(stateid_t));
1498 free_stateid->fr_stateid.si_generation = be32_to_cpup(p++);
1499 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
1500
1501 DECODE_TAIL;
1502}
1503
1504static __be32
1505nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1506 struct nfsd4_sequence *seq)
1507{
1508 DECODE_HEAD;
1509
1510 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1511 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1512 seq->seqid = be32_to_cpup(p++);
1513 seq->slotid = be32_to_cpup(p++);
1514 seq->maxslots = be32_to_cpup(p++);
1515 seq->cachethis = be32_to_cpup(p++);
1516
1517 DECODE_TAIL;
1518}
1519
1520static __be32
1521nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1522{
1523 int i;
1524 __be32 *p, status;
1525 struct nfsd4_test_stateid_id *stateid;
1526
1527 READ_BUF(4);
1528 test_stateid->ts_num_ids = ntohl(*p++);
1529
1530 INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
1531
1532 for (i = 0; i < test_stateid->ts_num_ids; i++) {
1533 stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));
1534 if (!stateid) {
1535 status = nfserrno(-ENOMEM);
1536 goto out;
1537 }
1538
1539 INIT_LIST_HEAD(&stateid->ts_id_list);
1540 list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
1541
1542 status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
1543 if (status)
1544 goto out;
1545 }
1546
1547 status = 0;
1548out:
1549 return status;
1550xdr_error:
1551 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
1552 status = nfserr_bad_xdr;
1553 goto out;
1554}
1555
1556static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc)
1557{
1558 DECODE_HEAD;
1559
1560 READ_BUF(8);
1561 COPYMEM(&dc->clientid, 8);
1562
1563 DECODE_TAIL;
1564}
1565
1566static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1567{
1568 DECODE_HEAD;
1569
1570 READ_BUF(4);
1571 rc->rca_one_fs = be32_to_cpup(p++);
1572
1573 DECODE_TAIL;
1574}
1575
1576#ifdef CONFIG_NFSD_PNFS
1577static __be32
1578nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
1579 struct nfsd4_getdeviceinfo *gdev)
1580{
1581 DECODE_HEAD;
1582 u32 num, i;
1583
1584 READ_BUF(sizeof(struct nfsd4_deviceid) + 3 * 4);
1585 COPYMEM(&gdev->gd_devid, sizeof(struct nfsd4_deviceid));
1586 gdev->gd_layout_type = be32_to_cpup(p++);
1587 gdev->gd_maxcount = be32_to_cpup(p++);
1588 num = be32_to_cpup(p++);
1589 if (num) {
1590 if (num > 1000)
1591 goto xdr_error;
1592 READ_BUF(4 * num);
1593 gdev->gd_notify_types = be32_to_cpup(p++);
1594 for (i = 1; i < num; i++) {
1595 if (be32_to_cpup(p++)) {
1596 status = nfserr_inval;
1597 goto out;
1598 }
1599 }
1600 }
1601 DECODE_TAIL;
1602}
1603
1604static __be32
1605nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
1606 struct nfsd4_layoutget *lgp)
1607{
1608 DECODE_HEAD;
1609
1610 READ_BUF(36);
1611 lgp->lg_signal = be32_to_cpup(p++);
1612 lgp->lg_layout_type = be32_to_cpup(p++);
1613 lgp->lg_seg.iomode = be32_to_cpup(p++);
1614 p = xdr_decode_hyper(p, &lgp->lg_seg.offset);
1615 p = xdr_decode_hyper(p, &lgp->lg_seg.length);
1616 p = xdr_decode_hyper(p, &lgp->lg_minlength);
1617
1618 status = nfsd4_decode_stateid(argp, &lgp->lg_sid);
1619 if (status)
1620 return status;
1621
1622 READ_BUF(4);
1623 lgp->lg_maxcount = be32_to_cpup(p++);
1624
1625 DECODE_TAIL;
1626}
1627
1628static __be32
1629nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
1630 struct nfsd4_layoutcommit *lcp)
1631{
1632 DECODE_HEAD;
1633 u32 timechange;
1634
1635 READ_BUF(20);
1636 p = xdr_decode_hyper(p, &lcp->lc_seg.offset);
1637 p = xdr_decode_hyper(p, &lcp->lc_seg.length);
1638 lcp->lc_reclaim = be32_to_cpup(p++);
1639
1640 status = nfsd4_decode_stateid(argp, &lcp->lc_sid);
1641 if (status)
1642 return status;
1643
1644 READ_BUF(4);
1645 lcp->lc_newoffset = be32_to_cpup(p++);
1646 if (lcp->lc_newoffset) {
1647 READ_BUF(8);
1648 p = xdr_decode_hyper(p, &lcp->lc_last_wr);
1649 } else
1650 lcp->lc_last_wr = 0;
1651 READ_BUF(4);
1652 timechange = be32_to_cpup(p++);
1653 if (timechange) {
1654 status = nfsd4_decode_time(argp, &lcp->lc_mtime);
1655 if (status)
1656 return status;
1657 } else {
1658 lcp->lc_mtime.tv_nsec = UTIME_NOW;
1659 }
1660 READ_BUF(8);
1661 lcp->lc_layout_type = be32_to_cpup(p++);
1662
1663
1664
1665
1666
1667 lcp->lc_up_len = be32_to_cpup(p++);
1668 if (lcp->lc_up_len > 0) {
1669 READ_BUF(lcp->lc_up_len);
1670 READMEM(lcp->lc_up_layout, lcp->lc_up_len);
1671 }
1672
1673 DECODE_TAIL;
1674}
1675
1676static __be32
1677nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
1678 struct nfsd4_layoutreturn *lrp)
1679{
1680 DECODE_HEAD;
1681
1682 READ_BUF(16);
1683 lrp->lr_reclaim = be32_to_cpup(p++);
1684 lrp->lr_layout_type = be32_to_cpup(p++);
1685 lrp->lr_seg.iomode = be32_to_cpup(p++);
1686 lrp->lr_return_type = be32_to_cpup(p++);
1687 if (lrp->lr_return_type == RETURN_FILE) {
1688 READ_BUF(16);
1689 p = xdr_decode_hyper(p, &lrp->lr_seg.offset);
1690 p = xdr_decode_hyper(p, &lrp->lr_seg.length);
1691
1692 status = nfsd4_decode_stateid(argp, &lrp->lr_sid);
1693 if (status)
1694 return status;
1695
1696 READ_BUF(4);
1697 lrp->lrf_body_len = be32_to_cpup(p++);
1698 if (lrp->lrf_body_len > 0) {
1699 READ_BUF(lrp->lrf_body_len);
1700 READMEM(lrp->lrf_body, lrp->lrf_body_len);
1701 }
1702 } else {
1703 lrp->lr_seg.offset = 0;
1704 lrp->lr_seg.length = NFS4_MAX_UINT64;
1705 }
1706
1707 DECODE_TAIL;
1708}
1709#endif
1710
1711static __be32
1712nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
1713 struct nfsd4_fallocate *fallocate)
1714{
1715 DECODE_HEAD;
1716
1717 status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid);
1718 if (status)
1719 return status;
1720
1721 READ_BUF(16);
1722 p = xdr_decode_hyper(p, &fallocate->falloc_offset);
1723 xdr_decode_hyper(p, &fallocate->falloc_length);
1724
1725 DECODE_TAIL;
1726}
1727
1728static __be32
1729nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
1730{
1731 DECODE_HEAD;
1732
1733 status = nfsd4_decode_stateid(argp, &clone->cl_src_stateid);
1734 if (status)
1735 return status;
1736 status = nfsd4_decode_stateid(argp, &clone->cl_dst_stateid);
1737 if (status)
1738 return status;
1739
1740 READ_BUF(8 + 8 + 8);
1741 p = xdr_decode_hyper(p, &clone->cl_src_pos);
1742 p = xdr_decode_hyper(p, &clone->cl_dst_pos);
1743 p = xdr_decode_hyper(p, &clone->cl_count);
1744 DECODE_TAIL;
1745}
1746
1747static __be32
1748nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
1749{
1750 DECODE_HEAD;
1751
1752 status = nfsd4_decode_stateid(argp, ©->cp_src_stateid);
1753 if (status)
1754 return status;
1755 status = nfsd4_decode_stateid(argp, ©->cp_dst_stateid);
1756 if (status)
1757 return status;
1758
1759 READ_BUF(8 + 8 + 8 + 4 + 4 + 4);
1760 p = xdr_decode_hyper(p, ©->cp_src_pos);
1761 p = xdr_decode_hyper(p, ©->cp_dst_pos);
1762 p = xdr_decode_hyper(p, ©->cp_count);
1763 p++;
1764 copy->cp_synchronous = be32_to_cpup(p++);
1765
1766
1767 DECODE_TAIL;
1768}
1769
1770static __be32
1771nfsd4_decode_offload_status(struct nfsd4_compoundargs *argp,
1772 struct nfsd4_offload_status *os)
1773{
1774 return nfsd4_decode_stateid(argp, &os->stateid);
1775}
1776
1777static __be32
1778nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
1779{
1780 DECODE_HEAD;
1781
1782 status = nfsd4_decode_stateid(argp, &seek->seek_stateid);
1783 if (status)
1784 return status;
1785
1786 READ_BUF(8 + 4);
1787 p = xdr_decode_hyper(p, &seek->seek_offset);
1788 seek->seek_whence = be32_to_cpup(p);
1789
1790 DECODE_TAIL;
1791}
1792
1793static __be32
1794nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
1795{
1796 return nfs_ok;
1797}
1798
1799static __be32
1800nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
1801{
1802 return nfserr_notsupp;
1803}
1804
1805typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1806
1807static const nfsd4_dec nfsd4_dec_ops[] = {
1808 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1809 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1810 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1811 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1812 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1813 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1814 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1815 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1816 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1817 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1818 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1819 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1820 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1821 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1822 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1823 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1824 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1825 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm,
1826 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1827 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
1828 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_putpubfh,
1829 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1830 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1831 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1832 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1833 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1834 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1835 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew,
1836 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1837 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1838 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1839 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1840 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid,
1841 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
1842 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1843 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1844 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner,
1845
1846
1847 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
1848 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
1849 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1850 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1851 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
1852 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_free_stateid,
1853 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1854#ifdef CONFIG_NFSD_PNFS
1855 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_getdeviceinfo,
1856 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1857 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_layoutcommit,
1858 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_layoutget,
1859 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_layoutreturn,
1860#else
1861 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
1862 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1863 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
1864 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
1865 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
1866#endif
1867 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
1868 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1869 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
1870 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid,
1871 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
1872 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_destroy_clientid,
1873 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,
1874
1875
1876 [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
1877 [OP_COPY] = (nfsd4_dec)nfsd4_decode_copy,
1878 [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp,
1879 [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
1880 [OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp,
1881 [OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp,
1882 [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
1883 [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_offload_status,
1884 [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_offload_status,
1885 [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp,
1886 [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,
1887 [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,
1888 [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,
1889};
1890
1891static inline bool
1892nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
1893{
1894 if (op->opnum < FIRST_NFS4_OP)
1895 return false;
1896 else if (argp->minorversion == 0 && op->opnum > LAST_NFS40_OP)
1897 return false;
1898 else if (argp->minorversion == 1 && op->opnum > LAST_NFS41_OP)
1899 return false;
1900 else if (argp->minorversion == 2 && op->opnum > LAST_NFS42_OP)
1901 return false;
1902 return true;
1903}
1904
1905static __be32
1906nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1907{
1908 DECODE_HEAD;
1909 struct nfsd4_op *op;
1910 bool cachethis = false;
1911 int auth_slack= argp->rqstp->rq_auth_slack;
1912 int max_reply = auth_slack + 8;
1913 int readcount = 0;
1914 int readbytes = 0;
1915 int i;
1916
1917 READ_BUF(4);
1918 argp->taglen = be32_to_cpup(p++);
1919 READ_BUF(argp->taglen);
1920 SAVEMEM(argp->tag, argp->taglen);
1921 READ_BUF(8);
1922 argp->minorversion = be32_to_cpup(p++);
1923 argp->opcnt = be32_to_cpup(p++);
1924 max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2);
1925
1926 if (argp->taglen > NFSD4_MAX_TAGLEN)
1927 goto xdr_error;
1928
1929
1930
1931
1932
1933 if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND)
1934 return 0;
1935
1936 if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
1937 argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1938 if (!argp->ops) {
1939 argp->ops = argp->iops;
1940 dprintk("nfsd: couldn't allocate room for COMPOUND\n");
1941 goto xdr_error;
1942 }
1943 }
1944
1945 if (argp->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
1946 argp->opcnt = 0;
1947
1948 for (i = 0; i < argp->opcnt; i++) {
1949 op = &argp->ops[i];
1950 op->replay = NULL;
1951
1952 READ_BUF(4);
1953 op->opnum = be32_to_cpup(p++);
1954
1955 if (nfsd4_opnum_in_range(argp, op))
1956 op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
1957 else {
1958 op->opnum = OP_ILLEGAL;
1959 op->status = nfserr_op_illegal;
1960 }
1961 op->opdesc = OPDESC(op);
1962
1963
1964
1965
1966 cachethis |= nfsd4_cache_this_op(op);
1967
1968 if (op->opnum == OP_READ) {
1969 readcount++;
1970 readbytes += nfsd4_max_reply(argp->rqstp, op);
1971 } else
1972 max_reply += nfsd4_max_reply(argp->rqstp, op);
1973
1974
1975
1976
1977
1978
1979 if (op->opnum == OP_LOCK || op->opnum == OP_LOCKT)
1980 max_reply += NFS4_OPAQUE_LIMIT;
1981
1982 if (op->status) {
1983 argp->opcnt = i+1;
1984 break;
1985 }
1986 }
1987
1988 if (argp->minorversion)
1989 cachethis = false;
1990 svc_reserve(argp->rqstp, max_reply + readbytes);
1991 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1992
1993 if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
1994 clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
1995
1996 DECODE_TAIL;
1997}
1998
1999static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
2000 struct svc_export *exp)
2001{
2002 if (exp->ex_flags & NFSEXP_V4ROOT) {
2003 *p++ = cpu_to_be32(convert_to_wallclock(exp->cd->flush_time));
2004 *p++ = 0;
2005 } else if (IS_I_VERSION(inode)) {
2006 p = xdr_encode_hyper(p, nfsd4_change_attribute(stat, inode));
2007 } else {
2008 *p++ = cpu_to_be32(stat->ctime.tv_sec);
2009 *p++ = cpu_to_be32(stat->ctime.tv_nsec);
2010 }
2011 return p;
2012}
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025static __be32 *encode_time_delta(__be32 *p, struct inode *inode)
2026{
2027 struct timespec ts;
2028 u32 ns;
2029
2030 ns = max_t(u32, NSEC_PER_SEC/HZ, inode->i_sb->s_time_gran);
2031 ts = ns_to_timespec(ns);
2032
2033 p = xdr_encode_hyper(p, ts.tv_sec);
2034 *p++ = cpu_to_be32(ts.tv_nsec);
2035
2036 return p;
2037}
2038
2039static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c)
2040{
2041 *p++ = cpu_to_be32(c->atomic);
2042 if (c->change_supported) {
2043 p = xdr_encode_hyper(p, c->before_change);
2044 p = xdr_encode_hyper(p, c->after_change);
2045 } else {
2046 *p++ = cpu_to_be32(c->before_ctime_sec);
2047 *p++ = cpu_to_be32(c->before_ctime_nsec);
2048 *p++ = cpu_to_be32(c->after_ctime_sec);
2049 *p++ = cpu_to_be32(c->after_ctime_nsec);
2050 }
2051 return p;
2052}
2053
2054
2055
2056
2057static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
2058 char *components, char esc_enter,
2059 char esc_exit)
2060{
2061 __be32 *p;
2062 __be32 pathlen;
2063 int pathlen_offset;
2064 int strlen, count=0;
2065 char *str, *end, *next;
2066
2067 dprintk("nfsd4_encode_components(%s)\n", components);
2068
2069 pathlen_offset = xdr->buf->len;
2070 p = xdr_reserve_space(xdr, 4);
2071 if (!p)
2072 return nfserr_resource;
2073 p++;
2074
2075 end = str = components;
2076 while (*end) {
2077 bool found_esc = false;
2078
2079
2080 if (*str == esc_enter) {
2081 for (; *end && (*end != esc_exit); end++)
2082 ;
2083 next = end + 1;
2084 if (*end && (!*next || *next == sep)) {
2085 str++;
2086 found_esc = true;
2087 }
2088 }
2089
2090 if (!found_esc)
2091 for (; *end && (*end != sep); end++)
2092 ;
2093
2094 strlen = end - str;
2095 if (strlen) {
2096 p = xdr_reserve_space(xdr, strlen + 4);
2097 if (!p)
2098 return nfserr_resource;
2099 p = xdr_encode_opaque(p, str, strlen);
2100 count++;
2101 }
2102 else
2103 end++;
2104 if (found_esc)
2105 end = next;
2106
2107 str = end;
2108 }
2109 pathlen = htonl(count);
2110 write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4);
2111 return 0;
2112}
2113
2114
2115
2116
2117static __be32 nfsd4_encode_components(struct xdr_stream *xdr, char sep,
2118 char *components)
2119{
2120 return nfsd4_encode_components_esc(xdr, sep, components, 0, 0);
2121}
2122
2123
2124
2125
2126static __be32 nfsd4_encode_fs_location4(struct xdr_stream *xdr,
2127 struct nfsd4_fs_location *location)
2128{
2129 __be32 status;
2130
2131 status = nfsd4_encode_components_esc(xdr, ':', location->hosts,
2132 '[', ']');
2133 if (status)
2134 return status;
2135 status = nfsd4_encode_components(xdr, '/', location->path);
2136 if (status)
2137 return status;
2138 return 0;
2139}
2140
2141
2142
2143
2144static __be32 nfsd4_encode_path(struct xdr_stream *xdr,
2145 const struct path *root,
2146 const struct path *path)
2147{
2148 struct path cur = *path;
2149 __be32 *p;
2150 struct dentry **components = NULL;
2151 unsigned int ncomponents = 0;
2152 __be32 err = nfserr_jukebox;
2153
2154 dprintk("nfsd4_encode_components(");
2155
2156 path_get(&cur);
2157
2158
2159
2160 for (;;) {
2161 if (path_equal(&cur, root))
2162 break;
2163 if (cur.dentry == cur.mnt->mnt_root) {
2164 if (follow_up(&cur))
2165 continue;
2166 goto out_free;
2167 }
2168 if ((ncomponents & 15) == 0) {
2169 struct dentry **new;
2170 new = krealloc(components,
2171 sizeof(*new) * (ncomponents + 16),
2172 GFP_KERNEL);
2173 if (!new)
2174 goto out_free;
2175 components = new;
2176 }
2177 components[ncomponents++] = cur.dentry;
2178 cur.dentry = dget_parent(cur.dentry);
2179 }
2180 err = nfserr_resource;
2181 p = xdr_reserve_space(xdr, 4);
2182 if (!p)
2183 goto out_free;
2184 *p++ = cpu_to_be32(ncomponents);
2185
2186 while (ncomponents) {
2187 struct dentry *dentry = components[ncomponents - 1];
2188 unsigned int len;
2189
2190 spin_lock(&dentry->d_lock);
2191 len = dentry->d_name.len;
2192 p = xdr_reserve_space(xdr, len + 4);
2193 if (!p) {
2194 spin_unlock(&dentry->d_lock);
2195 goto out_free;
2196 }
2197 p = xdr_encode_opaque(p, dentry->d_name.name, len);
2198 dprintk("/%pd", dentry);
2199 spin_unlock(&dentry->d_lock);
2200 dput(dentry);
2201 ncomponents--;
2202 }
2203
2204 err = 0;
2205out_free:
2206 dprintk(")\n");
2207 while (ncomponents)
2208 dput(components[--ncomponents]);
2209 kfree(components);
2210 path_put(&cur);
2211 return err;
2212}
2213
2214static __be32 nfsd4_encode_fsloc_fsroot(struct xdr_stream *xdr,
2215 struct svc_rqst *rqstp, const struct path *path)
2216{
2217 struct svc_export *exp_ps;
2218 __be32 res;
2219
2220 exp_ps = rqst_find_fsidzero_export(rqstp);
2221 if (IS_ERR(exp_ps))
2222 return nfserrno(PTR_ERR(exp_ps));
2223 res = nfsd4_encode_path(xdr, &exp_ps->ex_path, path);
2224 exp_put(exp_ps);
2225 return res;
2226}
2227
2228
2229
2230
2231static __be32 nfsd4_encode_fs_locations(struct xdr_stream *xdr,
2232 struct svc_rqst *rqstp, struct svc_export *exp)
2233{
2234 __be32 status;
2235 int i;
2236 __be32 *p;
2237 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
2238
2239 status = nfsd4_encode_fsloc_fsroot(xdr, rqstp, &exp->ex_path);
2240 if (status)
2241 return status;
2242 p = xdr_reserve_space(xdr, 4);
2243 if (!p)
2244 return nfserr_resource;
2245 *p++ = cpu_to_be32(fslocs->locations_count);
2246 for (i=0; i<fslocs->locations_count; i++) {
2247 status = nfsd4_encode_fs_location4(xdr, &fslocs->locations[i]);
2248 if (status)
2249 return status;
2250 }
2251 return 0;
2252}
2253
2254static u32 nfs4_file_type(umode_t mode)
2255{
2256 switch (mode & S_IFMT) {
2257 case S_IFIFO: return NF4FIFO;
2258 case S_IFCHR: return NF4CHR;
2259 case S_IFDIR: return NF4DIR;
2260 case S_IFBLK: return NF4BLK;
2261 case S_IFLNK: return NF4LNK;
2262 case S_IFREG: return NF4REG;
2263 case S_IFSOCK: return NF4SOCK;
2264 default: return NF4BAD;
2265 };
2266}
2267
2268static inline __be32
2269nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2270 struct nfs4_ace *ace)
2271{
2272 if (ace->whotype != NFS4_ACL_WHO_NAMED)
2273 return nfs4_acl_write_who(xdr, ace->whotype);
2274 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
2275 return nfsd4_encode_group(xdr, rqstp, ace->who_gid);
2276 else
2277 return nfsd4_encode_user(xdr, rqstp, ace->who_uid);
2278}
2279
2280static inline __be32
2281nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types)
2282{
2283 __be32 *p;
2284 unsigned long i = hweight_long(layout_types);
2285
2286 p = xdr_reserve_space(xdr, 4 + 4 * i);
2287 if (!p)
2288 return nfserr_resource;
2289
2290 *p++ = cpu_to_be32(i);
2291
2292 for (i = LAYOUT_NFSV4_1_FILES; i < LAYOUT_TYPE_MAX; ++i)
2293 if (layout_types & (1 << i))
2294 *p++ = cpu_to_be32(i);
2295
2296 return 0;
2297}
2298
2299#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
2300 FATTR4_WORD0_RDATTR_ERROR)
2301#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
2302#define WORD2_ABSENT_FS_ATTRS 0
2303
2304#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2305static inline __be32
2306nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2307 void *context, int len)
2308{
2309 __be32 *p;
2310
2311 p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
2312 if (!p)
2313 return nfserr_resource;
2314
2315
2316
2317
2318
2319 *p++ = cpu_to_be32(0);
2320 *p++ = cpu_to_be32(0);
2321 p = xdr_encode_opaque(p, context, len);
2322 return 0;
2323}
2324#else
2325static inline __be32
2326nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2327 void *context, int len)
2328{ return 0; }
2329#endif
2330
2331static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32 *rdattr_err)
2332{
2333
2334 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
2335 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
2336 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
2337 *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
2338 *rdattr_err = NFSERR_MOVED;
2339 else
2340 return nfserr_moved;
2341 }
2342 *bmval0 &= WORD0_ABSENT_FS_ATTRS;
2343 *bmval1 &= WORD1_ABSENT_FS_ATTRS;
2344 *bmval2 &= WORD2_ABSENT_FS_ATTRS;
2345 return 0;
2346}
2347
2348
2349static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
2350{
2351 struct path path = exp->ex_path;
2352 int err;
2353
2354 path_get(&path);
2355 while (follow_up(&path)) {
2356 if (path.dentry != path.mnt->mnt_root)
2357 break;
2358 }
2359 err = vfs_getattr(&path, stat, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
2360 path_put(&path);
2361 return err;
2362}
2363
2364static __be32
2365nfsd4_encode_bitmap(struct xdr_stream *xdr, u32 bmval0, u32 bmval1, u32 bmval2)
2366{
2367 __be32 *p;
2368
2369 if (bmval2) {
2370 p = xdr_reserve_space(xdr, 16);
2371 if (!p)
2372 goto out_resource;
2373 *p++ = cpu_to_be32(3);
2374 *p++ = cpu_to_be32(bmval0);
2375 *p++ = cpu_to_be32(bmval1);
2376 *p++ = cpu_to_be32(bmval2);
2377 } else if (bmval1) {
2378 p = xdr_reserve_space(xdr, 12);
2379 if (!p)
2380 goto out_resource;
2381 *p++ = cpu_to_be32(2);
2382 *p++ = cpu_to_be32(bmval0);
2383 *p++ = cpu_to_be32(bmval1);
2384 } else {
2385 p = xdr_reserve_space(xdr, 8);
2386 if (!p)
2387 goto out_resource;
2388 *p++ = cpu_to_be32(1);
2389 *p++ = cpu_to_be32(bmval0);
2390 }
2391
2392 return 0;
2393out_resource:
2394 return nfserr_resource;
2395}
2396
2397
2398
2399
2400
2401static __be32
2402nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2403 struct svc_export *exp,
2404 struct dentry *dentry, u32 *bmval,
2405 struct svc_rqst *rqstp, int ignore_crossmnt)
2406{
2407 u32 bmval0 = bmval[0];
2408 u32 bmval1 = bmval[1];
2409 u32 bmval2 = bmval[2];
2410 struct kstat stat;
2411 struct svc_fh *tempfh = NULL;
2412 struct kstatfs statfs;
2413 __be32 *p;
2414 int starting_len = xdr->buf->len;
2415 int attrlen_offset;
2416 __be32 attrlen;
2417 u32 dummy;
2418 u64 dummy64;
2419 u32 rdattr_err = 0;
2420 __be32 status;
2421 int err;
2422 struct nfs4_acl *acl = NULL;
2423#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2424 void *context = NULL;
2425 int contextlen;
2426#endif
2427 bool contextsupport = false;
2428 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2429 u32 minorversion = resp->cstate.minorversion;
2430 struct path path = {
2431 .mnt = exp->ex_path.mnt,
2432 .dentry = dentry,
2433 };
2434 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2435
2436 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
2437 BUG_ON(!nfsd_attrs_supported(minorversion, bmval));
2438
2439 if (exp->ex_fslocs.migrated) {
2440 status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err);
2441 if (status)
2442 goto out;
2443 }
2444
2445 err = vfs_getattr(&path, &stat, STATX_BASIC_STATS, AT_STATX_SYNC_AS_STAT);
2446 if (err)
2447 goto out_nfserr;
2448 if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
2449 FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
2450 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
2451 FATTR4_WORD1_SPACE_TOTAL))) {
2452 err = vfs_statfs(&path, &statfs);
2453 if (err)
2454 goto out_nfserr;
2455 }
2456 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
2457 tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
2458 status = nfserr_jukebox;
2459 if (!tempfh)
2460 goto out;
2461 fh_init(tempfh, NFS4_FHSIZE);
2462 status = fh_compose(tempfh, exp, dentry, NULL);
2463 if (status)
2464 goto out;
2465 fhp = tempfh;
2466 }
2467 if (bmval0 & FATTR4_WORD0_ACL) {
2468 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
2469 if (err == -EOPNOTSUPP)
2470 bmval0 &= ~FATTR4_WORD0_ACL;
2471 else if (err == -EINVAL) {
2472 status = nfserr_attrnotsupp;
2473 goto out;
2474 } else if (err != 0)
2475 goto out_nfserr;
2476 }
2477
2478#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2479 if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
2480 bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
2481 if (exp->ex_flags & NFSEXP_SECURITY_LABEL)
2482 err = security_inode_getsecctx(d_inode(dentry),
2483 &context, &contextlen);
2484 else
2485 err = -EOPNOTSUPP;
2486 contextsupport = (err == 0);
2487 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2488 if (err == -EOPNOTSUPP)
2489 bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2490 else if (err)
2491 goto out_nfserr;
2492 }
2493 }
2494#endif
2495
2496 status = nfsd4_encode_bitmap(xdr, bmval0, bmval1, bmval2);
2497 if (status)
2498 goto out;
2499
2500 attrlen_offset = xdr->buf->len;
2501 p = xdr_reserve_space(xdr, 4);
2502 if (!p)
2503 goto out_resource;
2504 p++;
2505
2506 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
2507 u32 supp[3];
2508
2509 memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
2510
2511 if (!IS_POSIXACL(dentry->d_inode))
2512 supp[0] &= ~FATTR4_WORD0_ACL;
2513 if (!contextsupport)
2514 supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
2515 if (!supp[2]) {
2516 p = xdr_reserve_space(xdr, 12);
2517 if (!p)
2518 goto out_resource;
2519 *p++ = cpu_to_be32(2);
2520 *p++ = cpu_to_be32(supp[0]);
2521 *p++ = cpu_to_be32(supp[1]);
2522 } else {
2523 p = xdr_reserve_space(xdr, 16);
2524 if (!p)
2525 goto out_resource;
2526 *p++ = cpu_to_be32(3);
2527 *p++ = cpu_to_be32(supp[0]);
2528 *p++ = cpu_to_be32(supp[1]);
2529 *p++ = cpu_to_be32(supp[2]);
2530 }
2531 }
2532 if (bmval0 & FATTR4_WORD0_TYPE) {
2533 p = xdr_reserve_space(xdr, 4);
2534 if (!p)
2535 goto out_resource;
2536 dummy = nfs4_file_type(stat.mode);
2537 if (dummy == NF4BAD) {
2538 status = nfserr_serverfault;
2539 goto out;
2540 }
2541 *p++ = cpu_to_be32(dummy);
2542 }
2543 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
2544 p = xdr_reserve_space(xdr, 4);
2545 if (!p)
2546 goto out_resource;
2547 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
2548 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT);
2549 else
2550 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT|
2551 NFS4_FH_VOL_RENAME);
2552 }
2553 if (bmval0 & FATTR4_WORD0_CHANGE) {
2554 p = xdr_reserve_space(xdr, 8);
2555 if (!p)
2556 goto out_resource;
2557 p = encode_change(p, &stat, d_inode(dentry), exp);
2558 }
2559 if (bmval0 & FATTR4_WORD0_SIZE) {
2560 p = xdr_reserve_space(xdr, 8);
2561 if (!p)
2562 goto out_resource;
2563 p = xdr_encode_hyper(p, stat.size);
2564 }
2565 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
2566 p = xdr_reserve_space(xdr, 4);
2567 if (!p)
2568 goto out_resource;
2569 *p++ = cpu_to_be32(1);
2570 }
2571 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
2572 p = xdr_reserve_space(xdr, 4);
2573 if (!p)
2574 goto out_resource;
2575 *p++ = cpu_to_be32(1);
2576 }
2577 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
2578 p = xdr_reserve_space(xdr, 4);
2579 if (!p)
2580 goto out_resource;
2581 *p++ = cpu_to_be32(0);
2582 }
2583 if (bmval0 & FATTR4_WORD0_FSID) {
2584 p = xdr_reserve_space(xdr, 16);
2585 if (!p)
2586 goto out_resource;
2587 if (exp->ex_fslocs.migrated) {
2588 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MAJOR);
2589 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MINOR);
2590 } else switch(fsid_source(fhp)) {
2591 case FSIDSOURCE_FSID:
2592 p = xdr_encode_hyper(p, (u64)exp->ex_fsid);
2593 p = xdr_encode_hyper(p, (u64)0);
2594 break;
2595 case FSIDSOURCE_DEV:
2596 *p++ = cpu_to_be32(0);
2597 *p++ = cpu_to_be32(MAJOR(stat.dev));
2598 *p++ = cpu_to_be32(0);
2599 *p++ = cpu_to_be32(MINOR(stat.dev));
2600 break;
2601 case FSIDSOURCE_UUID:
2602 p = xdr_encode_opaque_fixed(p, exp->ex_uuid,
2603 EX_UUID_LEN);
2604 break;
2605 }
2606 }
2607 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
2608 p = xdr_reserve_space(xdr, 4);
2609 if (!p)
2610 goto out_resource;
2611 *p++ = cpu_to_be32(0);
2612 }
2613 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
2614 p = xdr_reserve_space(xdr, 4);
2615 if (!p)
2616 goto out_resource;
2617 *p++ = cpu_to_be32(nn->nfsd4_lease);
2618 }
2619 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
2620 p = xdr_reserve_space(xdr, 4);
2621 if (!p)
2622 goto out_resource;
2623 *p++ = cpu_to_be32(rdattr_err);
2624 }
2625 if (bmval0 & FATTR4_WORD0_ACL) {
2626 struct nfs4_ace *ace;
2627
2628 if (acl == NULL) {
2629 p = xdr_reserve_space(xdr, 4);
2630 if (!p)
2631 goto out_resource;
2632
2633 *p++ = cpu_to_be32(0);
2634 goto out_acl;
2635 }
2636 p = xdr_reserve_space(xdr, 4);
2637 if (!p)
2638 goto out_resource;
2639 *p++ = cpu_to_be32(acl->naces);
2640
2641 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
2642 p = xdr_reserve_space(xdr, 4*3);
2643 if (!p)
2644 goto out_resource;
2645 *p++ = cpu_to_be32(ace->type);
2646 *p++ = cpu_to_be32(ace->flag);
2647 *p++ = cpu_to_be32(ace->access_mask &
2648 NFS4_ACE_MASK_ALL);
2649 status = nfsd4_encode_aclname(xdr, rqstp, ace);
2650 if (status)
2651 goto out;
2652 }
2653 }
2654out_acl:
2655 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
2656 p = xdr_reserve_space(xdr, 4);
2657 if (!p)
2658 goto out_resource;
2659 *p++ = cpu_to_be32(IS_POSIXACL(dentry->d_inode) ?
2660 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
2661 }
2662 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
2663 p = xdr_reserve_space(xdr, 4);
2664 if (!p)
2665 goto out_resource;
2666 *p++ = cpu_to_be32(1);
2667 }
2668 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
2669 p = xdr_reserve_space(xdr, 4);
2670 if (!p)
2671 goto out_resource;
2672 *p++ = cpu_to_be32(0);
2673 }
2674 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
2675 p = xdr_reserve_space(xdr, 4);
2676 if (!p)
2677 goto out_resource;
2678 *p++ = cpu_to_be32(1);
2679 }
2680 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
2681 p = xdr_reserve_space(xdr, 4);
2682 if (!p)
2683 goto out_resource;
2684 *p++ = cpu_to_be32(1);
2685 }
2686 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
2687 p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4);
2688 if (!p)
2689 goto out_resource;
2690 p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base,
2691 fhp->fh_handle.fh_size);
2692 }
2693 if (bmval0 & FATTR4_WORD0_FILEID) {
2694 p = xdr_reserve_space(xdr, 8);
2695 if (!p)
2696 goto out_resource;
2697 p = xdr_encode_hyper(p, stat.ino);
2698 }
2699 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
2700 p = xdr_reserve_space(xdr, 8);
2701 if (!p)
2702 goto out_resource;
2703 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
2704 }
2705 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
2706 p = xdr_reserve_space(xdr, 8);
2707 if (!p)
2708 goto out_resource;
2709 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
2710 }
2711 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
2712 p = xdr_reserve_space(xdr, 8);
2713 if (!p)
2714 goto out_resource;
2715 p = xdr_encode_hyper(p, (u64) statfs.f_files);
2716 }
2717 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
2718 status = nfsd4_encode_fs_locations(xdr, rqstp, exp);
2719 if (status)
2720 goto out;
2721 }
2722 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
2723 p = xdr_reserve_space(xdr, 4);
2724 if (!p)
2725 goto out_resource;
2726 *p++ = cpu_to_be32(1);
2727 }
2728 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
2729 p = xdr_reserve_space(xdr, 8);
2730 if (!p)
2731 goto out_resource;
2732 p = xdr_encode_hyper(p, exp->ex_path.mnt->mnt_sb->s_maxbytes);
2733 }
2734 if (bmval0 & FATTR4_WORD0_MAXLINK) {
2735 p = xdr_reserve_space(xdr, 4);
2736 if (!p)
2737 goto out_resource;
2738 *p++ = cpu_to_be32(255);
2739 }
2740 if (bmval0 & FATTR4_WORD0_MAXNAME) {
2741 p = xdr_reserve_space(xdr, 4);
2742 if (!p)
2743 goto out_resource;
2744 *p++ = cpu_to_be32(statfs.f_namelen);
2745 }
2746 if (bmval0 & FATTR4_WORD0_MAXREAD) {
2747 p = xdr_reserve_space(xdr, 8);
2748 if (!p)
2749 goto out_resource;
2750 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
2751 }
2752 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
2753 p = xdr_reserve_space(xdr, 8);
2754 if (!p)
2755 goto out_resource;
2756 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
2757 }
2758 if (bmval1 & FATTR4_WORD1_MODE) {
2759 p = xdr_reserve_space(xdr, 4);
2760 if (!p)
2761 goto out_resource;
2762 *p++ = cpu_to_be32(stat.mode & S_IALLUGO);
2763 }
2764 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
2765 p = xdr_reserve_space(xdr, 4);
2766 if (!p)
2767 goto out_resource;
2768 *p++ = cpu_to_be32(1);
2769 }
2770 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
2771 p = xdr_reserve_space(xdr, 4);
2772 if (!p)
2773 goto out_resource;
2774 *p++ = cpu_to_be32(stat.nlink);
2775 }
2776 if (bmval1 & FATTR4_WORD1_OWNER) {
2777 status = nfsd4_encode_user(xdr, rqstp, stat.uid);
2778 if (status)
2779 goto out;
2780 }
2781 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
2782 status = nfsd4_encode_group(xdr, rqstp, stat.gid);
2783 if (status)
2784 goto out;
2785 }
2786 if (bmval1 & FATTR4_WORD1_RAWDEV) {
2787 p = xdr_reserve_space(xdr, 8);
2788 if (!p)
2789 goto out_resource;
2790 *p++ = cpu_to_be32((u32) MAJOR(stat.rdev));
2791 *p++ = cpu_to_be32((u32) MINOR(stat.rdev));
2792 }
2793 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
2794 p = xdr_reserve_space(xdr, 8);
2795 if (!p)
2796 goto out_resource;
2797 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
2798 p = xdr_encode_hyper(p, dummy64);
2799 }
2800 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
2801 p = xdr_reserve_space(xdr, 8);
2802 if (!p)
2803 goto out_resource;
2804 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
2805 p = xdr_encode_hyper(p, dummy64);
2806 }
2807 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
2808 p = xdr_reserve_space(xdr, 8);
2809 if (!p)
2810 goto out_resource;
2811 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
2812 p = xdr_encode_hyper(p, dummy64);
2813 }
2814 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
2815 p = xdr_reserve_space(xdr, 8);
2816 if (!p)
2817 goto out_resource;
2818 dummy64 = (u64)stat.blocks << 9;
2819 p = xdr_encode_hyper(p, dummy64);
2820 }
2821 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
2822 p = xdr_reserve_space(xdr, 12);
2823 if (!p)
2824 goto out_resource;
2825 p = xdr_encode_hyper(p, (s64)stat.atime.tv_sec);
2826 *p++ = cpu_to_be32(stat.atime.tv_nsec);
2827 }
2828 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
2829 p = xdr_reserve_space(xdr, 12);
2830 if (!p)
2831 goto out_resource;
2832 p = encode_time_delta(p, d_inode(dentry));
2833 }
2834 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
2835 p = xdr_reserve_space(xdr, 12);
2836 if (!p)
2837 goto out_resource;
2838 p = xdr_encode_hyper(p, (s64)stat.ctime.tv_sec);
2839 *p++ = cpu_to_be32(stat.ctime.tv_nsec);
2840 }
2841 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
2842 p = xdr_reserve_space(xdr, 12);
2843 if (!p)
2844 goto out_resource;
2845 p = xdr_encode_hyper(p, (s64)stat.mtime.tv_sec);
2846 *p++ = cpu_to_be32(stat.mtime.tv_nsec);
2847 }
2848 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
2849 struct kstat parent_stat;
2850 u64 ino = stat.ino;
2851
2852 p = xdr_reserve_space(xdr, 8);
2853 if (!p)
2854 goto out_resource;
2855
2856
2857
2858
2859 if (ignore_crossmnt == 0 &&
2860 dentry == exp->ex_path.mnt->mnt_root) {
2861 err = get_parent_attributes(exp, &parent_stat);
2862 if (err)
2863 goto out_nfserr;
2864 ino = parent_stat.ino;
2865 }
2866 p = xdr_encode_hyper(p, ino);
2867 }
2868#ifdef CONFIG_NFSD_PNFS
2869 if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
2870 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
2871 if (status)
2872 goto out;
2873 }
2874
2875 if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
2876 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
2877 if (status)
2878 goto out;
2879 }
2880
2881 if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
2882 p = xdr_reserve_space(xdr, 4);
2883 if (!p)
2884 goto out_resource;
2885 *p++ = cpu_to_be32(stat.blksize);
2886 }
2887#endif
2888 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2889 u32 supp[3];
2890
2891 memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
2892 supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
2893 supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
2894 supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
2895
2896 status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
2897 if (status)
2898 goto out;
2899 }
2900
2901 if (bmval2 & FATTR4_WORD2_CHANGE_ATTR_TYPE) {
2902 p = xdr_reserve_space(xdr, 4);
2903 if (!p)
2904 goto out_resource;
2905 if (IS_I_VERSION(d_inode(dentry)))
2906 *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR);
2907 else
2908 *p++ = cpu_to_be32(NFS4_CHANGE_TYPE_IS_TIME_METADATA);
2909 }
2910
2911#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2912 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2913 status = nfsd4_encode_security_label(xdr, rqstp, context,
2914 contextlen);
2915 if (status)
2916 goto out;
2917 }
2918#endif
2919
2920 attrlen = htonl(xdr->buf->len - attrlen_offset - 4);
2921 write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4);
2922 status = nfs_ok;
2923
2924out:
2925#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2926 if (context)
2927 security_release_secctx(context, contextlen);
2928#endif
2929 kfree(acl);
2930 if (tempfh) {
2931 fh_put(tempfh);
2932 kfree(tempfh);
2933 }
2934 if (status)
2935 xdr_truncate_encode(xdr, starting_len);
2936 return status;
2937out_nfserr:
2938 status = nfserrno(err);
2939 goto out;
2940out_resource:
2941 status = nfserr_resource;
2942 goto out;
2943}
2944
2945static void svcxdr_init_encode_from_buffer(struct xdr_stream *xdr,
2946 struct xdr_buf *buf, __be32 *p, int bytes)
2947{
2948 xdr->scratch.iov_len = 0;
2949 memset(buf, 0, sizeof(struct xdr_buf));
2950 buf->head[0].iov_base = p;
2951 buf->head[0].iov_len = 0;
2952 buf->len = 0;
2953 xdr->buf = buf;
2954 xdr->iov = buf->head;
2955 xdr->p = p;
2956 xdr->end = (void *)p + bytes;
2957 buf->buflen = bytes;
2958}
2959
2960__be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words,
2961 struct svc_fh *fhp, struct svc_export *exp,
2962 struct dentry *dentry, u32 *bmval,
2963 struct svc_rqst *rqstp, int ignore_crossmnt)
2964{
2965 struct xdr_buf dummy;
2966 struct xdr_stream xdr;
2967 __be32 ret;
2968
2969 svcxdr_init_encode_from_buffer(&xdr, &dummy, *p, words << 2);
2970 ret = nfsd4_encode_fattr(&xdr, fhp, exp, dentry, bmval, rqstp,
2971 ignore_crossmnt);
2972 *p = xdr.p;
2973 return ret;
2974}
2975
2976static inline int attributes_need_mount(u32 *bmval)
2977{
2978 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
2979 return 1;
2980 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
2981 return 1;
2982 return 0;
2983}
2984
2985static __be32
2986nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
2987 const char *name, int namlen)
2988{
2989 struct svc_export *exp = cd->rd_fhp->fh_export;
2990 struct dentry *dentry;
2991 __be32 nfserr;
2992 int ignore_crossmnt = 0;
2993
2994 dentry = lookup_one_len_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
2995 if (IS_ERR(dentry))
2996 return nfserrno(PTR_ERR(dentry));
2997 if (d_really_is_negative(dentry)) {
2998
2999
3000
3001
3002
3003 dput(dentry);
3004 return nfserr_noent;
3005 }
3006
3007 exp_get(exp);
3008
3009
3010
3011
3012
3013
3014
3015 if (nfsd_mountpoint(dentry, exp)) {
3016 int err;
3017
3018 if (!(exp->ex_flags & NFSEXP_V4ROOT)
3019 && !attributes_need_mount(cd->rd_bmval)) {
3020 ignore_crossmnt = 1;
3021 goto out_encode;
3022 }
3023
3024
3025
3026
3027
3028 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
3029 if (err) {
3030 nfserr = nfserrno(err);
3031 goto out_put;
3032 }
3033 nfserr = check_nfsd_access(exp, cd->rd_rqstp);
3034 if (nfserr)
3035 goto out_put;
3036
3037 }
3038out_encode:
3039 nfserr = nfsd4_encode_fattr(xdr, NULL, exp, dentry, cd->rd_bmval,
3040 cd->rd_rqstp, ignore_crossmnt);
3041out_put:
3042 dput(dentry);
3043 exp_put(exp);
3044 return nfserr;
3045}
3046
3047static __be32 *
3048nfsd4_encode_rdattr_error(struct xdr_stream *xdr, __be32 nfserr)
3049{
3050 __be32 *p;
3051
3052 p = xdr_reserve_space(xdr, 20);
3053 if (!p)
3054 return NULL;
3055 *p++ = htonl(2);
3056 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR);
3057 *p++ = htonl(0);
3058
3059 *p++ = htonl(4);
3060 *p++ = nfserr;
3061 return p;
3062}
3063
3064static int
3065nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
3066 loff_t offset, u64 ino, unsigned int d_type)
3067{
3068 struct readdir_cd *ccd = ccdv;
3069 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
3070 struct xdr_stream *xdr = cd->xdr;
3071 int start_offset = xdr->buf->len;
3072 int cookie_offset;
3073 u32 name_and_cookie;
3074 int entry_bytes;
3075 __be32 nfserr = nfserr_toosmall;
3076 __be64 wire_offset;
3077 __be32 *p;
3078
3079
3080 if (name && isdotent(name, namlen)) {
3081 cd->common.err = nfs_ok;
3082 return 0;
3083 }
3084
3085 if (cd->cookie_offset) {
3086 wire_offset = cpu_to_be64(offset);
3087 write_bytes_to_xdr_buf(xdr->buf, cd->cookie_offset,
3088 &wire_offset, 8);
3089 }
3090
3091 p = xdr_reserve_space(xdr, 4);
3092 if (!p)
3093 goto fail;
3094 *p++ = xdr_one;
3095 cookie_offset = xdr->buf->len;
3096 p = xdr_reserve_space(xdr, 3*4 + namlen);
3097 if (!p)
3098 goto fail;
3099 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);
3100 p = xdr_encode_array(p, name, namlen);
3101
3102 nfserr = nfsd4_encode_dirent_fattr(xdr, cd, name, namlen);
3103 switch (nfserr) {
3104 case nfs_ok:
3105 break;
3106 case nfserr_resource:
3107 nfserr = nfserr_toosmall;
3108 goto fail;
3109 case nfserr_noent:
3110 xdr_truncate_encode(xdr, start_offset);
3111 goto skip_entry;
3112 default:
3113
3114
3115
3116
3117
3118
3119
3120 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
3121 goto fail;
3122 p = nfsd4_encode_rdattr_error(xdr, nfserr);
3123 if (p == NULL) {
3124 nfserr = nfserr_toosmall;
3125 goto fail;
3126 }
3127 }
3128 nfserr = nfserr_toosmall;
3129 entry_bytes = xdr->buf->len - start_offset;
3130 if (entry_bytes > cd->rd_maxcount)
3131 goto fail;
3132 cd->rd_maxcount -= entry_bytes;
3133
3134
3135
3136
3137 if (!cd->rd_dircount)
3138 goto fail;
3139 name_and_cookie = 4 + 4 * XDR_QUADLEN(namlen) + 8;
3140 if (name_and_cookie > cd->rd_dircount && cd->cookie_offset)
3141 goto fail;
3142 cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie);
3143
3144 cd->cookie_offset = cookie_offset;
3145skip_entry:
3146 cd->common.err = nfs_ok;
3147 return 0;
3148fail:
3149 xdr_truncate_encode(xdr, start_offset);
3150 cd->common.err = nfserr;
3151 return -EINVAL;
3152}
3153
3154static __be32
3155nfsd4_encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
3156{
3157 __be32 *p;
3158
3159 p = xdr_reserve_space(xdr, sizeof(stateid_t));
3160 if (!p)
3161 return nfserr_resource;
3162 *p++ = cpu_to_be32(sid->si_generation);
3163 p = xdr_encode_opaque_fixed(p, &sid->si_opaque,
3164 sizeof(stateid_opaque_t));
3165 return 0;
3166}
3167
3168static __be32
3169nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
3170{
3171 struct xdr_stream *xdr = &resp->xdr;
3172 __be32 *p;
3173
3174 p = xdr_reserve_space(xdr, 8);
3175 if (!p)
3176 return nfserr_resource;
3177 *p++ = cpu_to_be32(access->ac_supported);
3178 *p++ = cpu_to_be32(access->ac_resp_access);
3179 return 0;
3180}
3181
3182static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
3183{
3184 struct xdr_stream *xdr = &resp->xdr;
3185 __be32 *p;
3186
3187 p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8);
3188 if (!p)
3189 return nfserr_resource;
3190 p = xdr_encode_opaque_fixed(p, bcts->sessionid.data,
3191 NFS4_MAX_SESSIONID_LEN);
3192 *p++ = cpu_to_be32(bcts->dir);
3193
3194 *p++ = cpu_to_be32(0);
3195 return 0;
3196}
3197
3198static __be32
3199nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
3200{
3201 struct xdr_stream *xdr = &resp->xdr;
3202
3203 return nfsd4_encode_stateid(xdr, &close->cl_stateid);
3204}
3205
3206
3207static __be32
3208nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
3209{
3210 struct xdr_stream *xdr = &resp->xdr;
3211 __be32 *p;
3212
3213 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
3214 if (!p)
3215 return nfserr_resource;
3216 p = xdr_encode_opaque_fixed(p, commit->co_verf.data,
3217 NFS4_VERIFIER_SIZE);
3218 return 0;
3219}
3220
3221static __be32
3222nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
3223{
3224 struct xdr_stream *xdr = &resp->xdr;
3225 __be32 *p;
3226
3227 p = xdr_reserve_space(xdr, 20);
3228 if (!p)
3229 return nfserr_resource;
3230 encode_cinfo(p, &create->cr_cinfo);
3231 return nfsd4_encode_bitmap(xdr, create->cr_bmval[0],
3232 create->cr_bmval[1], create->cr_bmval[2]);
3233}
3234
3235static __be32
3236nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
3237{
3238 struct svc_fh *fhp = getattr->ga_fhp;
3239 struct xdr_stream *xdr = &resp->xdr;
3240
3241 return nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry,
3242 getattr->ga_bmval, resp->rqstp, 0);
3243}
3244
3245static __be32
3246nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
3247{
3248 struct xdr_stream *xdr = &resp->xdr;
3249 struct svc_fh *fhp = *fhpp;
3250 unsigned int len;
3251 __be32 *p;
3252
3253 len = fhp->fh_handle.fh_size;
3254 p = xdr_reserve_space(xdr, len + 4);
3255 if (!p)
3256 return nfserr_resource;
3257 p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len);
3258 return 0;
3259}
3260
3261
3262
3263
3264
3265static __be32
3266nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld)
3267{
3268 struct xdr_netobj *conf = &ld->ld_owner;
3269 __be32 *p;
3270
3271again:
3272 p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len));
3273 if (!p) {
3274
3275
3276
3277
3278 if (conf->len) {
3279 kfree(conf->data);
3280 conf->len = 0;
3281 conf->data = NULL;
3282 goto again;
3283 }
3284 return nfserr_resource;
3285 }
3286 p = xdr_encode_hyper(p, ld->ld_start);
3287 p = xdr_encode_hyper(p, ld->ld_length);
3288 *p++ = cpu_to_be32(ld->ld_type);
3289 if (conf->len) {
3290 p = xdr_encode_opaque_fixed(p, &ld->ld_clientid, 8);
3291 p = xdr_encode_opaque(p, conf->data, conf->len);
3292 kfree(conf->data);
3293 } else {
3294 p = xdr_encode_hyper(p, (u64)0);
3295 *p++ = cpu_to_be32(0);
3296 }
3297 return nfserr_denied;
3298}
3299
3300static __be32
3301nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
3302{
3303 struct xdr_stream *xdr = &resp->xdr;
3304
3305 if (!nfserr)
3306 nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid);
3307 else if (nfserr == nfserr_denied)
3308 nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied);
3309
3310 return nfserr;
3311}
3312
3313static __be32
3314nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
3315{
3316 struct xdr_stream *xdr = &resp->xdr;
3317
3318 if (nfserr == nfserr_denied)
3319 nfsd4_encode_lock_denied(xdr, &lockt->lt_denied);
3320 return nfserr;
3321}
3322
3323static __be32
3324nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
3325{
3326 struct xdr_stream *xdr = &resp->xdr;
3327
3328 return nfsd4_encode_stateid(xdr, &locku->lu_stateid);
3329}
3330
3331
3332static __be32
3333nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
3334{
3335 struct xdr_stream *xdr = &resp->xdr;
3336 __be32 *p;
3337
3338 p = xdr_reserve_space(xdr, 20);
3339 if (!p)
3340 return nfserr_resource;
3341 p = encode_cinfo(p, &link->li_cinfo);
3342 return 0;
3343}
3344
3345
3346static __be32
3347nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
3348{
3349 struct xdr_stream *xdr = &resp->xdr;
3350 __be32 *p;
3351
3352 nfserr = nfsd4_encode_stateid(xdr, &open->op_stateid);
3353 if (nfserr)
3354 return nfserr;
3355 p = xdr_reserve_space(xdr, 24);
3356 if (!p)
3357 return nfserr_resource;
3358 p = encode_cinfo(p, &open->op_cinfo);
3359 *p++ = cpu_to_be32(open->op_rflags);
3360
3361 nfserr = nfsd4_encode_bitmap(xdr, open->op_bmval[0], open->op_bmval[1],
3362 open->op_bmval[2]);
3363 if (nfserr)
3364 return nfserr;
3365
3366 p = xdr_reserve_space(xdr, 4);
3367 if (!p)
3368 return nfserr_resource;
3369
3370 *p++ = cpu_to_be32(open->op_delegate_type);
3371 switch (open->op_delegate_type) {
3372 case NFS4_OPEN_DELEGATE_NONE:
3373 break;
3374 case NFS4_OPEN_DELEGATE_READ:
3375 nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid);
3376 if (nfserr)
3377 return nfserr;
3378 p = xdr_reserve_space(xdr, 20);
3379 if (!p)
3380 return nfserr_resource;
3381 *p++ = cpu_to_be32(open->op_recall);
3382
3383
3384
3385
3386 *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
3387 *p++ = cpu_to_be32(0);
3388 *p++ = cpu_to_be32(0);
3389 *p++ = cpu_to_be32(0);
3390 break;
3391 case NFS4_OPEN_DELEGATE_WRITE:
3392 nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid);
3393 if (nfserr)
3394 return nfserr;
3395 p = xdr_reserve_space(xdr, 32);
3396 if (!p)
3397 return nfserr_resource;
3398 *p++ = cpu_to_be32(0);
3399
3400
3401
3402
3403 *p++ = cpu_to_be32(NFS4_LIMIT_SIZE);
3404 *p++ = cpu_to_be32(~(u32)0);
3405 *p++ = cpu_to_be32(~(u32)0);
3406
3407
3408
3409
3410 *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
3411 *p++ = cpu_to_be32(0);
3412 *p++ = cpu_to_be32(0);
3413 *p++ = cpu_to_be32(0);
3414 break;
3415 case NFS4_OPEN_DELEGATE_NONE_EXT:
3416 switch (open->op_why_no_deleg) {
3417 case WND4_CONTENTION:
3418 case WND4_RESOURCE:
3419 p = xdr_reserve_space(xdr, 8);
3420 if (!p)
3421 return nfserr_resource;
3422 *p++ = cpu_to_be32(open->op_why_no_deleg);
3423
3424 *p++ = cpu_to_be32(0);
3425 break;
3426 default:
3427 p = xdr_reserve_space(xdr, 4);
3428 if (!p)
3429 return nfserr_resource;
3430 *p++ = cpu_to_be32(open->op_why_no_deleg);
3431 }
3432 break;
3433 default:
3434 BUG();
3435 }
3436
3437 return 0;
3438}
3439
3440static __be32
3441nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
3442{
3443 struct xdr_stream *xdr = &resp->xdr;
3444
3445 return nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid);
3446}
3447
3448static __be32
3449nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
3450{
3451 struct xdr_stream *xdr = &resp->xdr;
3452
3453 return nfsd4_encode_stateid(xdr, &od->od_stateid);
3454}
3455
3456static __be32 nfsd4_encode_splice_read(
3457 struct nfsd4_compoundres *resp,
3458 struct nfsd4_read *read,
3459 struct file *file, unsigned long maxcount)
3460{
3461 struct xdr_stream *xdr = &resp->xdr;
3462 struct xdr_buf *buf = xdr->buf;
3463 u32 eof;
3464 long len;
3465 int space_left;
3466 __be32 nfserr;
3467 __be32 *p = xdr->p - 2;
3468
3469
3470 if (xdr->end - xdr->p < 1)
3471 return nfserr_resource;
3472
3473 len = maxcount;
3474 nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
3475 file, read->rd_offset, &maxcount, &eof);
3476 read->rd_length = maxcount;
3477 if (nfserr) {
3478
3479
3480
3481
3482
3483 buf->page_len = 0;
3484 return nfserr;
3485 }
3486
3487 *(p++) = htonl(eof);
3488 *(p++) = htonl(maxcount);
3489
3490 buf->page_len = maxcount;
3491 buf->len += maxcount;
3492 xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
3493 / PAGE_SIZE;
3494
3495
3496 buf->tail[0].iov_base = xdr->p;
3497 buf->tail[0].iov_len = 0;
3498 xdr->iov = buf->tail;
3499 if (maxcount&3) {
3500 int pad = 4 - (maxcount&3);
3501
3502 *(xdr->p++) = 0;
3503
3504 buf->tail[0].iov_base += maxcount&3;
3505 buf->tail[0].iov_len = pad;
3506 buf->len += pad;
3507 }
3508
3509 space_left = min_t(int, (void *)xdr->end - (void *)xdr->p,
3510 buf->buflen - buf->len);
3511 buf->buflen = buf->len + space_left;
3512 xdr->end = (__be32 *)((void *)xdr->end + space_left);
3513
3514 return 0;
3515}
3516
3517static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
3518 struct nfsd4_read *read,
3519 struct file *file, unsigned long maxcount)
3520{
3521 struct xdr_stream *xdr = &resp->xdr;
3522 u32 eof;
3523 int v;
3524 int starting_len = xdr->buf->len - 8;
3525 long len;
3526 int thislen;
3527 __be32 nfserr;
3528 __be32 tmp;
3529 __be32 *p;
3530 u32 zzz = 0;
3531 int pad;
3532
3533 len = maxcount;
3534 v = 0;
3535
3536 thislen = min_t(long, len, ((void *)xdr->end - (void *)xdr->p));
3537 p = xdr_reserve_space(xdr, (thislen+3)&~3);
3538 WARN_ON_ONCE(!p);
3539 resp->rqstp->rq_vec[v].iov_base = p;
3540 resp->rqstp->rq_vec[v].iov_len = thislen;
3541 v++;
3542 len -= thislen;
3543
3544 while (len) {
3545 thislen = min_t(long, len, PAGE_SIZE);
3546 p = xdr_reserve_space(xdr, (thislen+3)&~3);
3547 WARN_ON_ONCE(!p);
3548 resp->rqstp->rq_vec[v].iov_base = p;
3549 resp->rqstp->rq_vec[v].iov_len = thislen;
3550 v++;
3551 len -= thislen;
3552 }
3553 read->rd_vlen = v;
3554
3555 len = maxcount;
3556 nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
3557 resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
3558 &eof);
3559 read->rd_length = maxcount;
3560 if (nfserr)
3561 return nfserr;
3562 xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
3563
3564 tmp = htonl(eof);
3565 write_bytes_to_xdr_buf(xdr->buf, starting_len , &tmp, 4);
3566 tmp = htonl(maxcount);
3567 write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
3568
3569 pad = (maxcount&3) ? 4 - (maxcount&3) : 0;
3570 write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
3571 &zzz, pad);
3572 return 0;
3573
3574}
3575
3576static __be32
3577nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3578 struct nfsd4_read *read)
3579{
3580 unsigned long maxcount;
3581 struct xdr_stream *xdr = &resp->xdr;
3582 struct file *file;
3583 int starting_len = xdr->buf->len;
3584 __be32 *p;
3585
3586 if (nfserr)
3587 return nfserr;
3588 file = read->rd_nf->nf_file;
3589
3590 p = xdr_reserve_space(xdr, 8);
3591 if (!p) {
3592 WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags));
3593 return nfserr_resource;
3594 }
3595 if (resp->xdr.buf->page_len &&
3596 test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) {
3597 WARN_ON_ONCE(1);
3598 return nfserr_resource;
3599 }
3600 xdr_commit_encode(xdr);
3601
3602 maxcount = svc_max_payload(resp->rqstp);
3603 maxcount = min_t(unsigned long, maxcount,
3604 (xdr->buf->buflen - xdr->buf->len));
3605 maxcount = min_t(unsigned long, maxcount, read->rd_length);
3606
3607 if (file->f_op->splice_read &&
3608 test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
3609 nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
3610 else
3611 nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
3612
3613 if (nfserr)
3614 xdr_truncate_encode(xdr, starting_len);
3615
3616 return nfserr;
3617}
3618
3619static __be32
3620nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
3621{
3622 int maxcount;
3623 __be32 wire_count;
3624 int zero = 0;
3625 struct xdr_stream *xdr = &resp->xdr;
3626 int length_offset = xdr->buf->len;
3627 __be32 *p;
3628
3629 p = xdr_reserve_space(xdr, 4);
3630 if (!p)
3631 return nfserr_resource;
3632 maxcount = PAGE_SIZE;
3633
3634 p = xdr_reserve_space(xdr, maxcount);
3635 if (!p)
3636 return nfserr_resource;
3637
3638
3639
3640
3641
3642
3643 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp,
3644 (char *)p, &maxcount);
3645 if (nfserr == nfserr_isdir)
3646 nfserr = nfserr_inval;
3647 if (nfserr) {
3648 xdr_truncate_encode(xdr, length_offset);
3649 return nfserr;
3650 }
3651
3652 wire_count = htonl(maxcount);
3653 write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, 4);
3654 xdr_truncate_encode(xdr, length_offset + 4 + ALIGN(maxcount, 4));
3655 if (maxcount & 3)
3656 write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount,
3657 &zero, 4 - (maxcount&3));
3658 return 0;
3659}
3660
3661static __be32
3662nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
3663{
3664 int maxcount;
3665 int bytes_left;
3666 loff_t offset;
3667 __be64 wire_offset;
3668 struct xdr_stream *xdr = &resp->xdr;
3669 int starting_len = xdr->buf->len;
3670 __be32 *p;
3671
3672 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
3673 if (!p)
3674 return nfserr_resource;
3675
3676
3677 *p++ = cpu_to_be32(0);
3678 *p++ = cpu_to_be32(0);
3679 resp->xdr.buf->head[0].iov_len = ((char *)resp->xdr.p)
3680 - (char *)resp->xdr.buf->head[0].iov_base;
3681
3682
3683
3684
3685
3686 bytes_left = xdr->buf->buflen - xdr->buf->len
3687 - COMPOUND_ERR_SLACK_SPACE - 8;
3688 if (bytes_left < 0) {
3689 nfserr = nfserr_resource;
3690 goto err_no_verf;
3691 }
3692 maxcount = svc_max_payload(resp->rqstp);
3693 maxcount = min_t(u32, readdir->rd_maxcount, maxcount);
3694
3695
3696
3697
3698
3699 if (maxcount < 16) {
3700 nfserr = nfserr_toosmall;
3701 goto err_no_verf;
3702 }
3703 maxcount = min_t(int, maxcount-16, bytes_left);
3704
3705
3706 if (!readdir->rd_dircount)
3707 readdir->rd_dircount = svc_max_payload(resp->rqstp);
3708
3709 readdir->xdr = xdr;
3710 readdir->rd_maxcount = maxcount;
3711 readdir->common.err = 0;
3712 readdir->cookie_offset = 0;
3713
3714 offset = readdir->rd_cookie;
3715 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
3716 &offset,
3717 &readdir->common, nfsd4_encode_dirent);
3718 if (nfserr == nfs_ok &&
3719 readdir->common.err == nfserr_toosmall &&
3720 xdr->buf->len == starting_len + 8) {
3721
3722 if (maxcount - 16 < bytes_left)
3723
3724 nfserr = nfserr_toosmall;
3725 else
3726
3727 nfserr = nfserr_resource;
3728 }
3729 if (nfserr)
3730 goto err_no_verf;
3731
3732 if (readdir->cookie_offset) {
3733 wire_offset = cpu_to_be64(offset);
3734 write_bytes_to_xdr_buf(xdr->buf, readdir->cookie_offset,
3735 &wire_offset, 8);
3736 }
3737
3738 p = xdr_reserve_space(xdr, 8);
3739 if (!p) {
3740 WARN_ON_ONCE(1);
3741 goto err_no_verf;
3742 }
3743 *p++ = 0;
3744 *p++ = htonl(readdir->common.err == nfserr_eof);
3745
3746 return 0;
3747err_no_verf:
3748 xdr_truncate_encode(xdr, starting_len);
3749 return nfserr;
3750}
3751
3752static __be32
3753nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
3754{
3755 struct xdr_stream *xdr = &resp->xdr;
3756 __be32 *p;
3757
3758 p = xdr_reserve_space(xdr, 20);
3759 if (!p)
3760 return nfserr_resource;
3761 p = encode_cinfo(p, &remove->rm_cinfo);
3762 return 0;
3763}
3764
3765static __be32
3766nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
3767{
3768 struct xdr_stream *xdr = &resp->xdr;
3769 __be32 *p;
3770
3771 p = xdr_reserve_space(xdr, 40);
3772 if (!p)
3773 return nfserr_resource;
3774 p = encode_cinfo(p, &rename->rn_sinfo);
3775 p = encode_cinfo(p, &rename->rn_tinfo);
3776 return 0;
3777}
3778
3779static __be32
3780nfsd4_do_encode_secinfo(struct xdr_stream *xdr, struct svc_export *exp)
3781{
3782 u32 i, nflavs, supported;
3783 struct exp_flavor_info *flavs;
3784 struct exp_flavor_info def_flavs[2];
3785 __be32 *p, *flavorsp;
3786 static bool report = true;
3787
3788 if (exp->ex_nflavors) {
3789 flavs = exp->ex_flavors;
3790 nflavs = exp->ex_nflavors;
3791 } else {
3792 flavs = def_flavs;
3793 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
3794 nflavs = 2;
3795 flavs[0].pseudoflavor = RPC_AUTH_UNIX;
3796 flavs[1].pseudoflavor = RPC_AUTH_NULL;
3797 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
3798 nflavs = 1;
3799 flavs[0].pseudoflavor
3800 = svcauth_gss_flavor(exp->ex_client);
3801 } else {
3802 nflavs = 1;
3803 flavs[0].pseudoflavor
3804 = exp->ex_client->flavour->flavour;
3805 }
3806 }
3807
3808 supported = 0;
3809 p = xdr_reserve_space(xdr, 4);
3810 if (!p)
3811 return nfserr_resource;
3812 flavorsp = p++;
3813
3814 for (i = 0; i < nflavs; i++) {
3815 rpc_authflavor_t pf = flavs[i].pseudoflavor;
3816 struct rpcsec_gss_info info;
3817
3818 if (rpcauth_get_gssinfo(pf, &info) == 0) {
3819 supported++;
3820 p = xdr_reserve_space(xdr, 4 + 4 +
3821 XDR_LEN(info.oid.len) + 4 + 4);
3822 if (!p)
3823 return nfserr_resource;
3824 *p++ = cpu_to_be32(RPC_AUTH_GSS);
3825 p = xdr_encode_opaque(p, info.oid.data, info.oid.len);
3826 *p++ = cpu_to_be32(info.qop);
3827 *p++ = cpu_to_be32(info.service);
3828 } else if (pf < RPC_AUTH_MAXFLAVOR) {
3829 supported++;
3830 p = xdr_reserve_space(xdr, 4);
3831 if (!p)
3832 return nfserr_resource;
3833 *p++ = cpu_to_be32(pf);
3834 } else {
3835 if (report)
3836 pr_warn("NFS: SECINFO: security flavor %u "
3837 "is not supported\n", pf);
3838 }
3839 }
3840
3841 if (nflavs != supported)
3842 report = false;
3843 *flavorsp = htonl(supported);
3844 return 0;
3845}
3846
3847static __be32
3848nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
3849 struct nfsd4_secinfo *secinfo)
3850{
3851 struct xdr_stream *xdr = &resp->xdr;
3852
3853 return nfsd4_do_encode_secinfo(xdr, secinfo->si_exp);
3854}
3855
3856static __be32
3857nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
3858 struct nfsd4_secinfo_no_name *secinfo)
3859{
3860 struct xdr_stream *xdr = &resp->xdr;
3861
3862 return nfsd4_do_encode_secinfo(xdr, secinfo->sin_exp);
3863}
3864
3865
3866
3867
3868
3869static __be32
3870nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
3871{
3872 struct xdr_stream *xdr = &resp->xdr;
3873 __be32 *p;
3874
3875 p = xdr_reserve_space(xdr, 16);
3876 if (!p)
3877 return nfserr_resource;
3878 if (nfserr) {
3879 *p++ = cpu_to_be32(3);
3880 *p++ = cpu_to_be32(0);
3881 *p++ = cpu_to_be32(0);
3882 *p++ = cpu_to_be32(0);
3883 }
3884 else {
3885 *p++ = cpu_to_be32(3);
3886 *p++ = cpu_to_be32(setattr->sa_bmval[0]);
3887 *p++ = cpu_to_be32(setattr->sa_bmval[1]);
3888 *p++ = cpu_to_be32(setattr->sa_bmval[2]);
3889 }
3890 return nfserr;
3891}
3892
3893static __be32
3894nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
3895{
3896 struct xdr_stream *xdr = &resp->xdr;
3897 __be32 *p;
3898
3899 if (!nfserr) {
3900 p = xdr_reserve_space(xdr, 8 + NFS4_VERIFIER_SIZE);
3901 if (!p)
3902 return nfserr_resource;
3903 p = xdr_encode_opaque_fixed(p, &scd->se_clientid, 8);
3904 p = xdr_encode_opaque_fixed(p, &scd->se_confirm,
3905 NFS4_VERIFIER_SIZE);
3906 }
3907 else if (nfserr == nfserr_clid_inuse) {
3908 p = xdr_reserve_space(xdr, 8);
3909 if (!p)
3910 return nfserr_resource;
3911 *p++ = cpu_to_be32(0);
3912 *p++ = cpu_to_be32(0);
3913 }
3914 return nfserr;
3915}
3916
3917static __be32
3918nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
3919{
3920 struct xdr_stream *xdr = &resp->xdr;
3921 __be32 *p;
3922
3923 p = xdr_reserve_space(xdr, 16);
3924 if (!p)
3925 return nfserr_resource;
3926 *p++ = cpu_to_be32(write->wr_bytes_written);
3927 *p++ = cpu_to_be32(write->wr_how_written);
3928 p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
3929 NFS4_VERIFIER_SIZE);
3930 return 0;
3931}
3932
3933static __be32
3934nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
3935 struct nfsd4_exchange_id *exid)
3936{
3937 struct xdr_stream *xdr = &resp->xdr;
3938 __be32 *p;
3939 char *major_id;
3940 char *server_scope;
3941 int major_id_sz;
3942 int server_scope_sz;
3943 uint64_t minor_id = 0;
3944
3945 major_id = utsname()->nodename;
3946 major_id_sz = strlen(major_id);
3947 server_scope = utsname()->nodename;
3948 server_scope_sz = strlen(server_scope);
3949
3950 p = xdr_reserve_space(xdr,
3951 8 +
3952 4 +
3953 4 +
3954 4 );
3955 if (!p)
3956 return nfserr_resource;
3957
3958 p = xdr_encode_opaque_fixed(p, &exid->clientid, 8);
3959 *p++ = cpu_to_be32(exid->seqid);
3960 *p++ = cpu_to_be32(exid->flags);
3961
3962 *p++ = cpu_to_be32(exid->spa_how);
3963
3964 switch (exid->spa_how) {
3965 case SP4_NONE:
3966 break;
3967 case SP4_MACH_CRED:
3968
3969 nfserr = nfsd4_encode_bitmap(xdr,
3970 exid->spo_must_enforce[0],
3971 exid->spo_must_enforce[1],
3972 exid->spo_must_enforce[2]);
3973 if (nfserr)
3974 return nfserr;
3975
3976 nfserr = nfsd4_encode_bitmap(xdr,
3977 exid->spo_must_allow[0],
3978 exid->spo_must_allow[1],
3979 exid->spo_must_allow[2]);
3980 if (nfserr)
3981 return nfserr;
3982 break;
3983 default:
3984 WARN_ON_ONCE(1);
3985 }
3986
3987 p = xdr_reserve_space(xdr,
3988 8 +
3989 4 +
3990 (XDR_QUADLEN(major_id_sz) * 4) +
3991 4 +
3992 (XDR_QUADLEN(server_scope_sz) * 4) +
3993 4 );
3994 if (!p)
3995 return nfserr_resource;
3996
3997
3998 p = xdr_encode_hyper(p, minor_id);
3999
4000 p = xdr_encode_opaque(p, major_id, major_id_sz);
4001
4002
4003 p = xdr_encode_opaque(p, server_scope, server_scope_sz);
4004
4005
4006 *p++ = cpu_to_be32(0);
4007 return 0;
4008}
4009
4010static __be32
4011nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
4012 struct nfsd4_create_session *sess)
4013{
4014 struct xdr_stream *xdr = &resp->xdr;
4015 __be32 *p;
4016
4017 p = xdr_reserve_space(xdr, 24);
4018 if (!p)
4019 return nfserr_resource;
4020 p = xdr_encode_opaque_fixed(p, sess->sessionid.data,
4021 NFS4_MAX_SESSIONID_LEN);
4022 *p++ = cpu_to_be32(sess->seqid);
4023 *p++ = cpu_to_be32(sess->flags);
4024
4025 p = xdr_reserve_space(xdr, 28);
4026 if (!p)
4027 return nfserr_resource;
4028 *p++ = cpu_to_be32(0);
4029 *p++ = cpu_to_be32(sess->fore_channel.maxreq_sz);
4030 *p++ = cpu_to_be32(sess->fore_channel.maxresp_sz);
4031 *p++ = cpu_to_be32(sess->fore_channel.maxresp_cached);
4032 *p++ = cpu_to_be32(sess->fore_channel.maxops);
4033 *p++ = cpu_to_be32(sess->fore_channel.maxreqs);
4034 *p++ = cpu_to_be32(sess->fore_channel.nr_rdma_attrs);
4035
4036 if (sess->fore_channel.nr_rdma_attrs) {
4037 p = xdr_reserve_space(xdr, 4);
4038 if (!p)
4039 return nfserr_resource;
4040 *p++ = cpu_to_be32(sess->fore_channel.rdma_attrs);
4041 }
4042
4043 p = xdr_reserve_space(xdr, 28);
4044 if (!p)
4045 return nfserr_resource;
4046 *p++ = cpu_to_be32(0);
4047 *p++ = cpu_to_be32(sess->back_channel.maxreq_sz);
4048 *p++ = cpu_to_be32(sess->back_channel.maxresp_sz);
4049 *p++ = cpu_to_be32(sess->back_channel.maxresp_cached);
4050 *p++ = cpu_to_be32(sess->back_channel.maxops);
4051 *p++ = cpu_to_be32(sess->back_channel.maxreqs);
4052 *p++ = cpu_to_be32(sess->back_channel.nr_rdma_attrs);
4053
4054 if (sess->back_channel.nr_rdma_attrs) {
4055 p = xdr_reserve_space(xdr, 4);
4056 if (!p)
4057 return nfserr_resource;
4058 *p++ = cpu_to_be32(sess->back_channel.rdma_attrs);
4059 }
4060 return 0;
4061}
4062
4063static __be32
4064nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
4065 struct nfsd4_sequence *seq)
4066{
4067 struct xdr_stream *xdr = &resp->xdr;
4068 __be32 *p;
4069
4070 p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 20);
4071 if (!p)
4072 return nfserr_resource;
4073 p = xdr_encode_opaque_fixed(p, seq->sessionid.data,
4074 NFS4_MAX_SESSIONID_LEN);
4075 *p++ = cpu_to_be32(seq->seqid);
4076 *p++ = cpu_to_be32(seq->slotid);
4077
4078 *p++ = cpu_to_be32(seq->maxslots - 1);
4079 *p++ = cpu_to_be32(seq->maxslots - 1);
4080 *p++ = cpu_to_be32(seq->status_flags);
4081
4082 resp->cstate.data_offset = xdr->buf->len;
4083 return 0;
4084}
4085
4086static __be32
4087nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
4088 struct nfsd4_test_stateid *test_stateid)
4089{
4090 struct xdr_stream *xdr = &resp->xdr;
4091 struct nfsd4_test_stateid_id *stateid, *next;
4092 __be32 *p;
4093
4094 p = xdr_reserve_space(xdr, 4 + (4 * test_stateid->ts_num_ids));
4095 if (!p)
4096 return nfserr_resource;
4097 *p++ = htonl(test_stateid->ts_num_ids);
4098
4099 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
4100 *p++ = stateid->ts_id_status;
4101 }
4102
4103 return 0;
4104}
4105
4106#ifdef CONFIG_NFSD_PNFS
4107static __be32
4108nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
4109 struct nfsd4_getdeviceinfo *gdev)
4110{
4111 struct xdr_stream *xdr = &resp->xdr;
4112 const struct nfsd4_layout_ops *ops;
4113 u32 starting_len = xdr->buf->len, needed_len;
4114 __be32 *p;
4115
4116 p = xdr_reserve_space(xdr, 4);
4117 if (!p)
4118 return nfserr_resource;
4119
4120 *p++ = cpu_to_be32(gdev->gd_layout_type);
4121
4122
4123 if (gdev->gd_maxcount != 0) {
4124 ops = nfsd4_layout_ops[gdev->gd_layout_type];
4125 nfserr = ops->encode_getdeviceinfo(xdr, gdev);
4126 if (nfserr) {
4127
4128
4129
4130
4131
4132 if (xdr->buf->len + 4 > gdev->gd_maxcount)
4133 goto toosmall;
4134 return nfserr;
4135 }
4136 }
4137
4138 if (gdev->gd_notify_types) {
4139 p = xdr_reserve_space(xdr, 4 + 4);
4140 if (!p)
4141 return nfserr_resource;
4142 *p++ = cpu_to_be32(1);
4143 *p++ = cpu_to_be32(gdev->gd_notify_types);
4144 } else {
4145 p = xdr_reserve_space(xdr, 4);
4146 if (!p)
4147 return nfserr_resource;
4148 *p++ = 0;
4149 }
4150
4151 return 0;
4152toosmall:
4153 dprintk("%s: maxcount too small\n", __func__);
4154 needed_len = xdr->buf->len + 4 ;
4155 xdr_truncate_encode(xdr, starting_len);
4156 p = xdr_reserve_space(xdr, 4);
4157 if (!p)
4158 return nfserr_resource;
4159 *p++ = cpu_to_be32(needed_len);
4160 return nfserr_toosmall;
4161}
4162
4163static __be32
4164nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
4165 struct nfsd4_layoutget *lgp)
4166{
4167 struct xdr_stream *xdr = &resp->xdr;
4168 const struct nfsd4_layout_ops *ops;
4169 __be32 *p;
4170
4171 p = xdr_reserve_space(xdr, 36 + sizeof(stateid_opaque_t));
4172 if (!p)
4173 return nfserr_resource;
4174
4175 *p++ = cpu_to_be32(1);
4176 *p++ = cpu_to_be32(lgp->lg_sid.si_generation);
4177 p = xdr_encode_opaque_fixed(p, &lgp->lg_sid.si_opaque,
4178 sizeof(stateid_opaque_t));
4179
4180 *p++ = cpu_to_be32(1);
4181 p = xdr_encode_hyper(p, lgp->lg_seg.offset);
4182 p = xdr_encode_hyper(p, lgp->lg_seg.length);
4183 *p++ = cpu_to_be32(lgp->lg_seg.iomode);
4184 *p++ = cpu_to_be32(lgp->lg_layout_type);
4185
4186 ops = nfsd4_layout_ops[lgp->lg_layout_type];
4187 return ops->encode_layoutget(xdr, lgp);
4188}
4189
4190static __be32
4191nfsd4_encode_layoutcommit(struct nfsd4_compoundres *resp, __be32 nfserr,
4192 struct nfsd4_layoutcommit *lcp)
4193{
4194 struct xdr_stream *xdr = &resp->xdr;
4195 __be32 *p;
4196
4197 p = xdr_reserve_space(xdr, 4);
4198 if (!p)
4199 return nfserr_resource;
4200 *p++ = cpu_to_be32(lcp->lc_size_chg);
4201 if (lcp->lc_size_chg) {
4202 p = xdr_reserve_space(xdr, 8);
4203 if (!p)
4204 return nfserr_resource;
4205 p = xdr_encode_hyper(p, lcp->lc_newsize);
4206 }
4207
4208 return 0;
4209}
4210
4211static __be32
4212nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
4213 struct nfsd4_layoutreturn *lrp)
4214{
4215 struct xdr_stream *xdr = &resp->xdr;
4216 __be32 *p;
4217
4218 p = xdr_reserve_space(xdr, 4);
4219 if (!p)
4220 return nfserr_resource;
4221 *p++ = cpu_to_be32(lrp->lrs_present);
4222 if (lrp->lrs_present)
4223 return nfsd4_encode_stateid(xdr, &lrp->lr_sid);
4224 return 0;
4225}
4226#endif
4227
4228static __be32
4229nfsd42_encode_write_res(struct nfsd4_compoundres *resp,
4230 struct nfsd42_write_res *write, bool sync)
4231{
4232 __be32 *p;
4233 p = xdr_reserve_space(&resp->xdr, 4);
4234 if (!p)
4235 return nfserr_resource;
4236
4237 if (sync)
4238 *p++ = cpu_to_be32(0);
4239 else {
4240 __be32 nfserr;
4241 *p++ = cpu_to_be32(1);
4242 nfserr = nfsd4_encode_stateid(&resp->xdr, &write->cb_stateid);
4243 if (nfserr)
4244 return nfserr;
4245 }
4246 p = xdr_reserve_space(&resp->xdr, 8 + 4 + NFS4_VERIFIER_SIZE);
4247 if (!p)
4248 return nfserr_resource;
4249
4250 p = xdr_encode_hyper(p, write->wr_bytes_written);
4251 *p++ = cpu_to_be32(write->wr_stable_how);
4252 p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
4253 NFS4_VERIFIER_SIZE);
4254 return nfs_ok;
4255}
4256
4257static __be32
4258nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
4259 struct nfsd4_copy *copy)
4260{
4261 __be32 *p;
4262
4263 nfserr = nfsd42_encode_write_res(resp, ©->cp_res,
4264 copy->cp_synchronous);
4265 if (nfserr)
4266 return nfserr;
4267
4268 p = xdr_reserve_space(&resp->xdr, 4 + 4);
4269 *p++ = xdr_one;
4270 *p++ = cpu_to_be32(copy->cp_synchronous);
4271 return 0;
4272}
4273
4274static __be32
4275nfsd4_encode_offload_status(struct nfsd4_compoundres *resp, __be32 nfserr,
4276 struct nfsd4_offload_status *os)
4277{
4278 struct xdr_stream *xdr = &resp->xdr;
4279 __be32 *p;
4280
4281 p = xdr_reserve_space(xdr, 8 + 4);
4282 if (!p)
4283 return nfserr_resource;
4284 p = xdr_encode_hyper(p, os->count);
4285 *p++ = cpu_to_be32(0);
4286
4287 return nfserr;
4288}
4289
4290static __be32
4291nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
4292 struct nfsd4_seek *seek)
4293{
4294 __be32 *p;
4295
4296 p = xdr_reserve_space(&resp->xdr, 4 + 8);
4297 *p++ = cpu_to_be32(seek->seek_eof);
4298 p = xdr_encode_hyper(p, seek->seek_pos);
4299
4300 return 0;
4301}
4302
4303static __be32
4304nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
4305{
4306 return nfserr;
4307}
4308
4309typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
4310
4311
4312
4313
4314
4315
4316static const nfsd4_enc nfsd4_enc_ops[] = {
4317 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
4318 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
4319 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
4320 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create,
4321 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop,
4322 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop,
4323 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr,
4324 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh,
4325 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link,
4326 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock,
4327 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt,
4328 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku,
4329 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop,
4330 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop,
4331 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop,
4332 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open,
4333 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop,
4334 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm,
4335 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade,
4336 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop,
4337 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop,
4338 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop,
4339 [OP_READ] = (nfsd4_enc)nfsd4_encode_read,
4340 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir,
4341 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink,
4342 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove,
4343 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename,
4344 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop,
4345 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop,
4346 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop,
4347 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo,
4348 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr,
4349 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid,
4350 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
4351 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop,
4352 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write,
4353 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop,
4354
4355
4356 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
4357 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
4358 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
4359 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
4360 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_noop,
4361 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
4362 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
4363#ifdef CONFIG_NFSD_PNFS
4364 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_getdeviceinfo,
4365 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
4366 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_layoutcommit,
4367 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_layoutget,
4368 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_layoutreturn,
4369#else
4370 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
4371 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
4372 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop,
4373 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop,
4374 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop,
4375#endif
4376 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
4377 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
4378 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
4379 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid,
4380 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
4381 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
4382 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
4383
4384
4385 [OP_ALLOCATE] = (nfsd4_enc)nfsd4_encode_noop,
4386 [OP_COPY] = (nfsd4_enc)nfsd4_encode_copy,
4387 [OP_COPY_NOTIFY] = (nfsd4_enc)nfsd4_encode_noop,
4388 [OP_DEALLOCATE] = (nfsd4_enc)nfsd4_encode_noop,
4389 [OP_IO_ADVISE] = (nfsd4_enc)nfsd4_encode_noop,
4390 [OP_LAYOUTERROR] = (nfsd4_enc)nfsd4_encode_noop,
4391 [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop,
4392 [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop,
4393 [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_offload_status,
4394 [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop,
4395 [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,
4396 [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,
4397 [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,
4398};
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize)
4414{
4415 struct xdr_buf *buf = &resp->rqstp->rq_res;
4416 struct nfsd4_slot *slot = resp->cstate.slot;
4417
4418 if (buf->len + respsize <= buf->buflen)
4419 return nfs_ok;
4420 if (!nfsd4_has_session(&resp->cstate))
4421 return nfserr_resource;
4422 if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) {
4423 WARN_ON_ONCE(1);
4424 return nfserr_rep_too_big_to_cache;
4425 }
4426 return nfserr_rep_too_big;
4427}
4428
4429void
4430nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
4431{
4432 struct xdr_stream *xdr = &resp->xdr;
4433 struct nfs4_stateowner *so = resp->cstate.replay_owner;
4434 struct svc_rqst *rqstp = resp->rqstp;
4435 const struct nfsd4_operation *opdesc = op->opdesc;
4436 int post_err_offset;
4437 nfsd4_enc encoder;
4438 __be32 *p;
4439
4440 p = xdr_reserve_space(xdr, 8);
4441 if (!p) {
4442 WARN_ON_ONCE(1);
4443 return;
4444 }
4445 *p++ = cpu_to_be32(op->opnum);
4446 post_err_offset = xdr->buf->len;
4447
4448 if (op->opnum == OP_ILLEGAL)
4449 goto status;
4450 if (op->status && opdesc &&
4451 !(opdesc->op_flags & OP_NONTRIVIAL_ERROR_ENCODE))
4452 goto status;
4453 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
4454 !nfsd4_enc_ops[op->opnum]);
4455 encoder = nfsd4_enc_ops[op->opnum];
4456 op->status = encoder(resp, op->status, &op->u);
4457 if (opdesc && opdesc->op_release)
4458 opdesc->op_release(&op->u);
4459 xdr_commit_encode(xdr);
4460
4461
4462 if (!op->status) {
4463 int space_needed = 0;
4464 if (!nfsd4_last_compound_op(rqstp))
4465 space_needed = COMPOUND_ERR_SLACK_SPACE;
4466 op->status = nfsd4_check_resp_size(resp, space_needed);
4467 }
4468 if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) {
4469 struct nfsd4_slot *slot = resp->cstate.slot;
4470
4471 if (slot->sl_flags & NFSD4_SLOT_CACHETHIS)
4472 op->status = nfserr_rep_too_big_to_cache;
4473 else
4474 op->status = nfserr_rep_too_big;
4475 }
4476 if (op->status == nfserr_resource ||
4477 op->status == nfserr_rep_too_big ||
4478 op->status == nfserr_rep_too_big_to_cache) {
4479
4480
4481
4482
4483
4484
4485
4486 warn_on_nonidempotent_op(op);
4487 xdr_truncate_encode(xdr, post_err_offset);
4488 }
4489 if (so) {
4490 int len = xdr->buf->len - post_err_offset;
4491
4492 so->so_replay.rp_status = op->status;
4493 so->so_replay.rp_buflen = len;
4494 read_bytes_from_xdr_buf(xdr->buf, post_err_offset,
4495 so->so_replay.rp_buf, len);
4496 }
4497status:
4498
4499 write_bytes_to_xdr_buf(xdr->buf, post_err_offset - 4, &op->status, 4);
4500}
4501
4502
4503
4504
4505
4506
4507
4508void
4509nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op)
4510{
4511 __be32 *p;
4512 struct nfs4_replay *rp = op->replay;
4513
4514 BUG_ON(!rp);
4515
4516 p = xdr_reserve_space(xdr, 8 + rp->rp_buflen);
4517 if (!p) {
4518 WARN_ON_ONCE(1);
4519 return;
4520 }
4521 *p++ = cpu_to_be32(op->opnum);
4522 *p++ = rp->rp_status;
4523
4524 p = xdr_encode_opaque_fixed(p, rp->rp_buf, rp->rp_buflen);
4525}
4526
4527int
4528nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p)
4529{
4530 return xdr_ressize_check(rqstp, p);
4531}
4532
4533void nfsd4_release_compoundargs(struct svc_rqst *rqstp)
4534{
4535 struct nfsd4_compoundargs *args = rqstp->rq_argp;
4536
4537 if (args->ops != args->iops) {
4538 kfree(args->ops);
4539 args->ops = args->iops;
4540 }
4541 kfree(args->tmpp);
4542 args->tmpp = NULL;
4543 while (args->to_free) {
4544 struct svcxdr_tmpbuf *tb = args->to_free;
4545 args->to_free = tb->next;
4546 kfree(tb);
4547 }
4548}
4549
4550int
4551nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p)
4552{
4553 struct nfsd4_compoundargs *args = rqstp->rq_argp;
4554
4555 if (rqstp->rq_arg.head[0].iov_len % 4) {
4556
4557 dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)",
4558 __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid));
4559 return 0;
4560 }
4561 args->p = p;
4562 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
4563 args->pagelist = rqstp->rq_arg.pages;
4564 args->pagelen = rqstp->rq_arg.page_len;
4565 args->tail = false;
4566 args->tmpp = NULL;
4567 args->to_free = NULL;
4568 args->ops = args->iops;
4569 args->rqstp = rqstp;
4570
4571 return !nfsd4_decode_compound(args);
4572}
4573
4574int
4575nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p)
4576{
4577
4578
4579
4580 struct nfsd4_compoundres *resp = rqstp->rq_resp;
4581 struct xdr_buf *buf = resp->xdr.buf;
4582
4583 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +
4584 buf->tail[0].iov_len);
4585
4586 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
4587
4588 p = resp->tagp;
4589 *p++ = htonl(resp->taglen);
4590 memcpy(p, resp->tag, resp->taglen);
4591 p += XDR_QUADLEN(resp->taglen);
4592 *p++ = htonl(resp->opcnt);
4593
4594 nfsd4_sequence_done(resp);
4595 return 1;
4596}
4597
4598
4599
4600
4601
4602
4603