1/*
2 *  Server-side XDR for NFSv4
3 *
4 *  Copyright (c) 2002 The Regents of the University of Michigan.
5 *  All rights reserved.
6 *
7 *  Kendrick Smith <kmsmith@umich.edu>
8 *  Andy Adamson   <andros@umich.edu>
9 *
10 *  Redistribution and use in source and binary forms, with or without
11 *  modification, are permitted provided that the following conditions
12 *  are met:
13 *
14 *  1. Redistributions of source code must retain the above copyright
15 *     notice, this list of conditions and the following disclaimer.
16 *  2. Redistributions in binary form must reproduce the above copyright
17 *     notice, this list of conditions and the following disclaimer in the
18 *     documentation and/or other materials provided with the distribution.
19 *  3. Neither the name of the University nor the names of its
20 *     contributors may be used to endorse or promote products derived
21 *     from this software without specific prior written permission.
22 *
23 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 *
35 * TODO: Neil Brown made the following observation:  We currently
36 * initially reserve NFSD_BUFSIZE space on the transmit queue and
37 * never release any of that until the request is complete.
38 * It would be good to calculate a new maximum response size while
39 * decoding the COMPOUND, and call svc_reserve with this number
40 * at the end of nfs4svc_decode_compoundargs.
41 */
42
43#include <linux/slab.h>
44#include <linux/namei.h>
45#include <linux/statfs.h>
46#include <linux/utsname.h>
47#include <linux/nfsd_idmap.h>
48#include <linux/nfs4_acl.h>
49#include <linux/sunrpc/svcauth_gss.h>
50
51#include "xdr4.h"
52#include "vfs.h"
53
54#define NFSDDBG_FACILITY		NFSDDBG_XDR
55
56/*
57 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
58 * directory in order to indicate to the client that a filesystem boundary is present
59 * We use a fixed fsid for a referral
60 */
61#define NFS4_REFERRAL_FSID_MAJOR	0x8000000ULL
62#define NFS4_REFERRAL_FSID_MINOR	0x8000000ULL
63
64static __be32
65check_filename(char *str, int len, __be32 err)
66{
67	int i;
68
69	if (len == 0)
70		return nfserr_inval;
71	if (isdotent(str, len))
72		return err;
73	for (i = 0; i < len; i++)
74		if (str[i] == '/')
75			return err;
76	return 0;
77}
78
79#define DECODE_HEAD				\
80	__be32 *p;				\
81	__be32 status
82#define DECODE_TAIL				\
83	status = 0;				\
84out:						\
85	return status;				\
86xdr_error:					\
87	dprintk("NFSD: xdr error (%s:%d)\n",	\
88			__FILE__, __LINE__);	\
89	status = nfserr_bad_xdr;		\
90	goto out
91
92#define READ32(x)         (x) = ntohl(*p++)
93#define READ64(x)         do {			\
94	(x) = (u64)ntohl(*p++) << 32;		\
95	(x) |= ntohl(*p++);			\
96} while (0)
97#define READTIME(x)       do {			\
98	p++;					\
99	(x) = ntohl(*p++);			\
100	p++;					\
101} while (0)
102#define READMEM(x,nbytes) do {			\
103	x = (char *)p;				\
104	p += XDR_QUADLEN(nbytes);		\
105} while (0)
106#define SAVEMEM(x,nbytes) do {			\
107	if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
108 		savemem(argp, p, nbytes) :	\
109 		(char *)p)) {			\
110		dprintk("NFSD: xdr error (%s:%d)\n", \
111				__FILE__, __LINE__); \
112		goto xdr_error;			\
113		}				\
114	p += XDR_QUADLEN(nbytes);		\
115} while (0)
116#define COPYMEM(x,nbytes) do {			\
117	memcpy((x), p, nbytes);			\
118	p += XDR_QUADLEN(nbytes);		\
119} while (0)
120
121/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
122#define READ_BUF(nbytes)  do {			\
123	if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) {	\
124		p = argp->p;			\
125		argp->p += XDR_QUADLEN(nbytes);	\
126	} else if (!(p = read_buf(argp, nbytes))) { \
127		dprintk("NFSD: xdr error (%s:%d)\n", \
128				__FILE__, __LINE__); \
129		goto xdr_error;			\
130	}					\
131} while (0)
132
133static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
134{
135	/* We want more bytes than seem to be available.
136	 * Maybe we need a new page, maybe we have just run out
137	 */
138	unsigned int avail = (char *)argp->end - (char *)argp->p;
139	__be32 *p;
140	if (avail + argp->pagelen < nbytes)
141		return NULL;
142	if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
143		return NULL;
144	/* ok, we can do it with the current plus the next page */
145	if (nbytes <= sizeof(argp->tmp))
146		p = argp->tmp;
147	else {
148		kfree(argp->tmpp);
149		p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
150		if (!p)
151			return NULL;
152
153	}
154	/*
155	 * The following memcpy is safe because read_buf is always
156	 * called with nbytes > avail, and the two cases above both
157	 * guarantee p points to at least nbytes bytes.
158	 */
159	memcpy(p, argp->p, avail);
160	/* step to next page */
161	argp->p = page_address(argp->pagelist[0]);
162	argp->pagelist++;
163	if (argp->pagelen < PAGE_SIZE) {
164		argp->end = argp->p + (argp->pagelen>>2);
165		argp->pagelen = 0;
166	} else {
167		argp->end = argp->p + (PAGE_SIZE>>2);
168		argp->pagelen -= PAGE_SIZE;
169	}
170	memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
171	argp->p += XDR_QUADLEN(nbytes - avail);
172	return p;
173}
174
175static int zero_clientid(clientid_t *clid)
176{
177	return (clid->cl_boot == 0) && (clid->cl_id == 0);
178}
179
180static int
181defer_free(struct nfsd4_compoundargs *argp,
182		void (*release)(const void *), void *p)
183{
184	struct tmpbuf *tb;
185
186	tb = kmalloc(sizeof(*tb), GFP_KERNEL);
187	if (!tb)
188		return -ENOMEM;
189	tb->buf = p;
190	tb->release = release;
191	tb->next = argp->to_free;
192	argp->to_free = tb;
193	return 0;
194}
195
196static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
197{
198	if (p == argp->tmp) {
199		p = kmalloc(nbytes, GFP_KERNEL);
200		if (!p)
201			return NULL;
202		memcpy(p, argp->tmp, nbytes);
203	} else {
204		BUG_ON(p != argp->tmpp);
205		argp->tmpp = NULL;
206	}
207	if (defer_free(argp, kfree, p)) {
208		kfree(p);
209		return NULL;
210	} else
211		return (char *)p;
212}
213
214static __be32
215nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
216{
217	u32 bmlen;
218	DECODE_HEAD;
219
220	bmval[0] = 0;
221	bmval[1] = 0;
222	bmval[2] = 0;
223
224	READ_BUF(4);
225	READ32(bmlen);
226	if (bmlen > 1000)
227		goto xdr_error;
228
229	READ_BUF(bmlen << 2);
230	if (bmlen > 0)
231		READ32(bmval[0]);
232	if (bmlen > 1)
233		READ32(bmval[1]);
234	if (bmlen > 2)
235		READ32(bmval[2]);
236
237	DECODE_TAIL;
238}
239
240static __be32
241nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
242		   struct iattr *iattr, struct nfs4_acl **acl)
243{
244	int expected_len, len = 0;
245	u32 dummy32;
246	char *buf;
247	int host_err;
248
249	DECODE_HEAD;
250	iattr->ia_valid = 0;
251	if ((status = nfsd4_decode_bitmap(argp, bmval)))
252		return status;
253
254	READ_BUF(4);
255	READ32(expected_len);
256
257	if (bmval[0] & FATTR4_WORD0_SIZE) {
258		READ_BUF(8);
259		len += 8;
260		READ64(iattr->ia_size);
261		iattr->ia_valid |= ATTR_SIZE;
262	}
263	if (bmval[0] & FATTR4_WORD0_ACL) {
264		int nace;
265		struct nfs4_ace *ace;
266
267		READ_BUF(4); len += 4;
268		READ32(nace);
269
270		if (nace > NFS4_ACL_MAX)
271			return nfserr_resource;
272
273		*acl = nfs4_acl_new(nace);
274		if (*acl == NULL) {
275			host_err = -ENOMEM;
276			goto out_nfserr;
277		}
278		defer_free(argp, kfree, *acl);
279
280		(*acl)->naces = nace;
281		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
282			READ_BUF(16); len += 16;
283			READ32(ace->type);
284			READ32(ace->flag);
285			READ32(ace->access_mask);
286			READ32(dummy32);
287			READ_BUF(dummy32);
288			len += XDR_QUADLEN(dummy32) << 2;
289			READMEM(buf, dummy32);
290			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
291			host_err = 0;
292			if (ace->whotype != NFS4_ACL_WHO_NAMED)
293				ace->who = 0;
294			else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
295				host_err = nfsd_map_name_to_gid(argp->rqstp,
296						buf, dummy32, &ace->who);
297			else
298				host_err = nfsd_map_name_to_uid(argp->rqstp,
299						buf, dummy32, &ace->who);
300			if (host_err)
301				goto out_nfserr;
302		}
303	} else
304		*acl = NULL;
305	if (bmval[1] & FATTR4_WORD1_MODE) {
306		READ_BUF(4);
307		len += 4;
308		READ32(iattr->ia_mode);
309		iattr->ia_mode &= (S_IFMT | S_IALLUGO);
310		iattr->ia_valid |= ATTR_MODE;
311	}
312	if (bmval[1] & FATTR4_WORD1_OWNER) {
313		READ_BUF(4);
314		len += 4;
315		READ32(dummy32);
316		READ_BUF(dummy32);
317		len += (XDR_QUADLEN(dummy32) << 2);
318		READMEM(buf, dummy32);
319		if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
320			goto out_nfserr;
321		iattr->ia_valid |= ATTR_UID;
322	}
323	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
324		READ_BUF(4);
325		len += 4;
326		READ32(dummy32);
327		READ_BUF(dummy32);
328		len += (XDR_QUADLEN(dummy32) << 2);
329		READMEM(buf, dummy32);
330		if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
331			goto out_nfserr;
332		iattr->ia_valid |= ATTR_GID;
333	}
334	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
335		READ_BUF(4);
336		len += 4;
337		READ32(dummy32);
338		switch (dummy32) {
339		case NFS4_SET_TO_CLIENT_TIME:
340			/* We require the high 32 bits of 'seconds' to be 0, and we ignore
341			   all 32 bits of 'nseconds'. */
342			READ_BUF(12);
343			len += 12;
344			READ32(dummy32);
345			if (dummy32)
346				return nfserr_inval;
347			READ32(iattr->ia_atime.tv_sec);
348			READ32(iattr->ia_atime.tv_nsec);
349			if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
350				return nfserr_inval;
351			iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
352			break;
353		case NFS4_SET_TO_SERVER_TIME:
354			iattr->ia_valid |= ATTR_ATIME;
355			break;
356		default:
357			goto xdr_error;
358		}
359	}
360	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
361		READ_BUF(4);
362		len += 4;
363		READ32(dummy32);
364		switch (dummy32) {
365		case NFS4_SET_TO_CLIENT_TIME:
366			/* We require the high 32 bits of 'seconds' to be 0, and we ignore
367			   all 32 bits of 'nseconds'. */
368			READ_BUF(12);
369			len += 12;
370			READ32(dummy32);
371			if (dummy32)
372				return nfserr_inval;
373			READ32(iattr->ia_mtime.tv_sec);
374			READ32(iattr->ia_mtime.tv_nsec);
375			if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
376				return nfserr_inval;
377			iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
378			break;
379		case NFS4_SET_TO_SERVER_TIME:
380			iattr->ia_valid |= ATTR_MTIME;
381			break;
382		default:
383			goto xdr_error;
384		}
385	}
386	if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
387	    || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
388	    || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2)
389		READ_BUF(expected_len - len);
390	else if (len != expected_len)
391		goto xdr_error;
392
393	DECODE_TAIL;
394
395out_nfserr:
396	status = nfserrno(host_err);
397	goto out;
398}
399
400static __be32
401nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
402{
403	DECODE_HEAD;
404
405	READ_BUF(sizeof(stateid_t));
406	READ32(sid->si_generation);
407	COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
408
409	DECODE_TAIL;
410}
411
412static __be32
413nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
414{
415	DECODE_HEAD;
416
417	READ_BUF(4);
418	READ32(access->ac_req_access);
419
420	DECODE_TAIL;
421}
422
423static __be32
424nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
425{
426	DECODE_HEAD;
427
428	close->cl_stateowner = NULL;
429	READ_BUF(4);
430	READ32(close->cl_seqid);
431	return nfsd4_decode_stateid(argp, &close->cl_stateid);
432
433	DECODE_TAIL;
434}
435
436
437static __be32
438nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
439{
440	DECODE_HEAD;
441
442	READ_BUF(12);
443	READ64(commit->co_offset);
444	READ32(commit->co_count);
445
446	DECODE_TAIL;
447}
448
449static __be32
450nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
451{
452	DECODE_HEAD;
453
454	READ_BUF(4);
455	READ32(create->cr_type);
456	switch (create->cr_type) {
457	case NF4LNK:
458		READ_BUF(4);
459		READ32(create->cr_linklen);
460		READ_BUF(create->cr_linklen);
461		SAVEMEM(create->cr_linkname, create->cr_linklen);
462		break;
463	case NF4BLK:
464	case NF4CHR:
465		READ_BUF(8);
466		READ32(create->cr_specdata1);
467		READ32(create->cr_specdata2);
468		break;
469	case NF4SOCK:
470	case NF4FIFO:
471	case NF4DIR:
472	default:
473		break;
474	}
475
476	READ_BUF(4);
477	READ32(create->cr_namelen);
478	READ_BUF(create->cr_namelen);
479	SAVEMEM(create->cr_name, create->cr_namelen);
480	if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
481		return status;
482
483	status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
484				    &create->cr_acl);
485	if (status)
486		goto out;
487
488	DECODE_TAIL;
489}
490
491static inline __be32
492nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
493{
494	return nfsd4_decode_stateid(argp, &dr->dr_stateid);
495}
496
497static inline __be32
498nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
499{
500	return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
501}
502
503static __be32
504nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
505{
506	DECODE_HEAD;
507
508	READ_BUF(4);
509	READ32(link->li_namelen);
510	READ_BUF(link->li_namelen);
511	SAVEMEM(link->li_name, link->li_namelen);
512	if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
513		return status;
514
515	DECODE_TAIL;
516}
517
518static __be32
519nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
520{
521	DECODE_HEAD;
522
523	lock->lk_replay_owner = NULL;
524	/*
525	* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
526	*/
527	READ_BUF(28);
528	READ32(lock->lk_type);
529	if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
530		goto xdr_error;
531	READ32(lock->lk_reclaim);
532	READ64(lock->lk_offset);
533	READ64(lock->lk_length);
534	READ32(lock->lk_is_new);
535
536	if (lock->lk_is_new) {
537		READ_BUF(4);
538		READ32(lock->lk_new_open_seqid);
539		status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
540		if (status)
541			return status;
542		READ_BUF(8 + sizeof(clientid_t));
543		READ32(lock->lk_new_lock_seqid);
544		COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
545		READ32(lock->lk_new_owner.len);
546		READ_BUF(lock->lk_new_owner.len);
547		READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
548	} else {
549		status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
550		if (status)
551			return status;
552		READ_BUF(4);
553		READ32(lock->lk_old_lock_seqid);
554	}
555
556	DECODE_TAIL;
557}
558
559static __be32
560nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
561{
562	DECODE_HEAD;
563
564	READ_BUF(32);
565	READ32(lockt->lt_type);
566	if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
567		goto xdr_error;
568	READ64(lockt->lt_offset);
569	READ64(lockt->lt_length);
570	COPYMEM(&lockt->lt_clientid, 8);
571	READ32(lockt->lt_owner.len);
572	READ_BUF(lockt->lt_owner.len);
573	READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
574
575	if (argp->minorversion && !zero_clientid(&lockt->lt_clientid))
576		return nfserr_inval;
577	DECODE_TAIL;
578}
579
580static __be32
581nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
582{
583	DECODE_HEAD;
584
585	locku->lu_stateowner = NULL;
586	READ_BUF(8);
587	READ32(locku->lu_type);
588	if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
589		goto xdr_error;
590	READ32(locku->lu_seqid);
591	status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
592	if (status)
593		return status;
594	READ_BUF(16);
595	READ64(locku->lu_offset);
596	READ64(locku->lu_length);
597
598	DECODE_TAIL;
599}
600
601static __be32
602nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
603{
604	DECODE_HEAD;
605
606	READ_BUF(4);
607	READ32(lookup->lo_len);
608	READ_BUF(lookup->lo_len);
609	SAVEMEM(lookup->lo_name, lookup->lo_len);
610	if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
611		return status;
612
613	DECODE_TAIL;
614}
615
616static __be32
617nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
618{
619	DECODE_HEAD;
620
621	memset(open->op_bmval, 0, sizeof(open->op_bmval));
622	open->op_iattr.ia_valid = 0;
623	open->op_stateowner = NULL;
624
625	/* seqid, share_access, share_deny, clientid, ownerlen */
626	READ_BUF(16 + sizeof(clientid_t));
627	READ32(open->op_seqid);
628	READ32(open->op_share_access);
629	READ32(open->op_share_deny);
630	COPYMEM(&open->op_clientid, sizeof(clientid_t));
631	READ32(open->op_owner.len);
632
633	/* owner, open_flag */
634	READ_BUF(open->op_owner.len + 4);
635	SAVEMEM(open->op_owner.data, open->op_owner.len);
636	READ32(open->op_create);
637	switch (open->op_create) {
638	case NFS4_OPEN_NOCREATE:
639		break;
640	case NFS4_OPEN_CREATE:
641		READ_BUF(4);
642		READ32(open->op_createmode);
643		switch (open->op_createmode) {
644		case NFS4_CREATE_UNCHECKED:
645		case NFS4_CREATE_GUARDED:
646			status = nfsd4_decode_fattr(argp, open->op_bmval,
647				&open->op_iattr, &open->op_acl);
648			if (status)
649				goto out;
650			break;
651		case NFS4_CREATE_EXCLUSIVE:
652			READ_BUF(8);
653			COPYMEM(open->op_verf.data, 8);
654			break;
655		case NFS4_CREATE_EXCLUSIVE4_1:
656			if (argp->minorversion < 1)
657				goto xdr_error;
658			READ_BUF(8);
659			COPYMEM(open->op_verf.data, 8);
660			status = nfsd4_decode_fattr(argp, open->op_bmval,
661				&open->op_iattr, &open->op_acl);
662			if (status)
663				goto out;
664			break;
665		default:
666			goto xdr_error;
667		}
668		break;
669	default:
670		goto xdr_error;
671	}
672
673	/* open_claim */
674	READ_BUF(4);
675	READ32(open->op_claim_type);
676	switch (open->op_claim_type) {
677	case NFS4_OPEN_CLAIM_NULL:
678	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
679		READ_BUF(4);
680		READ32(open->op_fname.len);
681		READ_BUF(open->op_fname.len);
682		SAVEMEM(open->op_fname.data, open->op_fname.len);
683		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
684			return status;
685		break;
686	case NFS4_OPEN_CLAIM_PREVIOUS:
687		READ_BUF(4);
688		READ32(open->op_delegate_type);
689		break;
690	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
691		status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
692		if (status)
693			return status;
694		READ_BUF(4);
695		READ32(open->op_fname.len);
696		READ_BUF(open->op_fname.len);
697		SAVEMEM(open->op_fname.data, open->op_fname.len);
698		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
699			return status;
700		break;
701	default:
702		goto xdr_error;
703	}
704
705	DECODE_TAIL;
706}
707
708static __be32
709nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
710{
711	DECODE_HEAD;
712
713	open_conf->oc_stateowner = NULL;
714	status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
715	if (status)
716		return status;
717	READ_BUF(4);
718	READ32(open_conf->oc_seqid);
719
720	DECODE_TAIL;
721}
722
723static __be32
724nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
725{
726	DECODE_HEAD;
727
728	open_down->od_stateowner = NULL;
729	status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
730	if (status)
731		return status;
732	READ_BUF(12);
733	READ32(open_down->od_seqid);
734	READ32(open_down->od_share_access);
735	READ32(open_down->od_share_deny);
736
737	DECODE_TAIL;
738}
739
740static __be32
741nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
742{
743	DECODE_HEAD;
744
745	READ_BUF(4);
746	READ32(putfh->pf_fhlen);
747	if (putfh->pf_fhlen > NFS4_FHSIZE)
748		goto xdr_error;
749	READ_BUF(putfh->pf_fhlen);
750	SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
751
752	DECODE_TAIL;
753}
754
755static __be32
756nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
757{
758	DECODE_HEAD;
759
760	status = nfsd4_decode_stateid(argp, &read->rd_stateid);
761	if (status)
762		return status;
763	READ_BUF(12);
764	READ64(read->rd_offset);
765	READ32(read->rd_length);
766
767	DECODE_TAIL;
768}
769
770static __be32
771nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
772{
773	DECODE_HEAD;
774
775	READ_BUF(24);
776	READ64(readdir->rd_cookie);
777	COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
778	READ32(readdir->rd_dircount);    /* just in case you needed a useless field... */
779	READ32(readdir->rd_maxcount);
780	if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
781		goto out;
782
783	DECODE_TAIL;
784}
785
786static __be32
787nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
788{
789	DECODE_HEAD;
790
791	READ_BUF(4);
792	READ32(remove->rm_namelen);
793	READ_BUF(remove->rm_namelen);
794	SAVEMEM(remove->rm_name, remove->rm_namelen);
795	if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
796		return status;
797
798	DECODE_TAIL;
799}
800
801static __be32
802nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
803{
804	DECODE_HEAD;
805
806	READ_BUF(4);
807	READ32(rename->rn_snamelen);
808	READ_BUF(rename->rn_snamelen + 4);
809	SAVEMEM(rename->rn_sname, rename->rn_snamelen);
810	READ32(rename->rn_tnamelen);
811	READ_BUF(rename->rn_tnamelen);
812	SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
813	if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
814		return status;
815	if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
816		return status;
817
818	DECODE_TAIL;
819}
820
821static __be32
822nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
823{
824	DECODE_HEAD;
825
826	READ_BUF(sizeof(clientid_t));
827	COPYMEM(clientid, sizeof(clientid_t));
828
829	DECODE_TAIL;
830}
831
832static __be32
833nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
834		     struct nfsd4_secinfo *secinfo)
835{
836	DECODE_HEAD;
837
838	READ_BUF(4);
839	READ32(secinfo->si_namelen);
840	READ_BUF(secinfo->si_namelen);
841	SAVEMEM(secinfo->si_name, secinfo->si_namelen);
842	status = check_filename(secinfo->si_name, secinfo->si_namelen,
843								nfserr_noent);
844	if (status)
845		return status;
846	DECODE_TAIL;
847}
848
849static __be32
850nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
851{
852	__be32 status;
853
854	status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
855	if (status)
856		return status;
857	return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
858				  &setattr->sa_acl);
859}
860
861static __be32
862nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
863{
864	DECODE_HEAD;
865
866	READ_BUF(12);
867	COPYMEM(setclientid->se_verf.data, 8);
868	READ32(setclientid->se_namelen);
869
870	READ_BUF(setclientid->se_namelen + 8);
871	SAVEMEM(setclientid->se_name, setclientid->se_namelen);
872	READ32(setclientid->se_callback_prog);
873	READ32(setclientid->se_callback_netid_len);
874
875	READ_BUF(setclientid->se_callback_netid_len + 4);
876	SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
877	READ32(setclientid->se_callback_addr_len);
878
879	READ_BUF(setclientid->se_callback_addr_len + 4);
880	SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
881	READ32(setclientid->se_callback_ident);
882
883	DECODE_TAIL;
884}
885
886static __be32
887nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
888{
889	DECODE_HEAD;
890
891	READ_BUF(8 + sizeof(nfs4_verifier));
892	COPYMEM(&scd_c->sc_clientid, 8);
893	COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
894
895	DECODE_TAIL;
896}
897
898/* Also used for NVERIFY */
899static __be32
900nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
901{
902	DECODE_HEAD;
903
904	if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
905		goto out;
906
907	/* For convenience's sake, we compare raw xdr'd attributes in
908	 * nfsd4_proc_verify; however we still decode here just to return
909	 * correct error in case of bad xdr. */
910	READ_BUF(4);
911	READ32(verify->ve_attrlen);
912	READ_BUF(verify->ve_attrlen);
913	SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
914
915	DECODE_TAIL;
916}
917
918static __be32
919nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
920{
921	int avail;
922	int v;
923	int len;
924	DECODE_HEAD;
925
926	status = nfsd4_decode_stateid(argp, &write->wr_stateid);
927	if (status)
928		return status;
929	READ_BUF(16);
930	READ64(write->wr_offset);
931	READ32(write->wr_stable_how);
932	if (write->wr_stable_how > 2)
933		goto xdr_error;
934	READ32(write->wr_buflen);
935
936	/* Sorry .. no magic macros for this.. *
937	 * READ_BUF(write->wr_buflen);
938	 * SAVEMEM(write->wr_buf, write->wr_buflen);
939	 */
940	avail = (char*)argp->end - (char*)argp->p;
941	if (avail + argp->pagelen < write->wr_buflen) {
942		dprintk("NFSD: xdr error (%s:%d)\n",
943				__FILE__, __LINE__);
944		goto xdr_error;
945	}
946	argp->rqstp->rq_vec[0].iov_base = p;
947	argp->rqstp->rq_vec[0].iov_len = avail;
948	v = 0;
949	len = write->wr_buflen;
950	while (len > argp->rqstp->rq_vec[v].iov_len) {
951		len -= argp->rqstp->rq_vec[v].iov_len;
952		v++;
953		argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]);
954		argp->pagelist++;
955		if (argp->pagelen >= PAGE_SIZE) {
956			argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE;
957			argp->pagelen -= PAGE_SIZE;
958		} else {
959			argp->rqstp->rq_vec[v].iov_len = argp->pagelen;
960			argp->pagelen -= len;
961		}
962	}
963	argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
964	argp->p = (__be32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
965	argp->rqstp->rq_vec[v].iov_len = len;
966	write->wr_vlen = v+1;
967
968	DECODE_TAIL;
969}
970
971static __be32
972nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
973{
974	DECODE_HEAD;
975
976	READ_BUF(12);
977	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
978	READ32(rlockowner->rl_owner.len);
979	READ_BUF(rlockowner->rl_owner.len);
980	READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
981
982	if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
983		return nfserr_inval;
984	DECODE_TAIL;
985}
986
987static __be32
988nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
989			 struct nfsd4_exchange_id *exid)
990{
991	int dummy;
992	DECODE_HEAD;
993
994	READ_BUF(NFS4_VERIFIER_SIZE);
995	COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
996
997	READ_BUF(4);
998	READ32(exid->clname.len);
999
1000	READ_BUF(exid->clname.len);
1001	SAVEMEM(exid->clname.data, exid->clname.len);
1002
1003	READ_BUF(4);
1004	READ32(exid->flags);
1005
1006	/* Ignore state_protect4_a */
1007	READ_BUF(4);
1008	READ32(exid->spa_how);
1009	switch (exid->spa_how) {
1010	case SP4_NONE:
1011		break;
1012	case SP4_MACH_CRED:
1013		/* spo_must_enforce */
1014		READ_BUF(4);
1015		READ32(dummy);
1016		READ_BUF(dummy * 4);
1017		p += dummy;
1018
1019		/* spo_must_allow */
1020		READ_BUF(4);
1021		READ32(dummy);
1022		READ_BUF(dummy * 4);
1023		p += dummy;
1024		break;
1025	case SP4_SSV:
1026		/* ssp_ops */
1027		READ_BUF(4);
1028		READ32(dummy);
1029		READ_BUF(dummy * 4);
1030		p += dummy;
1031
1032		READ_BUF(4);
1033		READ32(dummy);
1034		READ_BUF(dummy * 4);
1035		p += dummy;
1036
1037		/* ssp_hash_algs<> */
1038		READ_BUF(4);
1039		READ32(dummy);
1040		READ_BUF(dummy);
1041		p += XDR_QUADLEN(dummy);
1042
1043		/* ssp_encr_algs<> */
1044		READ_BUF(4);
1045		READ32(dummy);
1046		READ_BUF(dummy);
1047		p += XDR_QUADLEN(dummy);
1048
1049		/* ssp_window and ssp_num_gss_handles */
1050		READ_BUF(8);
1051		READ32(dummy);
1052		READ32(dummy);
1053		break;
1054	default:
1055		goto xdr_error;
1056	}
1057
1058	/* Ignore Implementation ID */
1059	READ_BUF(4);    /* nfs_impl_id4 array length */
1060	READ32(dummy);
1061
1062	if (dummy > 1)
1063		goto xdr_error;
1064
1065	if (dummy == 1) {
1066		/* nii_domain */
1067		READ_BUF(4);
1068		READ32(dummy);
1069		READ_BUF(dummy);
1070		p += XDR_QUADLEN(dummy);
1071
1072		/* nii_name */
1073		READ_BUF(4);
1074		READ32(dummy);
1075		READ_BUF(dummy);
1076		p += XDR_QUADLEN(dummy);
1077
1078		/* nii_date */
1079		READ_BUF(12);
1080		p += 3;
1081	}
1082	DECODE_TAIL;
1083}
1084
1085static __be32
1086nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1087			    struct nfsd4_create_session *sess)
1088{
1089	DECODE_HEAD;
1090
1091	u32 dummy;
1092	char *machine_name;
1093	int i;
1094	int nr_secflavs;
1095
1096	READ_BUF(16);
1097	COPYMEM(&sess->clientid, 8);
1098	READ32(sess->seqid);
1099	READ32(sess->flags);
1100
1101	/* Fore channel attrs */
1102	READ_BUF(28);
1103	READ32(dummy); /* headerpadsz is always 0 */
1104	READ32(sess->fore_channel.maxreq_sz);
1105	READ32(sess->fore_channel.maxresp_sz);
1106	READ32(sess->fore_channel.maxresp_cached);
1107	READ32(sess->fore_channel.maxops);
1108	READ32(sess->fore_channel.maxreqs);
1109	READ32(sess->fore_channel.nr_rdma_attrs);
1110	if (sess->fore_channel.nr_rdma_attrs == 1) {
1111		READ_BUF(4);
1112		READ32(sess->fore_channel.rdma_attrs);
1113	} else if (sess->fore_channel.nr_rdma_attrs > 1) {
1114		dprintk("Too many fore channel attr bitmaps!\n");
1115		goto xdr_error;
1116	}
1117
1118	/* Back channel attrs */
1119	READ_BUF(28);
1120	READ32(dummy); /* headerpadsz is always 0 */
1121	READ32(sess->back_channel.maxreq_sz);
1122	READ32(sess->back_channel.maxresp_sz);
1123	READ32(sess->back_channel.maxresp_cached);
1124	READ32(sess->back_channel.maxops);
1125	READ32(sess->back_channel.maxreqs);
1126	READ32(sess->back_channel.nr_rdma_attrs);
1127	if (sess->back_channel.nr_rdma_attrs == 1) {
1128		READ_BUF(4);
1129		READ32(sess->back_channel.rdma_attrs);
1130	} else if (sess->back_channel.nr_rdma_attrs > 1) {
1131		dprintk("Too many back channel attr bitmaps!\n");
1132		goto xdr_error;
1133	}
1134
1135	READ_BUF(8);
1136	READ32(sess->callback_prog);
1137
1138	/* callback_sec_params4 */
1139	READ32(nr_secflavs);
1140	for (i = 0; i < nr_secflavs; ++i) {
1141		READ_BUF(4);
1142		READ32(dummy);
1143		switch (dummy) {
1144		case RPC_AUTH_NULL:
1145			/* Nothing to read */
1146			break;
1147		case RPC_AUTH_UNIX:
1148			READ_BUF(8);
1149			/* stamp */
1150			READ32(dummy);
1151
1152			/* machine name */
1153			READ32(dummy);
1154			READ_BUF(dummy);
1155			SAVEMEM(machine_name, dummy);
1156
1157			/* uid, gid */
1158			READ_BUF(8);
1159			READ32(sess->uid);
1160			READ32(sess->gid);
1161
1162			/* more gids */
1163			READ_BUF(4);
1164			READ32(dummy);
1165			READ_BUF(dummy * 4);
1166			for (i = 0; i < dummy; ++i)
1167				READ32(dummy);
1168			break;
1169		case RPC_AUTH_GSS:
1170			dprintk("RPC_AUTH_GSS callback secflavor "
1171				"not supported!\n");
1172			READ_BUF(8);
1173			/* gcbp_service */
1174			READ32(dummy);
1175			/* gcbp_handle_from_server */
1176			READ32(dummy);
1177			READ_BUF(dummy);
1178			p += XDR_QUADLEN(dummy);
1179			/* gcbp_handle_from_client */
1180			READ_BUF(4);
1181			READ32(dummy);
1182			READ_BUF(dummy);
1183			p += XDR_QUADLEN(dummy);
1184			break;
1185		default:
1186			dprintk("Illegal callback secflavor\n");
1187			return nfserr_inval;
1188		}
1189	}
1190	DECODE_TAIL;
1191}
1192
1193static __be32
1194nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1195			     struct nfsd4_destroy_session *destroy_session)
1196{
1197	DECODE_HEAD;
1198	READ_BUF(NFS4_MAX_SESSIONID_LEN);
1199	COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1200
1201	DECODE_TAIL;
1202}
1203
1204static __be32
1205nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1206		      struct nfsd4_sequence *seq)
1207{
1208	DECODE_HEAD;
1209
1210	READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1211	COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1212	READ32(seq->seqid);
1213	READ32(seq->slotid);
1214	READ32(seq->maxslots);
1215	READ32(seq->cachethis);
1216
1217	DECODE_TAIL;
1218}
1219
1220static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1221{
1222	DECODE_HEAD;
1223
1224	READ_BUF(4);
1225	READ32(rc->rca_one_fs);
1226
1227	DECODE_TAIL;
1228}
1229
1230static __be32
1231nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
1232{
1233	return nfs_ok;
1234}
1235
1236static __be32
1237nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
1238{
1239	return nfserr_notsupp;
1240}
1241
1242typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1243
1244static nfsd4_dec nfsd4_dec_ops[] = {
1245	[OP_ACCESS]		= (nfsd4_dec)nfsd4_decode_access,
1246	[OP_CLOSE]		= (nfsd4_dec)nfsd4_decode_close,
1247	[OP_COMMIT]		= (nfsd4_dec)nfsd4_decode_commit,
1248	[OP_CREATE]		= (nfsd4_dec)nfsd4_decode_create,
1249	[OP_DELEGPURGE]		= (nfsd4_dec)nfsd4_decode_notsupp,
1250	[OP_DELEGRETURN]	= (nfsd4_dec)nfsd4_decode_delegreturn,
1251	[OP_GETATTR]		= (nfsd4_dec)nfsd4_decode_getattr,
1252	[OP_GETFH]		= (nfsd4_dec)nfsd4_decode_noop,
1253	[OP_LINK]		= (nfsd4_dec)nfsd4_decode_link,
1254	[OP_LOCK]		= (nfsd4_dec)nfsd4_decode_lock,
1255	[OP_LOCKT]		= (nfsd4_dec)nfsd4_decode_lockt,
1256	[OP_LOCKU]		= (nfsd4_dec)nfsd4_decode_locku,
1257	[OP_LOOKUP]		= (nfsd4_dec)nfsd4_decode_lookup,
1258	[OP_LOOKUPP]		= (nfsd4_dec)nfsd4_decode_noop,
1259	[OP_NVERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
1260	[OP_OPEN]		= (nfsd4_dec)nfsd4_decode_open,
1261	[OP_OPENATTR]		= (nfsd4_dec)nfsd4_decode_notsupp,
1262	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_open_confirm,
1263	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
1264	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
1265	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_noop,
1266	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
1267	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
1268	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
1269	[OP_READLINK]		= (nfsd4_dec)nfsd4_decode_noop,
1270	[OP_REMOVE]		= (nfsd4_dec)nfsd4_decode_remove,
1271	[OP_RENAME]		= (nfsd4_dec)nfsd4_decode_rename,
1272	[OP_RENEW]		= (nfsd4_dec)nfsd4_decode_renew,
1273	[OP_RESTOREFH]		= (nfsd4_dec)nfsd4_decode_noop,
1274	[OP_SAVEFH]		= (nfsd4_dec)nfsd4_decode_noop,
1275	[OP_SECINFO]		= (nfsd4_dec)nfsd4_decode_secinfo,
1276	[OP_SETATTR]		= (nfsd4_dec)nfsd4_decode_setattr,
1277	[OP_SETCLIENTID]	= (nfsd4_dec)nfsd4_decode_setclientid,
1278	[OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
1279	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
1280	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
1281	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_release_lockowner,
1282};
1283
1284static nfsd4_dec nfsd41_dec_ops[] = {
1285	[OP_ACCESS]		= (nfsd4_dec)nfsd4_decode_access,
1286	[OP_CLOSE]		= (nfsd4_dec)nfsd4_decode_close,
1287	[OP_COMMIT]		= (nfsd4_dec)nfsd4_decode_commit,
1288	[OP_CREATE]		= (nfsd4_dec)nfsd4_decode_create,
1289	[OP_DELEGPURGE]		= (nfsd4_dec)nfsd4_decode_notsupp,
1290	[OP_DELEGRETURN]	= (nfsd4_dec)nfsd4_decode_delegreturn,
1291	[OP_GETATTR]		= (nfsd4_dec)nfsd4_decode_getattr,
1292	[OP_GETFH]		= (nfsd4_dec)nfsd4_decode_noop,
1293	[OP_LINK]		= (nfsd4_dec)nfsd4_decode_link,
1294	[OP_LOCK]		= (nfsd4_dec)nfsd4_decode_lock,
1295	[OP_LOCKT]		= (nfsd4_dec)nfsd4_decode_lockt,
1296	[OP_LOCKU]		= (nfsd4_dec)nfsd4_decode_locku,
1297	[OP_LOOKUP]		= (nfsd4_dec)nfsd4_decode_lookup,
1298	[OP_LOOKUPP]		= (nfsd4_dec)nfsd4_decode_noop,
1299	[OP_NVERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
1300	[OP_OPEN]		= (nfsd4_dec)nfsd4_decode_open,
1301	[OP_OPENATTR]		= (nfsd4_dec)nfsd4_decode_notsupp,
1302	[OP_OPEN_CONFIRM]	= (nfsd4_dec)nfsd4_decode_notsupp,
1303	[OP_OPEN_DOWNGRADE]	= (nfsd4_dec)nfsd4_decode_open_downgrade,
1304	[OP_PUTFH]		= (nfsd4_dec)nfsd4_decode_putfh,
1305	[OP_PUTPUBFH]		= (nfsd4_dec)nfsd4_decode_notsupp,
1306	[OP_PUTROOTFH]		= (nfsd4_dec)nfsd4_decode_noop,
1307	[OP_READ]		= (nfsd4_dec)nfsd4_decode_read,
1308	[OP_READDIR]		= (nfsd4_dec)nfsd4_decode_readdir,
1309	[OP_READLINK]		= (nfsd4_dec)nfsd4_decode_noop,
1310	[OP_REMOVE]		= (nfsd4_dec)nfsd4_decode_remove,
1311	[OP_RENAME]		= (nfsd4_dec)nfsd4_decode_rename,
1312	[OP_RENEW]		= (nfsd4_dec)nfsd4_decode_notsupp,
1313	[OP_RESTOREFH]		= (nfsd4_dec)nfsd4_decode_noop,
1314	[OP_SAVEFH]		= (nfsd4_dec)nfsd4_decode_noop,
1315	[OP_SECINFO]		= (nfsd4_dec)nfsd4_decode_secinfo,
1316	[OP_SETATTR]		= (nfsd4_dec)nfsd4_decode_setattr,
1317	[OP_SETCLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
1318	[OP_SETCLIENTID_CONFIRM]= (nfsd4_dec)nfsd4_decode_notsupp,
1319	[OP_VERIFY]		= (nfsd4_dec)nfsd4_decode_verify,
1320	[OP_WRITE]		= (nfsd4_dec)nfsd4_decode_write,
1321	[OP_RELEASE_LOCKOWNER]	= (nfsd4_dec)nfsd4_decode_notsupp,
1322
1323	/* new operations for NFSv4.1 */
1324	[OP_BACKCHANNEL_CTL]	= (nfsd4_dec)nfsd4_decode_notsupp,
1325	[OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_notsupp,
1326	[OP_EXCHANGE_ID]	= (nfsd4_dec)nfsd4_decode_exchange_id,
1327	[OP_CREATE_SESSION]	= (nfsd4_dec)nfsd4_decode_create_session,
1328	[OP_DESTROY_SESSION]	= (nfsd4_dec)nfsd4_decode_destroy_session,
1329	[OP_FREE_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
1330	[OP_GET_DIR_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
1331	[OP_GETDEVICEINFO]	= (nfsd4_dec)nfsd4_decode_notsupp,
1332	[OP_GETDEVICELIST]	= (nfsd4_dec)nfsd4_decode_notsupp,
1333	[OP_LAYOUTCOMMIT]	= (nfsd4_dec)nfsd4_decode_notsupp,
1334	[OP_LAYOUTGET]		= (nfsd4_dec)nfsd4_decode_notsupp,
1335	[OP_LAYOUTRETURN]	= (nfsd4_dec)nfsd4_decode_notsupp,
1336	[OP_SECINFO_NO_NAME]	= (nfsd4_dec)nfsd4_decode_notsupp,
1337	[OP_SEQUENCE]		= (nfsd4_dec)nfsd4_decode_sequence,
1338	[OP_SET_SSV]		= (nfsd4_dec)nfsd4_decode_notsupp,
1339	[OP_TEST_STATEID]	= (nfsd4_dec)nfsd4_decode_notsupp,
1340	[OP_WANT_DELEGATION]	= (nfsd4_dec)nfsd4_decode_notsupp,
1341	[OP_DESTROY_CLIENTID]	= (nfsd4_dec)nfsd4_decode_notsupp,
1342	[OP_RECLAIM_COMPLETE]	= (nfsd4_dec)nfsd4_decode_reclaim_complete,
1343};
1344
1345struct nfsd4_minorversion_ops {
1346	nfsd4_dec *decoders;
1347	int nops;
1348};
1349
1350static struct nfsd4_minorversion_ops nfsd4_minorversion[] = {
1351	[0] = { nfsd4_dec_ops, ARRAY_SIZE(nfsd4_dec_ops) },
1352	[1] = { nfsd41_dec_ops, ARRAY_SIZE(nfsd41_dec_ops) },
1353};
1354
1355static __be32
1356nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1357{
1358	DECODE_HEAD;
1359	struct nfsd4_op *op;
1360	struct nfsd4_minorversion_ops *ops;
1361	int i;
1362
1363	READ_BUF(4);
1364	READ32(argp->taglen);
1365	READ_BUF(argp->taglen + 8);
1366	SAVEMEM(argp->tag, argp->taglen);
1367	READ32(argp->minorversion);
1368	READ32(argp->opcnt);
1369
1370	if (argp->taglen > NFSD4_MAX_TAGLEN)
1371		goto xdr_error;
1372	if (argp->opcnt > 100)
1373		goto xdr_error;
1374
1375	if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
1376		argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1377		if (!argp->ops) {
1378			argp->ops = argp->iops;
1379			dprintk("nfsd: couldn't allocate room for COMPOUND\n");
1380			goto xdr_error;
1381		}
1382	}
1383
1384	if (argp->minorversion >= ARRAY_SIZE(nfsd4_minorversion))
1385		argp->opcnt = 0;
1386
1387	ops = &nfsd4_minorversion[argp->minorversion];
1388	for (i = 0; i < argp->opcnt; i++) {
1389		op = &argp->ops[i];
1390		op->replay = NULL;
1391
1392		/*
1393		 * We can't use READ_BUF() here because we need to handle
1394		 * a missing opcode as an OP_WRITE + 1. So we need to check
1395		 * to see if we're truly at the end of our buffer or if there
1396		 * is another page we need to flip to.
1397		 */
1398
1399		if (argp->p == argp->end) {
1400			if (argp->pagelen < 4) {
1401				/* There isn't an opcode still on the wire */
1402				op->opnum = OP_WRITE + 1;
1403				op->status = nfserr_bad_xdr;
1404				argp->opcnt = i+1;
1405				break;
1406			}
1407
1408			/*
1409			 * False alarm. We just hit a page boundary, but there
1410			 * is still data available.  Move pointer across page
1411			 * boundary.  *snip from READ_BUF*
1412			 */
1413			argp->p = page_address(argp->pagelist[0]);
1414			argp->pagelist++;
1415			if (argp->pagelen < PAGE_SIZE) {
1416				argp->end = argp->p + (argp->pagelen>>2);
1417				argp->pagelen = 0;
1418			} else {
1419				argp->end = argp->p + (PAGE_SIZE>>2);
1420				argp->pagelen -= PAGE_SIZE;
1421			}
1422		}
1423		op->opnum = ntohl(*argp->p++);
1424
1425		if (op->opnum >= FIRST_NFS4_OP && op->opnum <= LAST_NFS4_OP)
1426			op->status = ops->decoders[op->opnum](argp, &op->u);
1427		else {
1428			op->opnum = OP_ILLEGAL;
1429			op->status = nfserr_op_illegal;
1430		}
1431
1432		if (op->status) {
1433			argp->opcnt = i+1;
1434			break;
1435		}
1436	}
1437
1438	DECODE_TAIL;
1439}
1440
1441#define WRITE32(n)               *p++ = htonl(n)
1442#define WRITE64(n)               do {				\
1443	*p++ = htonl((u32)((n) >> 32));				\
1444	*p++ = htonl((u32)(n));					\
1445} while (0)
1446#define WRITEMEM(ptr,nbytes)     do { if (nbytes > 0) {		\
1447	*(p + XDR_QUADLEN(nbytes) -1) = 0;                      \
1448	memcpy(p, ptr, nbytes);					\
1449	p += XDR_QUADLEN(nbytes);				\
1450}} while (0)
1451
1452static void write32(__be32 **p, u32 n)
1453{
1454	*(*p)++ = n;
1455}
1456
1457static void write64(__be32 **p, u64 n)
1458{
1459	write32(p, (u32)(n >> 32));
1460	write32(p, (u32)n);
1461}
1462
1463static void write_change(__be32 **p, struct kstat *stat, struct inode *inode)
1464{
1465	if (IS_I_VERSION(inode)) {
1466		write64(p, inode->i_version);
1467	} else {
1468		write32(p, stat->ctime.tv_sec);
1469		write32(p, stat->ctime.tv_nsec);
1470	}
1471}
1472
1473static void write_cinfo(__be32 **p, struct nfsd4_change_info *c)
1474{
1475	write32(p, c->atomic);
1476	if (c->change_supported) {
1477		write64(p, c->before_change);
1478		write64(p, c->after_change);
1479	} else {
1480		write32(p, c->before_ctime_sec);
1481		write32(p, c->before_ctime_nsec);
1482		write32(p, c->after_ctime_sec);
1483		write32(p, c->after_ctime_nsec);
1484	}
1485}
1486
1487#define RESERVE_SPACE(nbytes)	do {				\
1488	p = resp->p;						\
1489	BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end);		\
1490} while (0)
1491#define ADJUST_ARGS()		resp->p = p
1492
1493/*
1494 * Header routine to setup seqid operation replay cache
1495 */
1496#define ENCODE_SEQID_OP_HEAD					\
1497	__be32 *save;						\
1498								\
1499	save = resp->p;
1500
1501/*
1502 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
1503 * is where sequence id's are incremented, and the replay cache is filled.
1504 * Note that we increment sequence id's here, at the last moment, so we're sure
1505 * we know whether the error to be returned is a sequence id mutating error.
1506 */
1507
1508#define ENCODE_SEQID_OP_TAIL(stateowner) do {			\
1509	if (seqid_mutating_err(nfserr) && stateowner) { 	\
1510		stateowner->so_seqid++;				\
1511		stateowner->so_replay.rp_status = nfserr;   	\
1512		stateowner->so_replay.rp_buflen = 		\
1513			  (((char *)(resp)->p - (char *)save)); \
1514		memcpy(stateowner->so_replay.rp_buf, save,      \
1515 			stateowner->so_replay.rp_buflen); 	\
1516	} } while (0);
1517
1518/* Encode as an array of strings the string given with components
1519 * separated @sep.
1520 */
1521static __be32 nfsd4_encode_components(char sep, char *components,
1522				   __be32 **pp, int *buflen)
1523{
1524	__be32 *p = *pp;
1525	__be32 *countp = p;
1526	int strlen, count=0;
1527	char *str, *end;
1528
1529	dprintk("nfsd4_encode_components(%s)\n", components);
1530	if ((*buflen -= 4) < 0)
1531		return nfserr_resource;
1532	WRITE32(0); /* We will fill this in with @count later */
1533	end = str = components;
1534	while (*end) {
1535		for (; *end && (*end != sep); end++)
1536			; /* Point to end of component */
1537		strlen = end - str;
1538		if (strlen) {
1539			if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0)
1540				return nfserr_resource;
1541			WRITE32(strlen);
1542			WRITEMEM(str, strlen);
1543			count++;
1544		}
1545		else
1546			end++;
1547		str = end;
1548	}
1549	*pp = p;
1550	p = countp;
1551	WRITE32(count);
1552	return 0;
1553}
1554
1555/*
1556 * encode a location element of a fs_locations structure
1557 */
1558static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1559				    __be32 **pp, int *buflen)
1560{
1561	__be32 status;
1562	__be32 *p = *pp;
1563
1564	status = nfsd4_encode_components(':', location->hosts, &p, buflen);
1565	if (status)
1566		return status;
1567	status = nfsd4_encode_components('/', location->path, &p, buflen);
1568	if (status)
1569		return status;
1570	*pp = p;
1571	return 0;
1572}
1573
1574/*
1575 * Return the path to an export point in the pseudo filesystem namespace
1576 * Returned string is safe to use as long as the caller holds a reference
1577 * to @exp.
1578 */
1579static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat)
1580{
1581	struct svc_fh tmp_fh;
1582	char *path = NULL, *rootpath;
1583	size_t rootlen;
1584
1585	fh_init(&tmp_fh, NFS4_FHSIZE);
1586	*stat = exp_pseudoroot(rqstp, &tmp_fh);
1587	if (*stat)
1588		return NULL;
1589	rootpath = tmp_fh.fh_export->ex_pathname;
1590
1591	path = exp->ex_pathname;
1592
1593	rootlen = strlen(rootpath);
1594	if (strncmp(path, rootpath, rootlen)) {
1595		dprintk("nfsd: fs_locations failed;"
1596			"%s is not contained in %s\n", path, rootpath);
1597		*stat = nfserr_notsupp;
1598		path = NULL;
1599		goto out;
1600	}
1601	path += rootlen;
1602out:
1603	fh_put(&tmp_fh);
1604	return path;
1605}
1606
1607/*
1608 *  encode a fs_locations structure
1609 */
1610static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1611				     struct svc_export *exp,
1612				     __be32 **pp, int *buflen)
1613{
1614	__be32 status;
1615	int i;
1616	__be32 *p = *pp;
1617	struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1618	char *root = nfsd4_path(rqstp, exp, &status);
1619
1620	if (status)
1621		return status;
1622	status = nfsd4_encode_components('/', root, &p, buflen);
1623	if (status)
1624		return status;
1625	if ((*buflen -= 4) < 0)
1626		return nfserr_resource;
1627	WRITE32(fslocs->locations_count);
1628	for (i=0; i<fslocs->locations_count; i++) {
1629		status = nfsd4_encode_fs_location4(&fslocs->locations[i],
1630						   &p, buflen);
1631		if (status)
1632			return status;
1633	}
1634	*pp = p;
1635	return 0;
1636}
1637
1638static u32 nfs4_ftypes[16] = {
1639        NF4BAD,  NF4FIFO, NF4CHR, NF4BAD,
1640        NF4DIR,  NF4BAD,  NF4BLK, NF4BAD,
1641        NF4REG,  NF4BAD,  NF4LNK, NF4BAD,
1642        NF4SOCK, NF4BAD,  NF4LNK, NF4BAD,
1643};
1644
1645static __be32
1646nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1647			__be32 **p, int *buflen)
1648{
1649	int status;
1650
1651	if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1652		return nfserr_resource;
1653	if (whotype != NFS4_ACL_WHO_NAMED)
1654		status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1655	else if (group)
1656		status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1657	else
1658		status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1659	if (status < 0)
1660		return nfserrno(status);
1661	*p = xdr_encode_opaque(*p, NULL, status);
1662	*buflen -= (XDR_QUADLEN(status) << 2) + 4;
1663	BUG_ON(*buflen < 0);
1664	return 0;
1665}
1666
1667static inline __be32
1668nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
1669{
1670	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1671}
1672
1673static inline __be32
1674nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
1675{
1676	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1677}
1678
1679static inline __be32
1680nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1681		__be32 **p, int *buflen)
1682{
1683	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1684}
1685
1686#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
1687			      FATTR4_WORD0_RDATTR_ERROR)
1688#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1689
1690static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1691{
1692	/* As per referral draft:  */
1693	if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
1694	    *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
1695		if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
1696	            *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
1697			*rdattr_err = NFSERR_MOVED;
1698		else
1699			return nfserr_moved;
1700	}
1701	*bmval0 &= WORD0_ABSENT_FS_ATTRS;
1702	*bmval1 &= WORD1_ABSENT_FS_ATTRS;
1703	return 0;
1704}
1705
1706/*
1707 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
1708 * ourselves.
1709 *
1710 * @countp is the buffer size in _words_; upon successful return this becomes
1711 * replaced with the number of words written.
1712 */
1713__be32
1714nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1715		struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
1716		struct svc_rqst *rqstp, int ignore_crossmnt)
1717{
1718	u32 bmval0 = bmval[0];
1719	u32 bmval1 = bmval[1];
1720	u32 bmval2 = bmval[2];
1721	struct kstat stat;
1722	struct svc_fh tempfh;
1723	struct kstatfs statfs;
1724	int buflen = *countp << 2;
1725	__be32 *attrlenp;
1726	u32 dummy;
1727	u64 dummy64;
1728	u32 rdattr_err = 0;
1729	__be32 *p = buffer;
1730	__be32 status;
1731	int err;
1732	int aclsupport = 0;
1733	struct nfs4_acl *acl = NULL;
1734	struct nfsd4_compoundres *resp = rqstp->rq_resp;
1735	u32 minorversion = resp->cstate.minorversion;
1736	struct path path = {
1737		.mnt	= exp->ex_path.mnt,
1738		.dentry	= dentry,
1739	};
1740
1741	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1742	BUG_ON(bmval0 & ~nfsd_suppattrs0(minorversion));
1743	BUG_ON(bmval1 & ~nfsd_suppattrs1(minorversion));
1744	BUG_ON(bmval2 & ~nfsd_suppattrs2(minorversion));
1745
1746	if (exp->ex_fslocs.migrated) {
1747		BUG_ON(bmval[2]);
1748		status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
1749		if (status)
1750			goto out;
1751	}
1752
1753	err = vfs_getattr(exp->ex_path.mnt, dentry, &stat);
1754	if (err)
1755		goto out_nfserr;
1756	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL |
1757			FATTR4_WORD0_MAXNAME)) ||
1758	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1759		       FATTR4_WORD1_SPACE_TOTAL))) {
1760		err = vfs_statfs(&path, &statfs);
1761		if (err)
1762			goto out_nfserr;
1763	}
1764	if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
1765		fh_init(&tempfh, NFS4_FHSIZE);
1766		status = fh_compose(&tempfh, exp, dentry, NULL);
1767		if (status)
1768			goto out;
1769		fhp = &tempfh;
1770	}
1771	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1772			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
1773		err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1774		aclsupport = (err == 0);
1775		if (bmval0 & FATTR4_WORD0_ACL) {
1776			if (err == -EOPNOTSUPP)
1777				bmval0 &= ~FATTR4_WORD0_ACL;
1778			else if (err == -EINVAL) {
1779				status = nfserr_attrnotsupp;
1780				goto out;
1781			} else if (err != 0)
1782				goto out_nfserr;
1783		}
1784	}
1785	if ((buflen -= 16) < 0)
1786		goto out_resource;
1787
1788	if (unlikely(bmval2)) {
1789		WRITE32(3);
1790		WRITE32(bmval0);
1791		WRITE32(bmval1);
1792		WRITE32(bmval2);
1793	} else if (likely(bmval1)) {
1794		WRITE32(2);
1795		WRITE32(bmval0);
1796		WRITE32(bmval1);
1797	} else {
1798		WRITE32(1);
1799		WRITE32(bmval0);
1800	}
1801	attrlenp = p++;                /* to be backfilled later */
1802
1803	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1804		u32 word0 = nfsd_suppattrs0(minorversion);
1805		u32 word1 = nfsd_suppattrs1(minorversion);
1806		u32 word2 = nfsd_suppattrs2(minorversion);
1807
1808		if ((buflen -= 12) < 0)
1809			goto out_resource;
1810		if (!aclsupport)
1811			word0 &= ~FATTR4_WORD0_ACL;
1812		if (!word2) {
1813			WRITE32(2);
1814			WRITE32(word0);
1815			WRITE32(word1);
1816		} else {
1817			WRITE32(3);
1818			WRITE32(word0);
1819			WRITE32(word1);
1820			WRITE32(word2);
1821		}
1822	}
1823	if (bmval0 & FATTR4_WORD0_TYPE) {
1824		if ((buflen -= 4) < 0)
1825			goto out_resource;
1826		dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1827		if (dummy == NF4BAD)
1828			goto out_serverfault;
1829		WRITE32(dummy);
1830	}
1831	if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1832		if ((buflen -= 4) < 0)
1833			goto out_resource;
1834		if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
1835			WRITE32(NFS4_FH_PERSISTENT);
1836		else
1837			WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
1838	}
1839	if (bmval0 & FATTR4_WORD0_CHANGE) {
1840		if ((buflen -= 8) < 0)
1841			goto out_resource;
1842		write_change(&p, &stat, dentry->d_inode);
1843	}
1844	if (bmval0 & FATTR4_WORD0_SIZE) {
1845		if ((buflen -= 8) < 0)
1846			goto out_resource;
1847		WRITE64(stat.size);
1848	}
1849	if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1850		if ((buflen -= 4) < 0)
1851			goto out_resource;
1852		WRITE32(1);
1853	}
1854	if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1855		if ((buflen -= 4) < 0)
1856			goto out_resource;
1857		WRITE32(1);
1858	}
1859	if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1860		if ((buflen -= 4) < 0)
1861			goto out_resource;
1862		WRITE32(0);
1863	}
1864	if (bmval0 & FATTR4_WORD0_FSID) {
1865		if ((buflen -= 16) < 0)
1866			goto out_resource;
1867		if (exp->ex_fslocs.migrated) {
1868			WRITE64(NFS4_REFERRAL_FSID_MAJOR);
1869			WRITE64(NFS4_REFERRAL_FSID_MINOR);
1870		} else switch(fsid_source(fhp)) {
1871		case FSIDSOURCE_FSID:
1872			WRITE64((u64)exp->ex_fsid);
1873			WRITE64((u64)0);
1874			break;
1875		case FSIDSOURCE_DEV:
1876			WRITE32(0);
1877			WRITE32(MAJOR(stat.dev));
1878			WRITE32(0);
1879			WRITE32(MINOR(stat.dev));
1880			break;
1881		case FSIDSOURCE_UUID:
1882			WRITEMEM(exp->ex_uuid, 16);
1883			break;
1884		}
1885	}
1886	if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1887		if ((buflen -= 4) < 0)
1888			goto out_resource;
1889		WRITE32(0);
1890	}
1891	if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1892		if ((buflen -= 4) < 0)
1893			goto out_resource;
1894		WRITE32(nfsd4_lease);
1895	}
1896	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1897		if ((buflen -= 4) < 0)
1898			goto out_resource;
1899		WRITE32(rdattr_err);
1900	}
1901	if (bmval0 & FATTR4_WORD0_ACL) {
1902		struct nfs4_ace *ace;
1903
1904		if (acl == NULL) {
1905			if ((buflen -= 4) < 0)
1906				goto out_resource;
1907
1908			WRITE32(0);
1909			goto out_acl;
1910		}
1911		if ((buflen -= 4) < 0)
1912			goto out_resource;
1913		WRITE32(acl->naces);
1914
1915		for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
1916			if ((buflen -= 4*3) < 0)
1917				goto out_resource;
1918			WRITE32(ace->type);
1919			WRITE32(ace->flag);
1920			WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
1921			status = nfsd4_encode_aclname(rqstp, ace->whotype,
1922				ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
1923				&p, &buflen);
1924			if (status == nfserr_resource)
1925				goto out_resource;
1926			if (status)
1927				goto out;
1928		}
1929	}
1930out_acl:
1931	if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1932		if ((buflen -= 4) < 0)
1933			goto out_resource;
1934		WRITE32(aclsupport ?
1935			ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
1936	}
1937	if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1938		if ((buflen -= 4) < 0)
1939			goto out_resource;
1940		WRITE32(1);
1941	}
1942	if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1943		if ((buflen -= 4) < 0)
1944			goto out_resource;
1945		WRITE32(1);
1946	}
1947	if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1948		if ((buflen -= 4) < 0)
1949			goto out_resource;
1950		WRITE32(1);
1951	}
1952	if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1953		if ((buflen -= 4) < 0)
1954			goto out_resource;
1955		WRITE32(1);
1956	}
1957	if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1958		buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1959		if (buflen < 0)
1960			goto out_resource;
1961		WRITE32(fhp->fh_handle.fh_size);
1962		WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1963	}
1964	if (bmval0 & FATTR4_WORD0_FILEID) {
1965		if ((buflen -= 8) < 0)
1966			goto out_resource;
1967		WRITE64(stat.ino);
1968	}
1969	if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1970		if ((buflen -= 8) < 0)
1971			goto out_resource;
1972		WRITE64((u64) statfs.f_ffree);
1973	}
1974	if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1975		if ((buflen -= 8) < 0)
1976			goto out_resource;
1977		WRITE64((u64) statfs.f_ffree);
1978	}
1979	if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1980		if ((buflen -= 8) < 0)
1981			goto out_resource;
1982		WRITE64((u64) statfs.f_files);
1983	}
1984	if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1985		status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
1986		if (status == nfserr_resource)
1987			goto out_resource;
1988		if (status)
1989			goto out;
1990	}
1991	if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1992		if ((buflen -= 4) < 0)
1993			goto out_resource;
1994		WRITE32(1);
1995	}
1996	if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
1997		if ((buflen -= 8) < 0)
1998			goto out_resource;
1999		WRITE64(~(u64)0);
2000	}
2001	if (bmval0 & FATTR4_WORD0_MAXLINK) {
2002		if ((buflen -= 4) < 0)
2003			goto out_resource;
2004		WRITE32(255);
2005	}
2006	if (bmval0 & FATTR4_WORD0_MAXNAME) {
2007		if ((buflen -= 4) < 0)
2008			goto out_resource;
2009		WRITE32(statfs.f_namelen);
2010	}
2011	if (bmval0 & FATTR4_WORD0_MAXREAD) {
2012		if ((buflen -= 8) < 0)
2013			goto out_resource;
2014		WRITE64((u64) svc_max_payload(rqstp));
2015	}
2016	if (bmval0 & FATTR4_WORD0_MAXWRITE) {
2017		if ((buflen -= 8) < 0)
2018			goto out_resource;
2019		WRITE64((u64) svc_max_payload(rqstp));
2020	}
2021	if (bmval1 & FATTR4_WORD1_MODE) {
2022		if ((buflen -= 4) < 0)
2023			goto out_resource;
2024		WRITE32(stat.mode & S_IALLUGO);
2025	}
2026	if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
2027		if ((buflen -= 4) < 0)
2028			goto out_resource;
2029		WRITE32(1);
2030	}
2031	if (bmval1 & FATTR4_WORD1_NUMLINKS) {
2032		if ((buflen -= 4) < 0)
2033			goto out_resource;
2034		WRITE32(stat.nlink);
2035	}
2036	if (bmval1 & FATTR4_WORD1_OWNER) {
2037		status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
2038		if (status == nfserr_resource)
2039			goto out_resource;
2040		if (status)
2041			goto out;
2042	}
2043	if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
2044		status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
2045		if (status == nfserr_resource)
2046			goto out_resource;
2047		if (status)
2048			goto out;
2049	}
2050	if (bmval1 & FATTR4_WORD1_RAWDEV) {
2051		if ((buflen -= 8) < 0)
2052			goto out_resource;
2053		WRITE32((u32) MAJOR(stat.rdev));
2054		WRITE32((u32) MINOR(stat.rdev));
2055	}
2056	if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
2057		if ((buflen -= 8) < 0)
2058			goto out_resource;
2059		dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
2060		WRITE64(dummy64);
2061	}
2062	if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
2063		if ((buflen -= 8) < 0)
2064			goto out_resource;
2065		dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
2066		WRITE64(dummy64);
2067	}
2068	if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
2069		if ((buflen -= 8) < 0)
2070			goto out_resource;
2071		dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
2072		WRITE64(dummy64);
2073	}
2074	if (bmval1 & FATTR4_WORD1_SPACE_USED) {
2075		if ((buflen -= 8) < 0)
2076			goto out_resource;
2077		dummy64 = (u64)stat.blocks << 9;
2078		WRITE64(dummy64);
2079	}
2080	if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
2081		if ((buflen -= 12) < 0)
2082			goto out_resource;
2083		WRITE32(0);
2084		WRITE32(stat.atime.tv_sec);
2085		WRITE32(stat.atime.tv_nsec);
2086	}
2087	if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
2088		if ((buflen -= 12) < 0)
2089			goto out_resource;
2090		WRITE32(0);
2091		WRITE32(1);
2092		WRITE32(0);
2093	}
2094	if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
2095		if ((buflen -= 12) < 0)
2096			goto out_resource;
2097		WRITE32(0);
2098		WRITE32(stat.ctime.tv_sec);
2099		WRITE32(stat.ctime.tv_nsec);
2100	}
2101	if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
2102		if ((buflen -= 12) < 0)
2103			goto out_resource;
2104		WRITE32(0);
2105		WRITE32(stat.mtime.tv_sec);
2106		WRITE32(stat.mtime.tv_nsec);
2107	}
2108	if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
2109		if ((buflen -= 8) < 0)
2110                	goto out_resource;
2111		/*
2112		 * Get parent's attributes if not ignoring crossmount
2113		 * and this is the root of a cross-mounted filesystem.
2114		 */
2115		if (ignore_crossmnt == 0 &&
2116		    dentry == exp->ex_path.mnt->mnt_root) {
2117			struct path path = exp->ex_path;
2118			path_get(&path);
2119			while (follow_up(&path)) {
2120				if (path.dentry != path.mnt->mnt_root)
2121					break;
2122			}
2123			err = vfs_getattr(path.mnt, path.dentry, &stat);
2124			path_put(&path);
2125			if (err)
2126				goto out_nfserr;
2127		}
2128		WRITE64(stat.ino);
2129	}
2130	if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
2131		WRITE32(3);
2132		WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD0);
2133		WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD1);
2134		WRITE32(NFSD_SUPPATTR_EXCLCREAT_WORD2);
2135	}
2136
2137	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2138	*countp = p - buffer;
2139	status = nfs_ok;
2140
2141out:
2142	kfree(acl);
2143	if (fhp == &tempfh)
2144		fh_put(&tempfh);
2145	return status;
2146out_nfserr:
2147	status = nfserrno(err);
2148	goto out;
2149out_resource:
2150	*countp = 0;
2151	status = nfserr_resource;
2152	goto out;
2153out_serverfault:
2154	status = nfserr_serverfault;
2155	goto out;
2156}
2157
2158static inline int attributes_need_mount(u32 *bmval)
2159{
2160	if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
2161		return 1;
2162	if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
2163		return 1;
2164	return 0;
2165}
2166
2167static __be32
2168nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
2169		const char *name, int namlen, __be32 *p, int *buflen)
2170{
2171	struct svc_export *exp = cd->rd_fhp->fh_export;
2172	struct dentry *dentry;
2173	__be32 nfserr;
2174	int ignore_crossmnt = 0;
2175
2176	dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
2177	if (IS_ERR(dentry))
2178		return nfserrno(PTR_ERR(dentry));
2179	if (!dentry->d_inode) {
2180		/*
2181		 * nfsd_buffered_readdir drops the i_mutex between
2182		 * readdir and calling this callback, leaving a window
2183		 * where this directory entry could have gone away.
2184		 */
2185		dput(dentry);
2186		return nfserr_noent;
2187	}
2188
2189	exp_get(exp);
2190	/*
2191	 * In the case of a mountpoint, the client may be asking for
2192	 * attributes that are only properties of the underlying filesystem
2193	 * as opposed to the cross-mounted file system. In such a case,
2194	 * we will not follow the cross mount and will fill the attribtutes
2195	 * directly from the mountpoint dentry.
2196	 */
2197	if (nfsd_mountpoint(dentry, exp)) {
2198		int err;
2199
2200		if (!(exp->ex_flags & NFSEXP_V4ROOT)
2201				&& !attributes_need_mount(cd->rd_bmval)) {
2202			ignore_crossmnt = 1;
2203			goto out_encode;
2204		}
2205		/*
2206		 * Why the heck aren't we just using nfsd_lookup??
2207		 * Different "."/".." handling?  Something else?
2208		 * At least, add a comment here to explain....
2209		 */
2210		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
2211		if (err) {
2212			nfserr = nfserrno(err);
2213			goto out_put;
2214		}
2215		nfserr = check_nfsd_access(exp, cd->rd_rqstp);
2216		if (nfserr)
2217			goto out_put;
2218
2219	}
2220out_encode:
2221	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
2222					cd->rd_rqstp, ignore_crossmnt);
2223out_put:
2224	dput(dentry);
2225	exp_put(exp);
2226	return nfserr;
2227}
2228
2229static __be32 *
2230nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
2231{
2232	__be32 *attrlenp;
2233
2234	if (buflen < 6)
2235		return NULL;
2236	*p++ = htonl(2);
2237	*p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
2238	*p++ = htonl(0);			 /* bmval1 */
2239
2240	attrlenp = p++;
2241	*p++ = nfserr;       /* no htonl */
2242	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
2243	return p;
2244}
2245
2246static int
2247nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2248		    loff_t offset, u64 ino, unsigned int d_type)
2249{
2250	struct readdir_cd *ccd = ccdv;
2251	struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
2252	int buflen;
2253	__be32 *p = cd->buffer;
2254	__be32 *cookiep;
2255	__be32 nfserr = nfserr_toosmall;
2256
2257	/* In nfsv4, "." and ".." never make it onto the wire.. */
2258	if (name && isdotent(name, namlen)) {
2259		cd->common.err = nfs_ok;
2260		return 0;
2261	}
2262
2263	if (cd->offset)
2264		xdr_encode_hyper(cd->offset, (u64) offset);
2265
2266	buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
2267	if (buflen < 0)
2268		goto fail;
2269
2270	*p++ = xdr_one;                             /* mark entry present */
2271	cookiep = p;
2272	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);    /* offset of next entry */
2273	p = xdr_encode_array(p, name, namlen);      /* name length & name */
2274
2275	nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
2276	switch (nfserr) {
2277	case nfs_ok:
2278		p += buflen;
2279		break;
2280	case nfserr_resource:
2281		nfserr = nfserr_toosmall;
2282		goto fail;
2283	case nfserr_dropit:
2284		goto fail;
2285	case nfserr_noent:
2286		goto skip_entry;
2287	default:
2288		/*
2289		 * If the client requested the RDATTR_ERROR attribute,
2290		 * we stuff the error code into this attribute
2291		 * and continue.  If this attribute was not requested,
2292		 * then in accordance with the spec, we fail the
2293		 * entire READDIR operation(!)
2294		 */
2295		if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
2296			goto fail;
2297		p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
2298		if (p == NULL) {
2299			nfserr = nfserr_toosmall;
2300			goto fail;
2301		}
2302	}
2303	cd->buflen -= (p - cd->buffer);
2304	cd->buffer = p;
2305	cd->offset = cookiep;
2306skip_entry:
2307	cd->common.err = nfs_ok;
2308	return 0;
2309fail:
2310	cd->common.err = nfserr;
2311	return -EINVAL;
2312}
2313
2314static void
2315nfsd4_encode_stateid(struct nfsd4_compoundres *resp, stateid_t *sid)
2316{
2317	__be32 *p;
2318
2319	RESERVE_SPACE(sizeof(stateid_t));
2320	WRITE32(sid->si_generation);
2321	WRITEMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
2322	ADJUST_ARGS();
2323}
2324
2325static __be32
2326nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
2327{
2328	__be32 *p;
2329
2330	if (!nfserr) {
2331		RESERVE_SPACE(8);
2332		WRITE32(access->ac_supported);
2333		WRITE32(access->ac_resp_access);
2334		ADJUST_ARGS();
2335	}
2336	return nfserr;
2337}
2338
2339static __be32
2340nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
2341{
2342	ENCODE_SEQID_OP_HEAD;
2343
2344	if (!nfserr)
2345		nfsd4_encode_stateid(resp, &close->cl_stateid);
2346
2347	ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
2348	return nfserr;
2349}
2350
2351
2352static __be32
2353nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
2354{
2355	__be32 *p;
2356
2357	if (!nfserr) {
2358		RESERVE_SPACE(8);
2359		WRITEMEM(commit->co_verf.data, 8);
2360		ADJUST_ARGS();
2361	}
2362	return nfserr;
2363}
2364
2365static __be32
2366nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
2367{
2368	__be32 *p;
2369
2370	if (!nfserr) {
2371		RESERVE_SPACE(32);
2372		write_cinfo(&p, &create->cr_cinfo);
2373		WRITE32(2);
2374		WRITE32(create->cr_bmval[0]);
2375		WRITE32(create->cr_bmval[1]);
2376		ADJUST_ARGS();
2377	}
2378	return nfserr;
2379}
2380
2381static __be32
2382nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
2383{
2384	struct svc_fh *fhp = getattr->ga_fhp;
2385	int buflen;
2386
2387	if (nfserr)
2388		return nfserr;
2389
2390	buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
2391	nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
2392				    resp->p, &buflen, getattr->ga_bmval,
2393				    resp->rqstp, 0);
2394	if (!nfserr)
2395		resp->p += buflen;
2396	return nfserr;
2397}
2398
2399static __be32
2400nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
2401{
2402	struct svc_fh *fhp = *fhpp;
2403	unsigned int len;
2404	__be32 *p;
2405
2406	if (!nfserr) {
2407		len = fhp->fh_handle.fh_size;
2408		RESERVE_SPACE(len + 4);
2409		WRITE32(len);
2410		WRITEMEM(&fhp->fh_handle.fh_base, len);
2411		ADJUST_ARGS();
2412	}
2413	return nfserr;
2414}
2415
2416/*
2417* Including all fields other than the name, a LOCK4denied structure requires
2418*   8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
2419*/
2420static void
2421nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
2422{
2423	__be32 *p;
2424
2425	RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
2426	WRITE64(ld->ld_start);
2427	WRITE64(ld->ld_length);
2428	WRITE32(ld->ld_type);
2429	if (ld->ld_sop) {
2430		WRITEMEM(&ld->ld_clientid, 8);
2431		WRITE32(ld->ld_sop->so_owner.len);
2432		WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
2433		kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
2434	}  else {  /* non - nfsv4 lock in conflict, no clientid nor owner */
2435		WRITE64((u64)0); /* clientid */
2436		WRITE32(0); /* length of owner name */
2437	}
2438	ADJUST_ARGS();
2439}
2440
2441static __be32
2442nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
2443{
2444	ENCODE_SEQID_OP_HEAD;
2445
2446	if (!nfserr)
2447		nfsd4_encode_stateid(resp, &lock->lk_resp_stateid);
2448	else if (nfserr == nfserr_denied)
2449		nfsd4_encode_lock_denied(resp, &lock->lk_denied);
2450
2451	ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
2452	return nfserr;
2453}
2454
2455static __be32
2456nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
2457{
2458	if (nfserr == nfserr_denied)
2459		nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
2460	return nfserr;
2461}
2462
2463static __be32
2464nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
2465{
2466	ENCODE_SEQID_OP_HEAD;
2467
2468	if (!nfserr)
2469		nfsd4_encode_stateid(resp, &locku->lu_stateid);
2470
2471	ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
2472	return nfserr;
2473}
2474
2475
2476static __be32
2477nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
2478{
2479	__be32 *p;
2480
2481	if (!nfserr) {
2482		RESERVE_SPACE(20);
2483		write_cinfo(&p, &link->li_cinfo);
2484		ADJUST_ARGS();
2485	}
2486	return nfserr;
2487}
2488
2489
2490static __be32
2491nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
2492{
2493	__be32 *p;
2494	ENCODE_SEQID_OP_HEAD;
2495
2496	if (nfserr)
2497		goto out;
2498
2499	nfsd4_encode_stateid(resp, &open->op_stateid);
2500	RESERVE_SPACE(40);
2501	write_cinfo(&p, &open->op_cinfo);
2502	WRITE32(open->op_rflags);
2503	WRITE32(2);
2504	WRITE32(open->op_bmval[0]);
2505	WRITE32(open->op_bmval[1]);
2506	WRITE32(open->op_delegate_type);
2507	ADJUST_ARGS();
2508
2509	switch (open->op_delegate_type) {
2510	case NFS4_OPEN_DELEGATE_NONE:
2511		break;
2512	case NFS4_OPEN_DELEGATE_READ:
2513		nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2514		RESERVE_SPACE(20);
2515		WRITE32(open->op_recall);
2516
2517		/*
2518		 * TODO: ACE's in delegations
2519		 */
2520		WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2521		WRITE32(0);
2522		WRITE32(0);
2523		WRITE32(0);
2524		ADJUST_ARGS();
2525		break;
2526	case NFS4_OPEN_DELEGATE_WRITE:
2527		nfsd4_encode_stateid(resp, &open->op_delegate_stateid);
2528		RESERVE_SPACE(32);
2529		WRITE32(0);
2530
2531		/*
2532		 * TODO: space_limit's in delegations
2533		 */
2534		WRITE32(NFS4_LIMIT_SIZE);
2535		WRITE32(~(u32)0);
2536		WRITE32(~(u32)0);
2537
2538		/*
2539		 * TODO: ACE's in delegations
2540		 */
2541		WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2542		WRITE32(0);
2543		WRITE32(0);
2544		WRITE32(0);
2545		ADJUST_ARGS();
2546		break;
2547	default:
2548		BUG();
2549	}
2550out:
2551	ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2552	return nfserr;
2553}
2554
2555static __be32
2556nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
2557{
2558	ENCODE_SEQID_OP_HEAD;
2559
2560	if (!nfserr)
2561		nfsd4_encode_stateid(resp, &oc->oc_resp_stateid);
2562
2563	ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2564	return nfserr;
2565}
2566
2567static __be32
2568nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
2569{
2570	ENCODE_SEQID_OP_HEAD;
2571
2572	if (!nfserr)
2573		nfsd4_encode_stateid(resp, &od->od_stateid);
2574
2575	ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2576	return nfserr;
2577}
2578
2579static __be32
2580nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2581		  struct nfsd4_read *read)
2582{
2583	u32 eof;
2584	int v, pn;
2585	unsigned long maxcount;
2586	long len;
2587	__be32 *p;
2588
2589	if (nfserr)
2590		return nfserr;
2591	if (resp->xbuf->page_len)
2592		return nfserr_resource;
2593
2594	RESERVE_SPACE(8); /* eof flag and byte count */
2595
2596	maxcount = svc_max_payload(resp->rqstp);
2597	if (maxcount > read->rd_length)
2598		maxcount = read->rd_length;
2599
2600	len = maxcount;
2601	v = 0;
2602	while (len > 0) {
2603		pn = resp->rqstp->rq_resused++;
2604		resp->rqstp->rq_vec[v].iov_base =
2605			page_address(resp->rqstp->rq_respages[pn]);
2606		resp->rqstp->rq_vec[v].iov_len =
2607			len < PAGE_SIZE ? len : PAGE_SIZE;
2608		v++;
2609		len -= PAGE_SIZE;
2610	}
2611	read->rd_vlen = v;
2612
2613	nfserr = nfsd_read_file(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2614			read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
2615			&maxcount);
2616
2617	if (nfserr == nfserr_symlink)
2618		nfserr = nfserr_inval;
2619	if (nfserr)
2620		return nfserr;
2621	eof = (read->rd_offset + maxcount >=
2622	       read->rd_fhp->fh_dentry->d_inode->i_size);
2623
2624	WRITE32(eof);
2625	WRITE32(maxcount);
2626	ADJUST_ARGS();
2627	resp->xbuf->head[0].iov_len = (char*)p
2628					- (char*)resp->xbuf->head[0].iov_base;
2629	resp->xbuf->page_len = maxcount;
2630
2631	/* Use rest of head for padding and remaining ops: */
2632	resp->xbuf->tail[0].iov_base = p;
2633	resp->xbuf->tail[0].iov_len = 0;
2634	if (maxcount&3) {
2635		RESERVE_SPACE(4);
2636		WRITE32(0);
2637		resp->xbuf->tail[0].iov_base += maxcount&3;
2638		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2639		ADJUST_ARGS();
2640	}
2641	return 0;
2642}
2643
2644static __be32
2645nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
2646{
2647	int maxcount;
2648	char *page;
2649	__be32 *p;
2650
2651	if (nfserr)
2652		return nfserr;
2653	if (resp->xbuf->page_len)
2654		return nfserr_resource;
2655
2656	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2657
2658	maxcount = PAGE_SIZE;
2659	RESERVE_SPACE(4);
2660
2661	nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2662	if (nfserr == nfserr_isdir)
2663		return nfserr_inval;
2664	if (nfserr)
2665		return nfserr;
2666
2667	WRITE32(maxcount);
2668	ADJUST_ARGS();
2669	resp->xbuf->head[0].iov_len = (char*)p
2670				- (char*)resp->xbuf->head[0].iov_base;
2671	resp->xbuf->page_len = maxcount;
2672
2673	/* Use rest of head for padding and remaining ops: */
2674	resp->xbuf->tail[0].iov_base = p;
2675	resp->xbuf->tail[0].iov_len = 0;
2676	if (maxcount&3) {
2677		RESERVE_SPACE(4);
2678		WRITE32(0);
2679		resp->xbuf->tail[0].iov_base += maxcount&3;
2680		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2681		ADJUST_ARGS();
2682	}
2683	return 0;
2684}
2685
2686static __be32
2687nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
2688{
2689	int maxcount;
2690	loff_t offset;
2691	__be32 *page, *savep, *tailbase;
2692	__be32 *p;
2693
2694	if (nfserr)
2695		return nfserr;
2696	if (resp->xbuf->page_len)
2697		return nfserr_resource;
2698
2699	RESERVE_SPACE(8);  /* verifier */
2700	savep = p;
2701
2702	WRITE32(0);
2703	WRITE32(0);
2704	ADJUST_ARGS();
2705	resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2706	tailbase = p;
2707
2708	maxcount = PAGE_SIZE;
2709	if (maxcount > readdir->rd_maxcount)
2710		maxcount = readdir->rd_maxcount;
2711
2712	/*
2713	 * Convert from bytes to words, account for the two words already
2714	 * written, make sure to leave two words at the end for the next
2715	 * pointer and eof field.
2716	 */
2717	maxcount = (maxcount >> 2) - 4;
2718	if (maxcount < 0) {
2719		nfserr =  nfserr_toosmall;
2720		goto err_no_verf;
2721	}
2722
2723	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2724	readdir->common.err = 0;
2725	readdir->buflen = maxcount;
2726	readdir->buffer = page;
2727	readdir->offset = NULL;
2728
2729	offset = readdir->rd_cookie;
2730	nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2731			      &offset,
2732			      &readdir->common, nfsd4_encode_dirent);
2733	if (nfserr == nfs_ok &&
2734	    readdir->common.err == nfserr_toosmall &&
2735	    readdir->buffer == page)
2736		nfserr = nfserr_toosmall;
2737	if (nfserr == nfserr_symlink)
2738		nfserr = nfserr_notdir;
2739	if (nfserr)
2740		goto err_no_verf;
2741
2742	if (readdir->offset)
2743		xdr_encode_hyper(readdir->offset, offset);
2744
2745	p = readdir->buffer;
2746	*p++ = 0;	/* no more entries */
2747	*p++ = htonl(readdir->common.err == nfserr_eof);
2748	resp->xbuf->page_len = ((char*)p) - (char*)page_address(
2749		resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2750
2751	/* Use rest of head for padding and remaining ops: */
2752	resp->xbuf->tail[0].iov_base = tailbase;
2753	resp->xbuf->tail[0].iov_len = 0;
2754	resp->p = resp->xbuf->tail[0].iov_base;
2755	resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
2756
2757	return 0;
2758err_no_verf:
2759	p = savep;
2760	ADJUST_ARGS();
2761	return nfserr;
2762}
2763
2764static __be32
2765nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
2766{
2767	__be32 *p;
2768
2769	if (!nfserr) {
2770		RESERVE_SPACE(20);
2771		write_cinfo(&p, &remove->rm_cinfo);
2772		ADJUST_ARGS();
2773	}
2774	return nfserr;
2775}
2776
2777static __be32
2778nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
2779{
2780	__be32 *p;
2781
2782	if (!nfserr) {
2783		RESERVE_SPACE(40);
2784		write_cinfo(&p, &rename->rn_sinfo);
2785		write_cinfo(&p, &rename->rn_tinfo);
2786		ADJUST_ARGS();
2787	}
2788	return nfserr;
2789}
2790
2791static __be32
2792nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
2793		     struct nfsd4_secinfo *secinfo)
2794{
2795	int i = 0;
2796	struct svc_export *exp = secinfo->si_exp;
2797	u32 nflavs;
2798	struct exp_flavor_info *flavs;
2799	struct exp_flavor_info def_flavs[2];
2800	__be32 *p;
2801
2802	if (nfserr)
2803		goto out;
2804	if (exp->ex_nflavors) {
2805		flavs = exp->ex_flavors;
2806		nflavs = exp->ex_nflavors;
2807	} else { /* Handling of some defaults in absence of real secinfo: */
2808		flavs = def_flavs;
2809		if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
2810			nflavs = 2;
2811			flavs[0].pseudoflavor = RPC_AUTH_UNIX;
2812			flavs[1].pseudoflavor = RPC_AUTH_NULL;
2813		} else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
2814			nflavs = 1;
2815			flavs[0].pseudoflavor
2816					= svcauth_gss_flavor(exp->ex_client);
2817		} else {
2818			nflavs = 1;
2819			flavs[0].pseudoflavor
2820					= exp->ex_client->flavour->flavour;
2821		}
2822	}
2823
2824	RESERVE_SPACE(4);
2825	WRITE32(nflavs);
2826	ADJUST_ARGS();
2827	for (i = 0; i < nflavs; i++) {
2828		u32 flav = flavs[i].pseudoflavor;
2829		struct gss_api_mech *gm = gss_mech_get_by_pseudoflavor(flav);
2830
2831		if (gm) {
2832			RESERVE_SPACE(4);
2833			WRITE32(RPC_AUTH_GSS);
2834			ADJUST_ARGS();
2835			RESERVE_SPACE(4 + gm->gm_oid.len);
2836			WRITE32(gm->gm_oid.len);
2837			WRITEMEM(gm->gm_oid.data, gm->gm_oid.len);
2838			ADJUST_ARGS();
2839			RESERVE_SPACE(4);
2840			WRITE32(0); /* qop */
2841			ADJUST_ARGS();
2842			RESERVE_SPACE(4);
2843			WRITE32(gss_pseudoflavor_to_service(gm, flav));
2844			ADJUST_ARGS();
2845			gss_mech_put(gm);
2846		} else {
2847			RESERVE_SPACE(4);
2848			WRITE32(flav);
2849			ADJUST_ARGS();
2850		}
2851	}
2852out:
2853	if (exp)
2854		exp_put(exp);
2855	return nfserr;
2856}
2857
2858/*
2859 * The SETATTR encode routine is special -- it always encodes a bitmap,
2860 * regardless of the error status.
2861 */
2862static __be32
2863nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
2864{
2865	__be32 *p;
2866
2867	RESERVE_SPACE(12);
2868	if (nfserr) {
2869		WRITE32(2);
2870		WRITE32(0);
2871		WRITE32(0);
2872	}
2873	else {
2874		WRITE32(2);
2875		WRITE32(setattr->sa_bmval[0]);
2876		WRITE32(setattr->sa_bmval[1]);
2877	}
2878	ADJUST_ARGS();
2879	return nfserr;
2880}
2881
2882static __be32
2883nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
2884{
2885	__be32 *p;
2886
2887	if (!nfserr) {
2888		RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2889		WRITEMEM(&scd->se_clientid, 8);
2890		WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2891		ADJUST_ARGS();
2892	}
2893	else if (nfserr == nfserr_clid_inuse) {
2894		RESERVE_SPACE(8);
2895		WRITE32(0);
2896		WRITE32(0);
2897		ADJUST_ARGS();
2898	}
2899	return nfserr;
2900}
2901
2902static __be32
2903nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
2904{
2905	__be32 *p;
2906
2907	if (!nfserr) {
2908		RESERVE_SPACE(16);
2909		WRITE32(write->wr_bytes_written);
2910		WRITE32(write->wr_how_written);
2911		WRITEMEM(write->wr_verifier.data, 8);
2912		ADJUST_ARGS();
2913	}
2914	return nfserr;
2915}
2916
2917static __be32
2918nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, int nfserr,
2919			 struct nfsd4_exchange_id *exid)
2920{
2921	__be32 *p;
2922	char *major_id;
2923	char *server_scope;
2924	int major_id_sz;
2925	int server_scope_sz;
2926	uint64_t minor_id = 0;
2927
2928	if (nfserr)
2929		return nfserr;
2930
2931	major_id = utsname()->nodename;
2932	major_id_sz = strlen(major_id);
2933	server_scope = utsname()->nodename;
2934	server_scope_sz = strlen(server_scope);
2935
2936	RESERVE_SPACE(
2937		8 /* eir_clientid */ +
2938		4 /* eir_sequenceid */ +
2939		4 /* eir_flags */ +
2940		4 /* spr_how (SP4_NONE) */ +
2941		8 /* so_minor_id */ +
2942		4 /* so_major_id.len */ +
2943		(XDR_QUADLEN(major_id_sz) * 4) +
2944		4 /* eir_server_scope.len */ +
2945		(XDR_QUADLEN(server_scope_sz) * 4) +
2946		4 /* eir_server_impl_id.count (0) */);
2947
2948	WRITEMEM(&exid->clientid, 8);
2949	WRITE32(exid->seqid);
2950	WRITE32(exid->flags);
2951
2952	/* state_protect4_r. Currently only support SP4_NONE */
2953	BUG_ON(exid->spa_how != SP4_NONE);
2954	WRITE32(exid->spa_how);
2955
2956	/* The server_owner struct */
2957	WRITE64(minor_id);      /* Minor id */
2958	/* major id */
2959	WRITE32(major_id_sz);
2960	WRITEMEM(major_id, major_id_sz);
2961
2962	/* Server scope */
2963	WRITE32(server_scope_sz);
2964	WRITEMEM(server_scope, server_scope_sz);
2965
2966	/* Implementation id */
2967	WRITE32(0);	/* zero length nfs_impl_id4 array */
2968	ADJUST_ARGS();
2969	return 0;
2970}
2971
2972static __be32
2973nfsd4_encode_create_session(struct nfsd4_compoundres *resp, int nfserr,
2974			    struct nfsd4_create_session *sess)
2975{
2976	__be32 *p;
2977
2978	if (nfserr)
2979		return nfserr;
2980
2981	RESERVE_SPACE(24);
2982	WRITEMEM(sess->sessionid.data, NFS4_MAX_SESSIONID_LEN);
2983	WRITE32(sess->seqid);
2984	WRITE32(sess->flags);
2985	ADJUST_ARGS();
2986
2987	RESERVE_SPACE(28);
2988	WRITE32(0); /* headerpadsz */
2989	WRITE32(sess->fore_channel.maxreq_sz);
2990	WRITE32(sess->fore_channel.maxresp_sz);
2991	WRITE32(sess->fore_channel.maxresp_cached);
2992	WRITE32(sess->fore_channel.maxops);
2993	WRITE32(sess->fore_channel.maxreqs);
2994	WRITE32(sess->fore_channel.nr_rdma_attrs);
2995	ADJUST_ARGS();
2996
2997	if (sess->fore_channel.nr_rdma_attrs) {
2998		RESERVE_SPACE(4);
2999		WRITE32(sess->fore_channel.rdma_attrs);
3000		ADJUST_ARGS();
3001	}
3002
3003	RESERVE_SPACE(28);
3004	WRITE32(0); /* headerpadsz */
3005	WRITE32(sess->back_channel.maxreq_sz);
3006	WRITE32(sess->back_channel.maxresp_sz);
3007	WRITE32(sess->back_channel.maxresp_cached);
3008	WRITE32(sess->back_channel.maxops);
3009	WRITE32(sess->back_channel.maxreqs);
3010	WRITE32(sess->back_channel.nr_rdma_attrs);
3011	ADJUST_ARGS();
3012
3013	if (sess->back_channel.nr_rdma_attrs) {
3014		RESERVE_SPACE(4);
3015		WRITE32(sess->back_channel.rdma_attrs);
3016		ADJUST_ARGS();
3017	}
3018	return 0;
3019}
3020
3021static __be32
3022nfsd4_encode_destroy_session(struct nfsd4_compoundres *resp, int nfserr,
3023			     struct nfsd4_destroy_session *destroy_session)
3024{
3025	return nfserr;
3026}
3027
3028__be32
3029nfsd4_encode_sequence(struct nfsd4_compoundres *resp, int nfserr,
3030		      struct nfsd4_sequence *seq)
3031{
3032	__be32 *p;
3033
3034	if (nfserr)
3035		return nfserr;
3036
3037	RESERVE_SPACE(NFS4_MAX_SESSIONID_LEN + 20);
3038	WRITEMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
3039	WRITE32(seq->seqid);
3040	WRITE32(seq->slotid);
3041	WRITE32(seq->maxslots);
3042	WRITE32(seq->maxslots);
3043	WRITE32(0);
3044
3045	ADJUST_ARGS();
3046	resp->cstate.datap = p; /* DRC cache data pointer */
3047	return 0;
3048}
3049
3050static __be32
3051nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
3052{
3053	return nfserr;
3054}
3055
3056typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
3057
3058/*
3059 * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1
3060 * since we don't need to filter out obsolete ops as this is
3061 * done in the decoding phase.
3062 */
3063static nfsd4_enc nfsd4_enc_ops[] = {
3064	[OP_ACCESS]		= (nfsd4_enc)nfsd4_encode_access,
3065	[OP_CLOSE]		= (nfsd4_enc)nfsd4_encode_close,
3066	[OP_COMMIT]		= (nfsd4_enc)nfsd4_encode_commit,
3067	[OP_CREATE]		= (nfsd4_enc)nfsd4_encode_create,
3068	[OP_DELEGPURGE]		= (nfsd4_enc)nfsd4_encode_noop,
3069	[OP_DELEGRETURN]	= (nfsd4_enc)nfsd4_encode_noop,
3070	[OP_GETATTR]		= (nfsd4_enc)nfsd4_encode_getattr,
3071	[OP_GETFH]		= (nfsd4_enc)nfsd4_encode_getfh,
3072	[OP_LINK]		= (nfsd4_enc)nfsd4_encode_link,
3073	[OP_LOCK]		= (nfsd4_enc)nfsd4_encode_lock,
3074	[OP_LOCKT]		= (nfsd4_enc)nfsd4_encode_lockt,
3075	[OP_LOCKU]		= (nfsd4_enc)nfsd4_encode_locku,
3076	[OP_LOOKUP]		= (nfsd4_enc)nfsd4_encode_noop,
3077	[OP_LOOKUPP]		= (nfsd4_enc)nfsd4_encode_noop,
3078	[OP_NVERIFY]		= (nfsd4_enc)nfsd4_encode_noop,
3079	[OP_OPEN]		= (nfsd4_enc)nfsd4_encode_open,
3080	[OP_OPENATTR]		= (nfsd4_enc)nfsd4_encode_noop,
3081	[OP_OPEN_CONFIRM]	= (nfsd4_enc)nfsd4_encode_open_confirm,
3082	[OP_OPEN_DOWNGRADE]	= (nfsd4_enc)nfsd4_encode_open_downgrade,
3083	[OP_PUTFH]		= (nfsd4_enc)nfsd4_encode_noop,
3084	[OP_PUTPUBFH]		= (nfsd4_enc)nfsd4_encode_noop,
3085	[OP_PUTROOTFH]		= (nfsd4_enc)nfsd4_encode_noop,
3086	[OP_READ]		= (nfsd4_enc)nfsd4_encode_read,
3087	[OP_READDIR]		= (nfsd4_enc)nfsd4_encode_readdir,
3088	[OP_READLINK]		= (nfsd4_enc)nfsd4_encode_readlink,
3089	[OP_REMOVE]		= (nfsd4_enc)nfsd4_encode_remove,
3090	[OP_RENAME]		= (nfsd4_enc)nfsd4_encode_rename,
3091	[OP_RENEW]		= (nfsd4_enc)nfsd4_encode_noop,
3092	[OP_RESTOREFH]		= (nfsd4_enc)nfsd4_encode_noop,
3093	[OP_SAVEFH]		= (nfsd4_enc)nfsd4_encode_noop,
3094	[OP_SECINFO]		= (nfsd4_enc)nfsd4_encode_secinfo,
3095	[OP_SETATTR]		= (nfsd4_enc)nfsd4_encode_setattr,
3096	[OP_SETCLIENTID]	= (nfsd4_enc)nfsd4_encode_setclientid,
3097	[OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
3098	[OP_VERIFY]		= (nfsd4_enc)nfsd4_encode_noop,
3099	[OP_WRITE]		= (nfsd4_enc)nfsd4_encode_write,
3100	[OP_RELEASE_LOCKOWNER]	= (nfsd4_enc)nfsd4_encode_noop,
3101
3102	/* NFSv4.1 operations */
3103	[OP_BACKCHANNEL_CTL]	= (nfsd4_enc)nfsd4_encode_noop,
3104	[OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_noop,
3105	[OP_EXCHANGE_ID]	= (nfsd4_enc)nfsd4_encode_exchange_id,
3106	[OP_CREATE_SESSION]	= (nfsd4_enc)nfsd4_encode_create_session,
3107	[OP_DESTROY_SESSION]	= (nfsd4_enc)nfsd4_encode_destroy_session,
3108	[OP_FREE_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
3109	[OP_GET_DIR_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
3110	[OP_GETDEVICEINFO]	= (nfsd4_enc)nfsd4_encode_noop,
3111	[OP_GETDEVICELIST]	= (nfsd4_enc)nfsd4_encode_noop,
3112	[OP_LAYOUTCOMMIT]	= (nfsd4_enc)nfsd4_encode_noop,
3113	[OP_LAYOUTGET]		= (nfsd4_enc)nfsd4_encode_noop,
3114	[OP_LAYOUTRETURN]	= (nfsd4_enc)nfsd4_encode_noop,
3115	[OP_SECINFO_NO_NAME]	= (nfsd4_enc)nfsd4_encode_noop,
3116	[OP_SEQUENCE]		= (nfsd4_enc)nfsd4_encode_sequence,
3117	[OP_SET_SSV]		= (nfsd4_enc)nfsd4_encode_noop,
3118	[OP_TEST_STATEID]	= (nfsd4_enc)nfsd4_encode_noop,
3119	[OP_WANT_DELEGATION]	= (nfsd4_enc)nfsd4_encode_noop,
3120	[OP_DESTROY_CLIENTID]	= (nfsd4_enc)nfsd4_encode_noop,
3121	[OP_RECLAIM_COMPLETE]	= (nfsd4_enc)nfsd4_encode_noop,
3122};
3123
3124/*
3125 * Calculate the total amount of memory that the compound response has taken
3126 * after encoding the current operation.
3127 *
3128 * pad: add on 8 bytes for the next operation's op_code and status so that
3129 * there is room to cache a failure on the next operation.
3130 *
3131 * Compare this length to the session se_fmaxresp_cached.
3132 *
3133 * Our se_fmaxresp_cached will always be a multiple of PAGE_SIZE, and so
3134 * will be at least a page and will therefore hold the xdr_buf head.
3135 */
3136static int nfsd4_check_drc_limit(struct nfsd4_compoundres *resp)
3137{
3138	int status = 0;
3139	struct xdr_buf *xb = &resp->rqstp->rq_res;
3140	struct nfsd4_compoundargs *args = resp->rqstp->rq_argp;
3141	struct nfsd4_session *session = NULL;
3142	struct nfsd4_slot *slot = resp->cstate.slot;
3143	u32 length, tlen = 0, pad = 8;
3144
3145	if (!nfsd4_has_session(&resp->cstate))
3146		return status;
3147
3148	session = resp->cstate.session;
3149	if (session == NULL || slot->sl_cachethis == 0)
3150		return status;
3151
3152	if (resp->opcnt >= args->opcnt)
3153		pad = 0; /* this is the last operation */
3154
3155	if (xb->page_len == 0) {
3156		length = (char *)resp->p - (char *)xb->head[0].iov_base + pad;
3157	} else {
3158		if (xb->tail[0].iov_base && xb->tail[0].iov_len > 0)
3159			tlen = (char *)resp->p - (char *)xb->tail[0].iov_base;
3160
3161		length = xb->head[0].iov_len + xb->page_len + tlen + pad;
3162	}
3163	dprintk("%s length %u, xb->page_len %u tlen %u pad %u\n", __func__,
3164		length, xb->page_len, tlen, pad);
3165
3166	if (length <= session->se_fchannel.maxresp_cached)
3167		return status;
3168	else
3169		return nfserr_rep_too_big_to_cache;
3170}
3171
3172void
3173nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3174{
3175	__be32 *statp;
3176	__be32 *p;
3177
3178	RESERVE_SPACE(8);
3179	WRITE32(op->opnum);
3180	statp = p++;	/* to be backfilled at the end */
3181	ADJUST_ARGS();
3182
3183	if (op->opnum == OP_ILLEGAL)
3184		goto status;
3185	BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
3186	       !nfsd4_enc_ops[op->opnum]);
3187	op->status = nfsd4_enc_ops[op->opnum](resp, op->status, &op->u);
3188	/* nfsd4_check_drc_limit guarantees enough room for error status */
3189	if (!op->status && nfsd4_check_drc_limit(resp))
3190		op->status = nfserr_rep_too_big_to_cache;
3191status:
3192	/*
3193	 * Note: We write the status directly, instead of using WRITE32(),
3194	 * since it is already in network byte order.
3195	 */
3196	*statp = op->status;
3197}
3198
3199/*
3200 * Encode the reply stored in the stateowner reply cache
3201 *
3202 * XDR note: do not encode rp->rp_buflen: the buffer contains the
3203 * previously sent already encoded operation.
3204 *
3205 * called with nfs4_lock_state() held
3206 */
3207void
3208nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
3209{
3210	__be32 *p;
3211	struct nfs4_replay *rp = op->replay;
3212
3213	BUG_ON(!rp);
3214
3215	RESERVE_SPACE(8);
3216	WRITE32(op->opnum);
3217	*p++ = rp->rp_status;  /* already xdr'ed */
3218	ADJUST_ARGS();
3219
3220	RESERVE_SPACE(rp->rp_buflen);
3221	WRITEMEM(rp->rp_buf, rp->rp_buflen);
3222	ADJUST_ARGS();
3223}
3224
3225int
3226nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
3227{
3228        return xdr_ressize_check(rqstp, p);
3229}
3230
3231void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
3232{
3233	if (args->ops != args->iops) {
3234		kfree(args->ops);
3235		args->ops = args->iops;
3236	}
3237	kfree(args->tmpp);
3238	args->tmpp = NULL;
3239	while (args->to_free) {
3240		struct tmpbuf *tb = args->to_free;
3241		args->to_free = tb->next;
3242		tb->release(tb->buf);
3243		kfree(tb);
3244	}
3245}
3246
3247int
3248nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
3249{
3250	__be32 status;
3251
3252	args->p = p;
3253	args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
3254	args->pagelist = rqstp->rq_arg.pages;
3255	args->pagelen = rqstp->rq_arg.page_len;
3256	args->tmpp = NULL;
3257	args->to_free = NULL;
3258	args->ops = args->iops;
3259	args->rqstp = rqstp;
3260
3261	status = nfsd4_decode_compound(args);
3262	if (status) {
3263		nfsd4_release_compoundargs(args);
3264	}
3265	return !status;
3266}
3267
3268int
3269nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
3270{
3271	/*
3272	 * All that remains is to write the tag and operation count...
3273	 */
3274	struct nfsd4_compound_state *cs = &resp->cstate;
3275	struct kvec *iov;
3276	p = resp->tagp;
3277	*p++ = htonl(resp->taglen);
3278	memcpy(p, resp->tag, resp->taglen);
3279	p += XDR_QUADLEN(resp->taglen);
3280	*p++ = htonl(resp->opcnt);
3281
3282	if (rqstp->rq_res.page_len)
3283		iov = &rqstp->rq_res.tail[0];
3284	else
3285		iov = &rqstp->rq_res.head[0];
3286	iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
3287	BUG_ON(iov->iov_len > PAGE_SIZE);
3288	if (nfsd4_has_session(cs)) {
3289		if (cs->status != nfserr_replay_cache) {
3290			nfsd4_store_cache_entry(resp);
3291			dprintk("%s: SET SLOT STATE TO AVAILABLE\n", __func__);
3292			cs->slot->sl_inuse = false;
3293		}
3294		/* Renew the clientid on success and on replay */
3295		release_session_client(cs->session);
3296		nfsd4_put_session(cs->session);
3297	}
3298	return 1;
3299}
3300
3301/*
3302 * Local variables:
3303 *  c-basic-offset: 8
3304 * End:
3305 */
3306