1/*
2 *  fs/nfs/nfs4xdr.c
3 *
4 *  Server-side XDR for NFSv4
5 *
6 *  Copyright (c) 2002 The Regents of the University of Michigan.
7 *  All rights reserved.
8 *
9 *  Kendrick Smith <kmsmith@umich.edu>
10 *  Andy Adamson   <andros@umich.edu>
11 *
12 *  Redistribution and use in source and binary forms, with or without
13 *  modification, are permitted provided that the following conditions
14 *  are met:
15 *
16 *  1. Redistributions of source code must retain the above copyright
17 *     notice, this list of conditions and the following disclaimer.
18 *  2. Redistributions in binary form must reproduce the above copyright
19 *     notice, this list of conditions and the following disclaimer in the
20 *     documentation and/or other materials provided with the distribution.
21 *  3. Neither the name of the University nor the names of its
22 *     contributors may be used to endorse or promote products derived
23 *     from this software without specific prior written permission.
24 *
25 *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 *
37 * TODO: Neil Brown made the following observation:  We currently
38 * initially reserve NFSD_BUFSIZE space on the transmit queue and
39 * never release any of that until the request is complete.
40 * It would be good to calculate a new maximum response size while
41 * decoding the COMPOUND, and call svc_reserve with this number
42 * at the end of nfs4svc_decode_compoundargs.
43 */
44
45#include <linux/param.h>
46#include <linux/smp.h>
47#include <linux/fs.h>
48#include <linux/namei.h>
49#include <linux/vfs.h>
50#include <linux/sunrpc/xdr.h>
51#include <linux/sunrpc/svc.h>
52#include <linux/sunrpc/clnt.h>
53#include <linux/nfsd/nfsd.h>
54#include <linux/nfsd/state.h>
55#include <linux/nfsd/xdr4.h>
56#include <linux/nfsd_idmap.h>
57#include <linux/nfs4.h>
58#include <linux/nfs4_acl.h>
59
60#define NFSDDBG_FACILITY		NFSDDBG_XDR
61
62/*
63 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
64 * directory in order to indicate to the client that a filesystem boundary is present
65 * We use a fixed fsid for a referral
66 */
67#define NFS4_REFERRAL_FSID_MAJOR	0x8000000ULL
68#define NFS4_REFERRAL_FSID_MINOR	0x8000000ULL
69
70static __be32
71check_filename(char *str, int len, __be32 err)
72{
73	int i;
74
75	if (len == 0)
76		return nfserr_inval;
77	if (isdotent(str, len))
78		return err;
79	for (i = 0; i < len; i++)
80		if (str[i] == '/')
81			return err;
82	return 0;
83}
84
85/*
86 * START OF "GENERIC" DECODE ROUTINES.
87 *   These may look a little ugly since they are imported from a "generic"
88 * set of XDR encode/decode routines which are intended to be shared by
89 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
90 *
91 * If the pain of reading these is too great, it should be a straightforward
92 * task to translate them into Linux-specific versions which are more
93 * consistent with the style used in NFSv2/v3...
94 */
95#define DECODE_HEAD				\
96	__be32 *p;				\
97	__be32 status
98#define DECODE_TAIL				\
99	status = 0;				\
100out:						\
101	return status;				\
102xdr_error:					\
103	printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__);	\
104	status = nfserr_bad_xdr;		\
105	goto out
106
107#define READ32(x)         (x) = ntohl(*p++)
108#define READ64(x)         do {			\
109	(x) = (u64)ntohl(*p++) << 32;		\
110	(x) |= ntohl(*p++);			\
111} while (0)
112#define READTIME(x)       do {			\
113	p++;					\
114	(x) = ntohl(*p++);			\
115	p++;					\
116} while (0)
117#define READMEM(x,nbytes) do {			\
118	x = (char *)p;				\
119	p += XDR_QUADLEN(nbytes);		\
120} while (0)
121#define SAVEMEM(x,nbytes) do {			\
122	if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
123 		savemem(argp, p, nbytes) :	\
124 		(char *)p)) {			\
125		printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
126		goto xdr_error;			\
127		}				\
128	p += XDR_QUADLEN(nbytes);		\
129} while (0)
130#define COPYMEM(x,nbytes) do {			\
131	memcpy((x), p, nbytes);			\
132	p += XDR_QUADLEN(nbytes);		\
133} while (0)
134
135/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
136#define READ_BUF(nbytes)  do {			\
137	if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) {	\
138		p = argp->p;			\
139		argp->p += XDR_QUADLEN(nbytes);	\
140	} else if (!(p = read_buf(argp, nbytes))) { \
141		printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
142		goto xdr_error;			\
143	}					\
144} while (0)
145
146static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
147{
148	/* We want more bytes than seem to be available.
149	 * Maybe we need a new page, maybe we have just run out
150	 */
151	int avail = (char*)argp->end - (char*)argp->p;
152	__be32 *p;
153	if (avail + argp->pagelen < nbytes)
154		return NULL;
155	if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
156		return NULL;
157	/* ok, we can do it with the current plus the next page */
158	if (nbytes <= sizeof(argp->tmp))
159		p = argp->tmp;
160	else {
161		kfree(argp->tmpp);
162		p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
163		if (!p)
164			return NULL;
165
166	}
167	memcpy(p, argp->p, avail);
168	/* step to next page */
169	argp->p = page_address(argp->pagelist[0]);
170	argp->pagelist++;
171	if (argp->pagelen < PAGE_SIZE) {
172		argp->end = p + (argp->pagelen>>2);
173		argp->pagelen = 0;
174	} else {
175		argp->end = p + (PAGE_SIZE>>2);
176		argp->pagelen -= PAGE_SIZE;
177	}
178	memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
179	argp->p += XDR_QUADLEN(nbytes - avail);
180	return p;
181}
182
183static int
184defer_free(struct nfsd4_compoundargs *argp,
185		void (*release)(const void *), void *p)
186{
187	struct tmpbuf *tb;
188
189	tb = kmalloc(sizeof(*tb), GFP_KERNEL);
190	if (!tb)
191		return -ENOMEM;
192	tb->buf = p;
193	tb->release = release;
194	tb->next = argp->to_free;
195	argp->to_free = tb;
196	return 0;
197}
198
199static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
200{
201	if (p == argp->tmp) {
202		p = kmalloc(nbytes, GFP_KERNEL);
203		if (!p)
204			return NULL;
205		memcpy(p, argp->tmp, nbytes);
206	} else {
207		BUG_ON(p != argp->tmpp);
208		argp->tmpp = NULL;
209	}
210	if (defer_free(argp, kfree, p)) {
211		kfree(p);
212		return NULL;
213	} else
214		return (char *)p;
215}
216
217static __be32
218nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
219{
220	u32 bmlen;
221	DECODE_HEAD;
222
223	bmval[0] = 0;
224	bmval[1] = 0;
225
226	READ_BUF(4);
227	READ32(bmlen);
228	if (bmlen > 1000)
229		goto xdr_error;
230
231	READ_BUF(bmlen << 2);
232	if (bmlen > 0)
233		READ32(bmval[0]);
234	if (bmlen > 1)
235		READ32(bmval[1]);
236
237	DECODE_TAIL;
238}
239
240static __be32
241nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr,
242    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	/*
255	 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP;
256	 * read-only attributes return ERR_INVAL.
257	 */
258	if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
259		return nfserr_attrnotsupp;
260	if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1))
261		return nfserr_inval;
262
263	READ_BUF(4);
264	READ32(expected_len);
265
266	if (bmval[0] & FATTR4_WORD0_SIZE) {
267		READ_BUF(8);
268		len += 8;
269		READ64(iattr->ia_size);
270		iattr->ia_valid |= ATTR_SIZE;
271	}
272	if (bmval[0] & FATTR4_WORD0_ACL) {
273		int nace;
274		struct nfs4_ace *ace;
275
276		READ_BUF(4); len += 4;
277		READ32(nace);
278
279		if (nace > NFS4_ACL_MAX)
280			return nfserr_resource;
281
282		*acl = nfs4_acl_new(nace);
283		if (*acl == NULL) {
284			host_err = -ENOMEM;
285			goto out_nfserr;
286		}
287		defer_free(argp, kfree, *acl);
288
289		(*acl)->naces = nace;
290		for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
291			READ_BUF(16); len += 16;
292			READ32(ace->type);
293			READ32(ace->flag);
294			READ32(ace->access_mask);
295			READ32(dummy32);
296			READ_BUF(dummy32);
297			len += XDR_QUADLEN(dummy32) << 2;
298			READMEM(buf, dummy32);
299			ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
300			host_err = 0;
301			if (ace->whotype != NFS4_ACL_WHO_NAMED)
302				ace->who = 0;
303			else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
304				host_err = nfsd_map_name_to_gid(argp->rqstp,
305						buf, dummy32, &ace->who);
306			else
307				host_err = nfsd_map_name_to_uid(argp->rqstp,
308						buf, dummy32, &ace->who);
309			if (host_err)
310				goto out_nfserr;
311		}
312	} else
313		*acl = NULL;
314	if (bmval[1] & FATTR4_WORD1_MODE) {
315		READ_BUF(4);
316		len += 4;
317		READ32(iattr->ia_mode);
318		iattr->ia_mode &= (S_IFMT | S_IALLUGO);
319		iattr->ia_valid |= ATTR_MODE;
320	}
321	if (bmval[1] & FATTR4_WORD1_OWNER) {
322		READ_BUF(4);
323		len += 4;
324		READ32(dummy32);
325		READ_BUF(dummy32);
326		len += (XDR_QUADLEN(dummy32) << 2);
327		READMEM(buf, dummy32);
328		if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
329			goto out_nfserr;
330		iattr->ia_valid |= ATTR_UID;
331	}
332	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
333		READ_BUF(4);
334		len += 4;
335		READ32(dummy32);
336		READ_BUF(dummy32);
337		len += (XDR_QUADLEN(dummy32) << 2);
338		READMEM(buf, dummy32);
339		if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
340			goto out_nfserr;
341		iattr->ia_valid |= ATTR_GID;
342	}
343	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
344		READ_BUF(4);
345		len += 4;
346		READ32(dummy32);
347		switch (dummy32) {
348		case NFS4_SET_TO_CLIENT_TIME:
349			/* We require the high 32 bits of 'seconds' to be 0, and we ignore
350			   all 32 bits of 'nseconds'. */
351			READ_BUF(12);
352			len += 12;
353			READ32(dummy32);
354			if (dummy32)
355				return nfserr_inval;
356			READ32(iattr->ia_atime.tv_sec);
357			READ32(iattr->ia_atime.tv_nsec);
358			if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
359				return nfserr_inval;
360			iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
361			break;
362		case NFS4_SET_TO_SERVER_TIME:
363			iattr->ia_valid |= ATTR_ATIME;
364			break;
365		default:
366			goto xdr_error;
367		}
368	}
369	if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
370		/* We require the high 32 bits of 'seconds' to be 0, and we ignore
371		   all 32 bits of 'nseconds'. */
372		READ_BUF(12);
373		len += 12;
374		READ32(dummy32);
375		if (dummy32)
376			return nfserr_inval;
377		READ32(iattr->ia_ctime.tv_sec);
378		READ32(iattr->ia_ctime.tv_nsec);
379		if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
380			return nfserr_inval;
381		iattr->ia_valid |= ATTR_CTIME;
382	}
383	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
384		READ_BUF(4);
385		len += 4;
386		READ32(dummy32);
387		switch (dummy32) {
388		case NFS4_SET_TO_CLIENT_TIME:
389			/* We require the high 32 bits of 'seconds' to be 0, and we ignore
390			   all 32 bits of 'nseconds'. */
391			READ_BUF(12);
392			len += 12;
393			READ32(dummy32);
394			if (dummy32)
395				return nfserr_inval;
396			READ32(iattr->ia_mtime.tv_sec);
397			READ32(iattr->ia_mtime.tv_nsec);
398			if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
399				return nfserr_inval;
400			iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
401			break;
402		case NFS4_SET_TO_SERVER_TIME:
403			iattr->ia_valid |= ATTR_MTIME;
404			break;
405		default:
406			goto xdr_error;
407		}
408	}
409	if (len != expected_len)
410		goto xdr_error;
411
412	DECODE_TAIL;
413
414out_nfserr:
415	status = nfserrno(host_err);
416	goto out;
417}
418
419static __be32
420nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
421{
422	DECODE_HEAD;
423
424	READ_BUF(4);
425	READ32(access->ac_req_access);
426
427	DECODE_TAIL;
428}
429
430static __be32
431nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
432{
433	DECODE_HEAD;
434
435	close->cl_stateowner = NULL;
436	READ_BUF(4 + sizeof(stateid_t));
437	READ32(close->cl_seqid);
438	READ32(close->cl_stateid.si_generation);
439	COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
440
441	DECODE_TAIL;
442}
443
444
445static __be32
446nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
447{
448	DECODE_HEAD;
449
450	READ_BUF(12);
451	READ64(commit->co_offset);
452	READ32(commit->co_count);
453
454	DECODE_TAIL;
455}
456
457static __be32
458nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
459{
460	DECODE_HEAD;
461
462	READ_BUF(4);
463	READ32(create->cr_type);
464	switch (create->cr_type) {
465	case NF4LNK:
466		READ_BUF(4);
467		READ32(create->cr_linklen);
468		READ_BUF(create->cr_linklen);
469		SAVEMEM(create->cr_linkname, create->cr_linklen);
470		break;
471	case NF4BLK:
472	case NF4CHR:
473		READ_BUF(8);
474		READ32(create->cr_specdata1);
475		READ32(create->cr_specdata2);
476		break;
477	case NF4SOCK:
478	case NF4FIFO:
479	case NF4DIR:
480	default:
481		break;
482	}
483
484	READ_BUF(4);
485	READ32(create->cr_namelen);
486	READ_BUF(create->cr_namelen);
487	SAVEMEM(create->cr_name, create->cr_namelen);
488	if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
489		return status;
490
491	if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl)))
492		goto out;
493
494	DECODE_TAIL;
495}
496
497static inline __be32
498nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
499{
500	DECODE_HEAD;
501
502	READ_BUF(sizeof(stateid_t));
503	READ32(dr->dr_stateid.si_generation);
504	COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t));
505
506	DECODE_TAIL;
507}
508
509static inline __be32
510nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
511{
512	return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
513}
514
515static __be32
516nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
517{
518	DECODE_HEAD;
519
520	READ_BUF(4);
521	READ32(link->li_namelen);
522	READ_BUF(link->li_namelen);
523	SAVEMEM(link->li_name, link->li_namelen);
524	if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
525		return status;
526
527	DECODE_TAIL;
528}
529
530static __be32
531nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
532{
533	DECODE_HEAD;
534
535	lock->lk_replay_owner = NULL;
536	/*
537	* type, reclaim(boolean), offset, length, new_lock_owner(boolean)
538	*/
539	READ_BUF(28);
540	READ32(lock->lk_type);
541	if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
542		goto xdr_error;
543	READ32(lock->lk_reclaim);
544	READ64(lock->lk_offset);
545	READ64(lock->lk_length);
546	READ32(lock->lk_is_new);
547
548	if (lock->lk_is_new) {
549		READ_BUF(36);
550		READ32(lock->lk_new_open_seqid);
551		READ32(lock->lk_new_open_stateid.si_generation);
552
553		COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t));
554		READ32(lock->lk_new_lock_seqid);
555		COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
556		READ32(lock->lk_new_owner.len);
557		READ_BUF(lock->lk_new_owner.len);
558		READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
559	} else {
560		READ_BUF(20);
561		READ32(lock->lk_old_lock_stateid.si_generation);
562		COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t));
563		READ32(lock->lk_old_lock_seqid);
564	}
565
566	DECODE_TAIL;
567}
568
569static __be32
570nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
571{
572	DECODE_HEAD;
573
574	READ_BUF(32);
575	READ32(lockt->lt_type);
576	if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
577		goto xdr_error;
578	READ64(lockt->lt_offset);
579	READ64(lockt->lt_length);
580	COPYMEM(&lockt->lt_clientid, 8);
581	READ32(lockt->lt_owner.len);
582	READ_BUF(lockt->lt_owner.len);
583	READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
584
585	DECODE_TAIL;
586}
587
588static __be32
589nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
590{
591	DECODE_HEAD;
592
593	locku->lu_stateowner = NULL;
594	READ_BUF(24 + sizeof(stateid_t));
595	READ32(locku->lu_type);
596	if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
597		goto xdr_error;
598	READ32(locku->lu_seqid);
599	READ32(locku->lu_stateid.si_generation);
600	COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
601	READ64(locku->lu_offset);
602	READ64(locku->lu_length);
603
604	DECODE_TAIL;
605}
606
607static __be32
608nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
609{
610	DECODE_HEAD;
611
612	READ_BUF(4);
613	READ32(lookup->lo_len);
614	READ_BUF(lookup->lo_len);
615	SAVEMEM(lookup->lo_name, lookup->lo_len);
616	if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
617		return status;
618
619	DECODE_TAIL;
620}
621
622static __be32
623nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
624{
625	DECODE_HEAD;
626
627	memset(open->op_bmval, 0, sizeof(open->op_bmval));
628	open->op_iattr.ia_valid = 0;
629	open->op_stateowner = NULL;
630
631	/* seqid, share_access, share_deny, clientid, ownerlen */
632	READ_BUF(16 + sizeof(clientid_t));
633	READ32(open->op_seqid);
634	READ32(open->op_share_access);
635	READ32(open->op_share_deny);
636	COPYMEM(&open->op_clientid, sizeof(clientid_t));
637	READ32(open->op_owner.len);
638
639	/* owner, open_flag */
640	READ_BUF(open->op_owner.len + 4);
641	SAVEMEM(open->op_owner.data, open->op_owner.len);
642	READ32(open->op_create);
643	switch (open->op_create) {
644	case NFS4_OPEN_NOCREATE:
645		break;
646	case NFS4_OPEN_CREATE:
647		READ_BUF(4);
648		READ32(open->op_createmode);
649		switch (open->op_createmode) {
650		case NFS4_CREATE_UNCHECKED:
651		case NFS4_CREATE_GUARDED:
652			if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl)))
653				goto out;
654			break;
655		case NFS4_CREATE_EXCLUSIVE:
656			READ_BUF(8);
657			COPYMEM(open->op_verf.data, 8);
658			break;
659		default:
660			goto xdr_error;
661		}
662		break;
663	default:
664		goto xdr_error;
665	}
666
667	/* open_claim */
668	READ_BUF(4);
669	READ32(open->op_claim_type);
670	switch (open->op_claim_type) {
671	case NFS4_OPEN_CLAIM_NULL:
672	case NFS4_OPEN_CLAIM_DELEGATE_PREV:
673		READ_BUF(4);
674		READ32(open->op_fname.len);
675		READ_BUF(open->op_fname.len);
676		SAVEMEM(open->op_fname.data, open->op_fname.len);
677		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
678			return status;
679		break;
680	case NFS4_OPEN_CLAIM_PREVIOUS:
681		READ_BUF(4);
682		READ32(open->op_delegate_type);
683		break;
684	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
685		READ_BUF(sizeof(stateid_t) + 4);
686		COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t));
687		READ32(open->op_fname.len);
688		READ_BUF(open->op_fname.len);
689		SAVEMEM(open->op_fname.data, open->op_fname.len);
690		if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
691			return status;
692		break;
693	default:
694		goto xdr_error;
695	}
696
697	DECODE_TAIL;
698}
699
700static __be32
701nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
702{
703	DECODE_HEAD;
704
705	open_conf->oc_stateowner = NULL;
706	READ_BUF(4 + sizeof(stateid_t));
707	READ32(open_conf->oc_req_stateid.si_generation);
708	COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
709	READ32(open_conf->oc_seqid);
710
711	DECODE_TAIL;
712}
713
714static __be32
715nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
716{
717	DECODE_HEAD;
718
719	open_down->od_stateowner = NULL;
720	READ_BUF(12 + sizeof(stateid_t));
721	READ32(open_down->od_stateid.si_generation);
722	COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
723	READ32(open_down->od_seqid);
724	READ32(open_down->od_share_access);
725	READ32(open_down->od_share_deny);
726
727	DECODE_TAIL;
728}
729
730static __be32
731nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
732{
733	DECODE_HEAD;
734
735	READ_BUF(4);
736	READ32(putfh->pf_fhlen);
737	if (putfh->pf_fhlen > NFS4_FHSIZE)
738		goto xdr_error;
739	READ_BUF(putfh->pf_fhlen);
740	SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
741
742	DECODE_TAIL;
743}
744
745static __be32
746nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
747{
748	DECODE_HEAD;
749
750	READ_BUF(sizeof(stateid_t) + 12);
751	READ32(read->rd_stateid.si_generation);
752	COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
753	READ64(read->rd_offset);
754	READ32(read->rd_length);
755
756	DECODE_TAIL;
757}
758
759static __be32
760nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
761{
762	DECODE_HEAD;
763
764	READ_BUF(24);
765	READ64(readdir->rd_cookie);
766	COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
767	READ32(readdir->rd_dircount);    /* just in case you needed a useless field... */
768	READ32(readdir->rd_maxcount);
769	if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
770		goto out;
771
772	DECODE_TAIL;
773}
774
775static __be32
776nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
777{
778	DECODE_HEAD;
779
780	READ_BUF(4);
781	READ32(remove->rm_namelen);
782	READ_BUF(remove->rm_namelen);
783	SAVEMEM(remove->rm_name, remove->rm_namelen);
784	if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
785		return status;
786
787	DECODE_TAIL;
788}
789
790static __be32
791nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
792{
793	DECODE_HEAD;
794
795	READ_BUF(4);
796	READ32(rename->rn_snamelen);
797	READ_BUF(rename->rn_snamelen + 4);
798	SAVEMEM(rename->rn_sname, rename->rn_snamelen);
799	READ32(rename->rn_tnamelen);
800	READ_BUF(rename->rn_tnamelen);
801	SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
802	if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
803		return status;
804	if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
805		return status;
806
807	DECODE_TAIL;
808}
809
810static __be32
811nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
812{
813	DECODE_HEAD;
814
815	READ_BUF(sizeof(clientid_t));
816	COPYMEM(clientid, sizeof(clientid_t));
817
818	DECODE_TAIL;
819}
820
821static __be32
822nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
823{
824	DECODE_HEAD;
825
826	READ_BUF(sizeof(stateid_t));
827	READ32(setattr->sa_stateid.si_generation);
828	COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
829	if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
830		goto out;
831
832	DECODE_TAIL;
833}
834
835static __be32
836nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
837{
838	DECODE_HEAD;
839
840	READ_BUF(12);
841	COPYMEM(setclientid->se_verf.data, 8);
842	READ32(setclientid->se_namelen);
843
844	READ_BUF(setclientid->se_namelen + 8);
845	SAVEMEM(setclientid->se_name, setclientid->se_namelen);
846	READ32(setclientid->se_callback_prog);
847	READ32(setclientid->se_callback_netid_len);
848
849	READ_BUF(setclientid->se_callback_netid_len + 4);
850	SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
851	READ32(setclientid->se_callback_addr_len);
852
853	READ_BUF(setclientid->se_callback_addr_len + 4);
854	SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
855	READ32(setclientid->se_callback_ident);
856
857	DECODE_TAIL;
858}
859
860static __be32
861nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
862{
863	DECODE_HEAD;
864
865	READ_BUF(8 + sizeof(nfs4_verifier));
866	COPYMEM(&scd_c->sc_clientid, 8);
867	COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
868
869	DECODE_TAIL;
870}
871
872/* Also used for NVERIFY */
873static __be32
874nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
875{
876	DECODE_HEAD;
877
878	if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
879		goto out;
880
881	/* For convenience's sake, we compare raw xdr'd attributes in
882	 * nfsd4_proc_verify; however we still decode here just to return
883	 * correct error in case of bad xdr. */
884	READ_BUF(4);
885	READ32(verify->ve_attrlen);
886	READ_BUF(verify->ve_attrlen);
887	SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
888
889	DECODE_TAIL;
890}
891
892static __be32
893nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
894{
895	int avail;
896	int v;
897	int len;
898	DECODE_HEAD;
899
900	READ_BUF(sizeof(stateid_opaque_t) + 20);
901	READ32(write->wr_stateid.si_generation);
902	COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
903	READ64(write->wr_offset);
904	READ32(write->wr_stable_how);
905	if (write->wr_stable_how > 2)
906		goto xdr_error;
907	READ32(write->wr_buflen);
908
909	/* Sorry .. no magic macros for this.. *
910	 * READ_BUF(write->wr_buflen);
911	 * SAVEMEM(write->wr_buf, write->wr_buflen);
912	 */
913	avail = (char*)argp->end - (char*)argp->p;
914	if (avail + argp->pagelen < write->wr_buflen) {
915		printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__);
916		goto xdr_error;
917	}
918	argp->rqstp->rq_vec[0].iov_base = p;
919	argp->rqstp->rq_vec[0].iov_len = avail;
920	v = 0;
921	len = write->wr_buflen;
922	while (len > argp->rqstp->rq_vec[v].iov_len) {
923		len -= argp->rqstp->rq_vec[v].iov_len;
924		v++;
925		argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]);
926		argp->pagelist++;
927		if (argp->pagelen >= PAGE_SIZE) {
928			argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE;
929			argp->pagelen -= PAGE_SIZE;
930		} else {
931			argp->rqstp->rq_vec[v].iov_len = argp->pagelen;
932			argp->pagelen -= len;
933		}
934	}
935	argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len);
936	argp->p = (__be32*)  (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
937	argp->rqstp->rq_vec[v].iov_len = len;
938	write->wr_vlen = v+1;
939
940	DECODE_TAIL;
941}
942
943static __be32
944nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
945{
946	DECODE_HEAD;
947
948	READ_BUF(12);
949	COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
950	READ32(rlockowner->rl_owner.len);
951	READ_BUF(rlockowner->rl_owner.len);
952	READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
953
954	DECODE_TAIL;
955}
956
957static __be32
958nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
959{
960	DECODE_HEAD;
961	struct nfsd4_op *op;
962	int i;
963
964	READ_BUF(4);
965	READ32(argp->taglen);
966	READ_BUF(argp->taglen + 8);
967	SAVEMEM(argp->tag, argp->taglen);
968	READ32(argp->minorversion);
969	READ32(argp->opcnt);
970
971	if (argp->taglen > NFSD4_MAX_TAGLEN)
972		goto xdr_error;
973	if (argp->opcnt > 100)
974		goto xdr_error;
975
976	if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
977		argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
978		if (!argp->ops) {
979			argp->ops = argp->iops;
980			printk(KERN_INFO "nfsd: couldn't allocate room for COMPOUND\n");
981			goto xdr_error;
982		}
983	}
984
985	for (i = 0; i < argp->opcnt; i++) {
986		op = &argp->ops[i];
987		op->replay = NULL;
988
989		/*
990		 * We can't use READ_BUF() here because we need to handle
991		 * a missing opcode as an OP_WRITE + 1. So we need to check
992		 * to see if we're truly at the end of our buffer or if there
993		 * is another page we need to flip to.
994		 */
995
996		if (argp->p == argp->end) {
997			if (argp->pagelen < 4) {
998				/* There isn't an opcode still on the wire */
999				op->opnum = OP_WRITE + 1;
1000				op->status = nfserr_bad_xdr;
1001				argp->opcnt = i+1;
1002				break;
1003			}
1004
1005			/*
1006			 * False alarm. We just hit a page boundary, but there
1007			 * is still data available.  Move pointer across page
1008			 * boundary.  *snip from READ_BUF*
1009			 */
1010			argp->p = page_address(argp->pagelist[0]);
1011			argp->pagelist++;
1012			if (argp->pagelen < PAGE_SIZE) {
1013				argp->end = p + (argp->pagelen>>2);
1014				argp->pagelen = 0;
1015			} else {
1016				argp->end = p + (PAGE_SIZE>>2);
1017				argp->pagelen -= PAGE_SIZE;
1018			}
1019		}
1020		op->opnum = ntohl(*argp->p++);
1021
1022		switch (op->opnum) {
1023		case 2: /* Reserved operation */
1024			op->opnum = OP_ILLEGAL;
1025			if (argp->minorversion == 0)
1026				op->status = nfserr_op_illegal;
1027			else
1028				op->status = nfserr_minor_vers_mismatch;
1029			break;
1030		case OP_ACCESS:
1031			op->status = nfsd4_decode_access(argp, &op->u.access);
1032			break;
1033		case OP_CLOSE:
1034			op->status = nfsd4_decode_close(argp, &op->u.close);
1035			break;
1036		case OP_COMMIT:
1037			op->status = nfsd4_decode_commit(argp, &op->u.commit);
1038			break;
1039		case OP_CREATE:
1040			op->status = nfsd4_decode_create(argp, &op->u.create);
1041			break;
1042		case OP_DELEGRETURN:
1043			op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn);
1044			break;
1045		case OP_GETATTR:
1046			op->status = nfsd4_decode_getattr(argp, &op->u.getattr);
1047			break;
1048		case OP_GETFH:
1049			op->status = nfs_ok;
1050			break;
1051		case OP_LINK:
1052			op->status = nfsd4_decode_link(argp, &op->u.link);
1053			break;
1054		case OP_LOCK:
1055			op->status = nfsd4_decode_lock(argp, &op->u.lock);
1056			break;
1057		case OP_LOCKT:
1058			op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
1059			break;
1060		case OP_LOCKU:
1061			op->status = nfsd4_decode_locku(argp, &op->u.locku);
1062			break;
1063		case OP_LOOKUP:
1064			op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
1065			break;
1066		case OP_LOOKUPP:
1067			op->status = nfs_ok;
1068			break;
1069		case OP_NVERIFY:
1070			op->status = nfsd4_decode_verify(argp, &op->u.nverify);
1071			break;
1072		case OP_OPEN:
1073			op->status = nfsd4_decode_open(argp, &op->u.open);
1074			break;
1075		case OP_OPEN_CONFIRM:
1076			op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
1077			break;
1078		case OP_OPEN_DOWNGRADE:
1079			op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
1080			break;
1081		case OP_PUTFH:
1082			op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
1083			break;
1084		case OP_PUTROOTFH:
1085			op->status = nfs_ok;
1086			break;
1087		case OP_READ:
1088			op->status = nfsd4_decode_read(argp, &op->u.read);
1089			break;
1090		case OP_READDIR:
1091			op->status = nfsd4_decode_readdir(argp, &op->u.readdir);
1092			break;
1093		case OP_READLINK:
1094			op->status = nfs_ok;
1095			break;
1096		case OP_REMOVE:
1097			op->status = nfsd4_decode_remove(argp, &op->u.remove);
1098			break;
1099		case OP_RENAME:
1100			op->status = nfsd4_decode_rename(argp, &op->u.rename);
1101			break;
1102		case OP_RESTOREFH:
1103			op->status = nfs_ok;
1104			break;
1105		case OP_RENEW:
1106			op->status = nfsd4_decode_renew(argp, &op->u.renew);
1107			break;
1108		case OP_SAVEFH:
1109			op->status = nfs_ok;
1110			break;
1111		case OP_SETATTR:
1112			op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
1113			break;
1114		case OP_SETCLIENTID:
1115			op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid);
1116			break;
1117		case OP_SETCLIENTID_CONFIRM:
1118			op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm);
1119			break;
1120		case OP_VERIFY:
1121			op->status = nfsd4_decode_verify(argp, &op->u.verify);
1122			break;
1123		case OP_WRITE:
1124			op->status = nfsd4_decode_write(argp, &op->u.write);
1125			break;
1126		case OP_RELEASE_LOCKOWNER:
1127			op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
1128			break;
1129		default:
1130			op->opnum = OP_ILLEGAL;
1131			op->status = nfserr_op_illegal;
1132			break;
1133		}
1134
1135		if (op->status) {
1136			argp->opcnt = i+1;
1137			break;
1138		}
1139	}
1140
1141	DECODE_TAIL;
1142}
1143/*
1144 * END OF "GENERIC" DECODE ROUTINES.
1145 */
1146
1147/*
1148 * START OF "GENERIC" ENCODE ROUTINES.
1149 *   These may look a little ugly since they are imported from a "generic"
1150 * set of XDR encode/decode routines which are intended to be shared by
1151 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
1152 *
1153 * If the pain of reading these is too great, it should be a straightforward
1154 * task to translate them into Linux-specific versions which are more
1155 * consistent with the style used in NFSv2/v3...
1156 */
1157#define ENCODE_HEAD              __be32 *p
1158
1159#define WRITE32(n)               *p++ = htonl(n)
1160#define WRITE64(n)               do {				\
1161	*p++ = htonl((u32)((n) >> 32));				\
1162	*p++ = htonl((u32)(n));					\
1163} while (0)
1164#define WRITEMEM(ptr,nbytes)     do {				\
1165	*(p + XDR_QUADLEN(nbytes) -1) = 0;                      \
1166	memcpy(p, ptr, nbytes);					\
1167	p += XDR_QUADLEN(nbytes);				\
1168} while (0)
1169#define WRITECINFO(c)		do {				\
1170	*p++ = htonl(c.atomic);					\
1171	*p++ = htonl(c.before_ctime_sec);				\
1172	*p++ = htonl(c.before_ctime_nsec);				\
1173	*p++ = htonl(c.after_ctime_sec);				\
1174	*p++ = htonl(c.after_ctime_nsec);				\
1175} while (0)
1176
1177#define RESERVE_SPACE(nbytes)	do {				\
1178	p = resp->p;						\
1179	BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end);		\
1180} while (0)
1181#define ADJUST_ARGS()		resp->p = p
1182
1183/*
1184 * Header routine to setup seqid operation replay cache
1185 */
1186#define ENCODE_SEQID_OP_HEAD					\
1187	__be32 *p;						\
1188	__be32 *save;						\
1189								\
1190	save = resp->p;
1191
1192/*
1193 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation.  This
1194 * is where sequence id's are incremented, and the replay cache is filled.
1195 * Note that we increment sequence id's here, at the last moment, so we're sure
1196 * we know whether the error to be returned is a sequence id mutating error.
1197 */
1198
1199#define ENCODE_SEQID_OP_TAIL(stateowner) do {			\
1200	if (seqid_mutating_err(nfserr) && stateowner) { 	\
1201		stateowner->so_seqid++;				\
1202		stateowner->so_replay.rp_status = nfserr;   	\
1203		stateowner->so_replay.rp_buflen = 		\
1204			  (((char *)(resp)->p - (char *)save)); \
1205		memcpy(stateowner->so_replay.rp_buf, save,      \
1206 			stateowner->so_replay.rp_buflen); 	\
1207	} } while (0);
1208
1209/* Encode as an array of strings the string given with components
1210 * seperated @sep.
1211 */
1212static __be32 nfsd4_encode_components(char sep, char *components,
1213				   __be32 **pp, int *buflen)
1214{
1215	__be32 *p = *pp;
1216	__be32 *countp = p;
1217	int strlen, count=0;
1218	char *str, *end;
1219
1220	dprintk("nfsd4_encode_components(%s)\n", components);
1221	if ((*buflen -= 4) < 0)
1222		return nfserr_resource;
1223	WRITE32(0); /* We will fill this in with @count later */
1224	end = str = components;
1225	while (*end) {
1226		for (; *end && (*end != sep); end++)
1227			; /* Point to end of component */
1228		strlen = end - str;
1229		if (strlen) {
1230			if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0)
1231				return nfserr_resource;
1232			WRITE32(strlen);
1233			WRITEMEM(str, strlen);
1234			count++;
1235		}
1236		else
1237			end++;
1238		str = end;
1239	}
1240	*pp = p;
1241	p = countp;
1242	WRITE32(count);
1243	return 0;
1244}
1245
1246/*
1247 * encode a location element of a fs_locations structure
1248 */
1249static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location,
1250				    __be32 **pp, int *buflen)
1251{
1252	__be32 status;
1253	__be32 *p = *pp;
1254
1255	status = nfsd4_encode_components(':', location->hosts, &p, buflen);
1256	if (status)
1257		return status;
1258	status = nfsd4_encode_components('/', location->path, &p, buflen);
1259	if (status)
1260		return status;
1261	*pp = p;
1262	return 0;
1263}
1264
1265/*
1266 * Return the path to an export point in the pseudo filesystem namespace
1267 * Returned string is safe to use as long as the caller holds a reference
1268 * to @exp.
1269 */
1270static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat)
1271{
1272	struct svc_fh tmp_fh;
1273	char *path, *rootpath;
1274
1275	fh_init(&tmp_fh, NFS4_FHSIZE);
1276	*stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle);
1277	if (*stat)
1278		return NULL;
1279	rootpath = tmp_fh.fh_export->ex_path;
1280
1281	path = exp->ex_path;
1282
1283	if (strncmp(path, rootpath, strlen(rootpath))) {
1284		printk("nfsd: fs_locations failed;"
1285			"%s is not contained in %s\n", path, rootpath);
1286		*stat = nfserr_notsupp;
1287		return NULL;
1288	}
1289
1290	return path + strlen(rootpath);
1291}
1292
1293/*
1294 *  encode a fs_locations structure
1295 */
1296static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp,
1297				     struct svc_export *exp,
1298				     __be32 **pp, int *buflen)
1299{
1300	__be32 status;
1301	int i;
1302	__be32 *p = *pp;
1303	struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
1304	char *root = nfsd4_path(rqstp, exp, &status);
1305
1306	if (status)
1307		return status;
1308	status = nfsd4_encode_components('/', root, &p, buflen);
1309	if (status)
1310		return status;
1311	if ((*buflen -= 4) < 0)
1312		return nfserr_resource;
1313	WRITE32(fslocs->locations_count);
1314	for (i=0; i<fslocs->locations_count; i++) {
1315		status = nfsd4_encode_fs_location4(&fslocs->locations[i],
1316						   &p, buflen);
1317		if (status)
1318			return status;
1319	}
1320	*pp = p;
1321	return 0;
1322}
1323
1324static u32 nfs4_ftypes[16] = {
1325        NF4BAD,  NF4FIFO, NF4CHR, NF4BAD,
1326        NF4DIR,  NF4BAD,  NF4BLK, NF4BAD,
1327        NF4REG,  NF4BAD,  NF4LNK, NF4BAD,
1328        NF4SOCK, NF4BAD,  NF4LNK, NF4BAD,
1329};
1330
1331static __be32
1332nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1333			__be32 **p, int *buflen)
1334{
1335	int status;
1336
1337	if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1338		return nfserr_resource;
1339	if (whotype != NFS4_ACL_WHO_NAMED)
1340		status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1341	else if (group)
1342		status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1343	else
1344		status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1345	if (status < 0)
1346		return nfserrno(status);
1347	*p = xdr_encode_opaque(*p, NULL, status);
1348	*buflen -= (XDR_QUADLEN(status) << 2) + 4;
1349	BUG_ON(*buflen < 0);
1350	return 0;
1351}
1352
1353static inline __be32
1354nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
1355{
1356	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1357}
1358
1359static inline __be32
1360nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
1361{
1362	return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1363}
1364
1365static inline __be32
1366nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1367		__be32 **p, int *buflen)
1368{
1369	return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1370}
1371
1372#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
1373			      FATTR4_WORD0_RDATTR_ERROR)
1374#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
1375
1376static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err)
1377{
1378	/* As per referral draft:  */
1379	if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
1380	    *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
1381		if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
1382	            *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
1383			*rdattr_err = NFSERR_MOVED;
1384		else
1385			return nfserr_moved;
1386	}
1387	*bmval0 &= WORD0_ABSENT_FS_ATTRS;
1388	*bmval1 &= WORD1_ABSENT_FS_ATTRS;
1389	return 0;
1390}
1391
1392/*
1393 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
1394 * ourselves.
1395 *
1396 * @countp is the buffer size in _words_; upon successful return this becomes
1397 * replaced with the number of words written.
1398 */
1399__be32
1400nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1401		struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval,
1402		struct svc_rqst *rqstp)
1403{
1404	u32 bmval0 = bmval[0];
1405	u32 bmval1 = bmval[1];
1406	struct kstat stat;
1407	struct svc_fh tempfh;
1408	struct kstatfs statfs;
1409	int buflen = *countp << 2;
1410	__be32 *attrlenp;
1411	u32 dummy;
1412	u64 dummy64;
1413	u32 rdattr_err = 0;
1414	__be32 *p = buffer;
1415	__be32 status;
1416	int err;
1417	int aclsupport = 0;
1418	struct nfs4_acl *acl = NULL;
1419
1420	BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1421	BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
1422	BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
1423
1424	if (exp->ex_fslocs.migrated) {
1425		status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err);
1426		if (status)
1427			goto out;
1428	}
1429
1430	err = vfs_getattr(exp->ex_mnt, dentry, &stat);
1431	if (err)
1432		goto out_nfserr;
1433	if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
1434	    (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1435		       FATTR4_WORD1_SPACE_TOTAL))) {
1436		err = vfs_statfs(dentry, &statfs);
1437		if (err)
1438			goto out_nfserr;
1439	}
1440	if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
1441		fh_init(&tempfh, NFS4_FHSIZE);
1442		status = fh_compose(&tempfh, exp, dentry, NULL);
1443		if (status)
1444			goto out;
1445		fhp = &tempfh;
1446	}
1447	if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1448			| FATTR4_WORD0_SUPPORTED_ATTRS)) {
1449		err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1450		aclsupport = (err == 0);
1451		if (bmval0 & FATTR4_WORD0_ACL) {
1452			if (err == -EOPNOTSUPP)
1453				bmval0 &= ~FATTR4_WORD0_ACL;
1454			else if (err == -EINVAL) {
1455				status = nfserr_attrnotsupp;
1456				goto out;
1457			} else if (err != 0)
1458				goto out_nfserr;
1459		}
1460	}
1461	if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1462		if (exp->ex_fslocs.locations == NULL) {
1463			bmval0 &= ~FATTR4_WORD0_FS_LOCATIONS;
1464		}
1465	}
1466	if ((buflen -= 16) < 0)
1467		goto out_resource;
1468
1469	WRITE32(2);
1470	WRITE32(bmval0);
1471	WRITE32(bmval1);
1472	attrlenp = p++;                /* to be backfilled later */
1473
1474	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1475		u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0;
1476		if ((buflen -= 12) < 0)
1477			goto out_resource;
1478		if (!aclsupport)
1479			word0 &= ~FATTR4_WORD0_ACL;
1480		if (!exp->ex_fslocs.locations)
1481			word0 &= ~FATTR4_WORD0_FS_LOCATIONS;
1482		WRITE32(2);
1483		WRITE32(word0);
1484		WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
1485	}
1486	if (bmval0 & FATTR4_WORD0_TYPE) {
1487		if ((buflen -= 4) < 0)
1488			goto out_resource;
1489		dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1490		if (dummy == NF4BAD)
1491			goto out_serverfault;
1492		WRITE32(dummy);
1493	}
1494	if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1495		if ((buflen -= 4) < 0)
1496			goto out_resource;
1497		if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
1498			WRITE32(NFS4_FH_PERSISTENT);
1499		else
1500			WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME);
1501	}
1502	if (bmval0 & FATTR4_WORD0_CHANGE) {
1503		/*
1504		 * Note: This _must_ be consistent with the scheme for writing
1505		 * change_info, so any changes made here must be reflected there
1506		 * as well.  (See xdr4.h:set_change_info() and the WRITECINFO()
1507		 * macro above.)
1508		 */
1509		if ((buflen -= 8) < 0)
1510			goto out_resource;
1511		WRITE32(stat.ctime.tv_sec);
1512		WRITE32(stat.ctime.tv_nsec);
1513	}
1514	if (bmval0 & FATTR4_WORD0_SIZE) {
1515		if ((buflen -= 8) < 0)
1516			goto out_resource;
1517		WRITE64(stat.size);
1518	}
1519	if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1520		if ((buflen -= 4) < 0)
1521			goto out_resource;
1522		WRITE32(1);
1523	}
1524	if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1525		if ((buflen -= 4) < 0)
1526			goto out_resource;
1527		WRITE32(1);
1528	}
1529	if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1530		if ((buflen -= 4) < 0)
1531			goto out_resource;
1532		WRITE32(0);
1533	}
1534	if (bmval0 & FATTR4_WORD0_FSID) {
1535		if ((buflen -= 16) < 0)
1536			goto out_resource;
1537		if (exp->ex_fslocs.migrated) {
1538			WRITE64(NFS4_REFERRAL_FSID_MAJOR);
1539			WRITE64(NFS4_REFERRAL_FSID_MINOR);
1540		} else switch(fsid_source(fhp)) {
1541		case FSIDSOURCE_FSID:
1542			WRITE64((u64)exp->ex_fsid);
1543			WRITE64((u64)0);
1544			break;
1545		case FSIDSOURCE_DEV:
1546			WRITE32(0);
1547			WRITE32(MAJOR(stat.dev));
1548			WRITE32(0);
1549			WRITE32(MINOR(stat.dev));
1550			break;
1551		case FSIDSOURCE_UUID:
1552			WRITEMEM(exp->ex_uuid, 16);
1553			break;
1554		}
1555	}
1556	if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1557		if ((buflen -= 4) < 0)
1558			goto out_resource;
1559		WRITE32(0);
1560	}
1561	if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1562		if ((buflen -= 4) < 0)
1563			goto out_resource;
1564		WRITE32(NFSD_LEASE_TIME);
1565	}
1566	if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1567		if ((buflen -= 4) < 0)
1568			goto out_resource;
1569		WRITE32(rdattr_err);
1570	}
1571	if (bmval0 & FATTR4_WORD0_ACL) {
1572		struct nfs4_ace *ace;
1573
1574		if (acl == NULL) {
1575			if ((buflen -= 4) < 0)
1576				goto out_resource;
1577
1578			WRITE32(0);
1579			goto out_acl;
1580		}
1581		if ((buflen -= 4) < 0)
1582			goto out_resource;
1583		WRITE32(acl->naces);
1584
1585		for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
1586			if ((buflen -= 4*3) < 0)
1587				goto out_resource;
1588			WRITE32(ace->type);
1589			WRITE32(ace->flag);
1590			WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
1591			status = nfsd4_encode_aclname(rqstp, ace->whotype,
1592				ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
1593				&p, &buflen);
1594			if (status == nfserr_resource)
1595				goto out_resource;
1596			if (status)
1597				goto out;
1598		}
1599	}
1600out_acl:
1601	if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1602		if ((buflen -= 4) < 0)
1603			goto out_resource;
1604		WRITE32(aclsupport ?
1605			ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
1606	}
1607	if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1608		if ((buflen -= 4) < 0)
1609			goto out_resource;
1610		WRITE32(1);
1611	}
1612	if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1613		if ((buflen -= 4) < 0)
1614			goto out_resource;
1615		WRITE32(1);
1616	}
1617	if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1618		if ((buflen -= 4) < 0)
1619			goto out_resource;
1620		WRITE32(1);
1621	}
1622	if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1623		if ((buflen -= 4) < 0)
1624			goto out_resource;
1625		WRITE32(1);
1626	}
1627	if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1628		buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1629		if (buflen < 0)
1630			goto out_resource;
1631		WRITE32(fhp->fh_handle.fh_size);
1632		WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1633	}
1634	if (bmval0 & FATTR4_WORD0_FILEID) {
1635		if ((buflen -= 8) < 0)
1636			goto out_resource;
1637		WRITE64((u64) stat.ino);
1638	}
1639	if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1640		if ((buflen -= 8) < 0)
1641			goto out_resource;
1642		WRITE64((u64) statfs.f_ffree);
1643	}
1644	if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1645		if ((buflen -= 8) < 0)
1646			goto out_resource;
1647		WRITE64((u64) statfs.f_ffree);
1648	}
1649	if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1650		if ((buflen -= 8) < 0)
1651			goto out_resource;
1652		WRITE64((u64) statfs.f_files);
1653	}
1654	if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
1655		status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen);
1656		if (status == nfserr_resource)
1657			goto out_resource;
1658		if (status)
1659			goto out;
1660	}
1661	if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1662		if ((buflen -= 4) < 0)
1663			goto out_resource;
1664		WRITE32(1);
1665	}
1666	if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
1667		if ((buflen -= 8) < 0)
1668			goto out_resource;
1669		WRITE64(~(u64)0);
1670	}
1671	if (bmval0 & FATTR4_WORD0_MAXLINK) {
1672		if ((buflen -= 4) < 0)
1673			goto out_resource;
1674		WRITE32(255);
1675	}
1676	if (bmval0 & FATTR4_WORD0_MAXNAME) {
1677		if ((buflen -= 4) < 0)
1678			goto out_resource;
1679		WRITE32(~(u32) 0);
1680	}
1681	if (bmval0 & FATTR4_WORD0_MAXREAD) {
1682		if ((buflen -= 8) < 0)
1683			goto out_resource;
1684		WRITE64((u64) svc_max_payload(rqstp));
1685	}
1686	if (bmval0 & FATTR4_WORD0_MAXWRITE) {
1687		if ((buflen -= 8) < 0)
1688			goto out_resource;
1689		WRITE64((u64) svc_max_payload(rqstp));
1690	}
1691	if (bmval1 & FATTR4_WORD1_MODE) {
1692		if ((buflen -= 4) < 0)
1693			goto out_resource;
1694		WRITE32(stat.mode & S_IALLUGO);
1695	}
1696	if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
1697		if ((buflen -= 4) < 0)
1698			goto out_resource;
1699		WRITE32(1);
1700	}
1701	if (bmval1 & FATTR4_WORD1_NUMLINKS) {
1702		if ((buflen -= 4) < 0)
1703			goto out_resource;
1704		WRITE32(stat.nlink);
1705	}
1706	if (bmval1 & FATTR4_WORD1_OWNER) {
1707		status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
1708		if (status == nfserr_resource)
1709			goto out_resource;
1710		if (status)
1711			goto out;
1712	}
1713	if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
1714		status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
1715		if (status == nfserr_resource)
1716			goto out_resource;
1717		if (status)
1718			goto out;
1719	}
1720	if (bmval1 & FATTR4_WORD1_RAWDEV) {
1721		if ((buflen -= 8) < 0)
1722			goto out_resource;
1723		WRITE32((u32) MAJOR(stat.rdev));
1724		WRITE32((u32) MINOR(stat.rdev));
1725	}
1726	if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
1727		if ((buflen -= 8) < 0)
1728			goto out_resource;
1729		dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
1730		WRITE64(dummy64);
1731	}
1732	if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
1733		if ((buflen -= 8) < 0)
1734			goto out_resource;
1735		dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
1736		WRITE64(dummy64);
1737	}
1738	if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
1739		if ((buflen -= 8) < 0)
1740			goto out_resource;
1741		dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
1742		WRITE64(dummy64);
1743	}
1744	if (bmval1 & FATTR4_WORD1_SPACE_USED) {
1745		if ((buflen -= 8) < 0)
1746			goto out_resource;
1747		dummy64 = (u64)stat.blocks << 9;
1748		WRITE64(dummy64);
1749	}
1750	if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
1751		if ((buflen -= 12) < 0)
1752			goto out_resource;
1753		WRITE32(0);
1754		WRITE32(stat.atime.tv_sec);
1755		WRITE32(stat.atime.tv_nsec);
1756	}
1757	if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
1758		if ((buflen -= 12) < 0)
1759			goto out_resource;
1760		WRITE32(0);
1761		WRITE32(1);
1762		WRITE32(0);
1763	}
1764	if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
1765		if ((buflen -= 12) < 0)
1766			goto out_resource;
1767		WRITE32(0);
1768		WRITE32(stat.ctime.tv_sec);
1769		WRITE32(stat.ctime.tv_nsec);
1770	}
1771	if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
1772		if ((buflen -= 12) < 0)
1773			goto out_resource;
1774		WRITE32(0);
1775		WRITE32(stat.mtime.tv_sec);
1776		WRITE32(stat.mtime.tv_nsec);
1777	}
1778	if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
1779		struct dentry *mnt_pnt, *mnt_root;
1780
1781		if ((buflen -= 8) < 0)
1782                	goto out_resource;
1783		mnt_root = exp->ex_mnt->mnt_root;
1784		if (mnt_root->d_inode == dentry->d_inode) {
1785			mnt_pnt = exp->ex_mnt->mnt_mountpoint;
1786			WRITE64((u64) mnt_pnt->d_inode->i_ino);
1787		} else
1788                	WRITE64((u64) stat.ino);
1789	}
1790	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1791	*countp = p - buffer;
1792	status = nfs_ok;
1793
1794out:
1795	kfree(acl);
1796	if (fhp == &tempfh)
1797		fh_put(&tempfh);
1798	return status;
1799out_nfserr:
1800	status = nfserrno(err);
1801	goto out;
1802out_resource:
1803	*countp = 0;
1804	status = nfserr_resource;
1805	goto out;
1806out_serverfault:
1807	status = nfserr_serverfault;
1808	goto out;
1809}
1810
1811static __be32
1812nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
1813		const char *name, int namlen, __be32 *p, int *buflen)
1814{
1815	struct svc_export *exp = cd->rd_fhp->fh_export;
1816	struct dentry *dentry;
1817	__be32 nfserr;
1818
1819	dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
1820	if (IS_ERR(dentry))
1821		return nfserrno(PTR_ERR(dentry));
1822
1823	exp_get(exp);
1824	if (d_mountpoint(dentry)) {
1825		int err;
1826
1827		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
1828		if (err) {
1829			nfserr = nfserrno(err);
1830			goto out_put;
1831		}
1832
1833	}
1834	nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
1835					cd->rd_rqstp);
1836out_put:
1837	dput(dentry);
1838	exp_put(exp);
1839	return nfserr;
1840}
1841
1842static __be32 *
1843nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr)
1844{
1845	__be32 *attrlenp;
1846
1847	if (buflen < 6)
1848		return NULL;
1849	*p++ = htonl(2);
1850	*p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
1851	*p++ = htonl(0);			 /* bmval1 */
1852
1853	attrlenp = p++;
1854	*p++ = nfserr;       /* no htonl */
1855	*attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1856	return p;
1857}
1858
1859static int
1860nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
1861		    loff_t offset, u64 ino, unsigned int d_type)
1862{
1863	struct readdir_cd *ccd = ccdv;
1864	struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
1865	int buflen;
1866	__be32 *p = cd->buffer;
1867	__be32 nfserr = nfserr_toosmall;
1868
1869	/* In nfsv4, "." and ".." never make it onto the wire.. */
1870	if (name && isdotent(name, namlen)) {
1871		cd->common.err = nfs_ok;
1872		return 0;
1873	}
1874
1875	if (cd->offset)
1876		xdr_encode_hyper(cd->offset, (u64) offset);
1877
1878	buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
1879	if (buflen < 0)
1880		goto fail;
1881
1882	*p++ = xdr_one;                             /* mark entry present */
1883	cd->offset = p;                             /* remember pointer */
1884	p = xdr_encode_hyper(p, NFS_OFFSET_MAX);    /* offset of next entry */
1885	p = xdr_encode_array(p, name, namlen);      /* name length & name */
1886
1887	nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
1888	switch (nfserr) {
1889	case nfs_ok:
1890		p += buflen;
1891		break;
1892	case nfserr_resource:
1893		nfserr = nfserr_toosmall;
1894		goto fail;
1895	case nfserr_dropit:
1896		goto fail;
1897	default:
1898		/*
1899		 * If the client requested the RDATTR_ERROR attribute,
1900		 * we stuff the error code into this attribute
1901		 * and continue.  If this attribute was not requested,
1902		 * then in accordance with the spec, we fail the
1903		 * entire READDIR operation(!)
1904		 */
1905		if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
1906			goto fail;
1907		p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
1908		if (p == NULL) {
1909			nfserr = nfserr_toosmall;
1910			goto fail;
1911		}
1912	}
1913	cd->buflen -= (p - cd->buffer);
1914	cd->buffer = p;
1915	cd->common.err = nfs_ok;
1916	return 0;
1917fail:
1918	cd->common.err = nfserr;
1919	return -EINVAL;
1920}
1921
1922static void
1923nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
1924{
1925	ENCODE_HEAD;
1926
1927	if (!nfserr) {
1928		RESERVE_SPACE(8);
1929		WRITE32(access->ac_supported);
1930		WRITE32(access->ac_resp_access);
1931		ADJUST_ARGS();
1932	}
1933}
1934
1935static void
1936nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
1937{
1938	ENCODE_SEQID_OP_HEAD;
1939
1940	if (!nfserr) {
1941		RESERVE_SPACE(sizeof(stateid_t));
1942		WRITE32(close->cl_stateid.si_generation);
1943		WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
1944		ADJUST_ARGS();
1945	}
1946	ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
1947}
1948
1949
1950static void
1951nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
1952{
1953	ENCODE_HEAD;
1954
1955	if (!nfserr) {
1956		RESERVE_SPACE(8);
1957		WRITEMEM(commit->co_verf.data, 8);
1958		ADJUST_ARGS();
1959	}
1960}
1961
1962static void
1963nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
1964{
1965	ENCODE_HEAD;
1966
1967	if (!nfserr) {
1968		RESERVE_SPACE(32);
1969		WRITECINFO(create->cr_cinfo);
1970		WRITE32(2);
1971		WRITE32(create->cr_bmval[0]);
1972		WRITE32(create->cr_bmval[1]);
1973		ADJUST_ARGS();
1974	}
1975}
1976
1977static __be32
1978nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
1979{
1980	struct svc_fh *fhp = getattr->ga_fhp;
1981	int buflen;
1982
1983	if (nfserr)
1984		return nfserr;
1985
1986	buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
1987	nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
1988				    resp->p, &buflen, getattr->ga_bmval,
1989				    resp->rqstp);
1990	if (!nfserr)
1991		resp->p += buflen;
1992	return nfserr;
1993}
1994
1995static void
1996nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp)
1997{
1998	unsigned int len;
1999	ENCODE_HEAD;
2000
2001	if (!nfserr) {
2002		len = fhp->fh_handle.fh_size;
2003		RESERVE_SPACE(len + 4);
2004		WRITE32(len);
2005		WRITEMEM(&fhp->fh_handle.fh_base, len);
2006		ADJUST_ARGS();
2007	}
2008}
2009
2010/*
2011* Including all fields other than the name, a LOCK4denied structure requires
2012*   8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
2013*/
2014static void
2015nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
2016{
2017	ENCODE_HEAD;
2018
2019	RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0));
2020	WRITE64(ld->ld_start);
2021	WRITE64(ld->ld_length);
2022	WRITE32(ld->ld_type);
2023	if (ld->ld_sop) {
2024		WRITEMEM(&ld->ld_clientid, 8);
2025		WRITE32(ld->ld_sop->so_owner.len);
2026		WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
2027		kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
2028	}  else {  /* non - nfsv4 lock in conflict, no clientid nor owner */
2029		WRITE64((u64)0); /* clientid */
2030		WRITE32(0); /* length of owner name */
2031	}
2032	ADJUST_ARGS();
2033}
2034
2035static void
2036nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
2037{
2038	ENCODE_SEQID_OP_HEAD;
2039
2040	if (!nfserr) {
2041		RESERVE_SPACE(4 + sizeof(stateid_t));
2042		WRITE32(lock->lk_resp_stateid.si_generation);
2043		WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2044		ADJUST_ARGS();
2045	} else if (nfserr == nfserr_denied)
2046		nfsd4_encode_lock_denied(resp, &lock->lk_denied);
2047
2048	ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner);
2049}
2050
2051static void
2052nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
2053{
2054	if (nfserr == nfserr_denied)
2055		nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
2056}
2057
2058static void
2059nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
2060{
2061	ENCODE_SEQID_OP_HEAD;
2062
2063	if (!nfserr) {
2064		RESERVE_SPACE(sizeof(stateid_t));
2065		WRITE32(locku->lu_stateid.si_generation);
2066		WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
2067		ADJUST_ARGS();
2068	}
2069
2070	ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
2071}
2072
2073
2074static void
2075nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
2076{
2077	ENCODE_HEAD;
2078
2079	if (!nfserr) {
2080		RESERVE_SPACE(20);
2081		WRITECINFO(link->li_cinfo);
2082		ADJUST_ARGS();
2083	}
2084}
2085
2086
2087static void
2088nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
2089{
2090	ENCODE_SEQID_OP_HEAD;
2091
2092	if (nfserr)
2093		goto out;
2094
2095	RESERVE_SPACE(36 + sizeof(stateid_t));
2096	WRITE32(open->op_stateid.si_generation);
2097	WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
2098	WRITECINFO(open->op_cinfo);
2099	WRITE32(open->op_rflags);
2100	WRITE32(2);
2101	WRITE32(open->op_bmval[0]);
2102	WRITE32(open->op_bmval[1]);
2103	WRITE32(open->op_delegate_type);
2104	ADJUST_ARGS();
2105
2106	switch (open->op_delegate_type) {
2107	case NFS4_OPEN_DELEGATE_NONE:
2108		break;
2109	case NFS4_OPEN_DELEGATE_READ:
2110		RESERVE_SPACE(20 + sizeof(stateid_t));
2111		WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
2112		WRITE32(open->op_recall);
2113
2114		/*
2115		 * TODO: ACE's in delegations
2116		 */
2117		WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2118		WRITE32(0);
2119		WRITE32(0);
2120		WRITE32(0);
2121		ADJUST_ARGS();
2122		break;
2123	case NFS4_OPEN_DELEGATE_WRITE:
2124		RESERVE_SPACE(32 + sizeof(stateid_t));
2125		WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
2126		WRITE32(0);
2127
2128		/*
2129		 * TODO: space_limit's in delegations
2130		 */
2131		WRITE32(NFS4_LIMIT_SIZE);
2132		WRITE32(~(u32)0);
2133		WRITE32(~(u32)0);
2134
2135		/*
2136		 * TODO: ACE's in delegations
2137		 */
2138		WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2139		WRITE32(0);
2140		WRITE32(0);
2141		WRITE32(0);
2142		ADJUST_ARGS();
2143		break;
2144	default:
2145		BUG();
2146	}
2147out:
2148	ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2149}
2150
2151static void
2152nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
2153{
2154	ENCODE_SEQID_OP_HEAD;
2155
2156	if (!nfserr) {
2157		RESERVE_SPACE(sizeof(stateid_t));
2158		WRITE32(oc->oc_resp_stateid.si_generation);
2159		WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2160		ADJUST_ARGS();
2161	}
2162
2163	ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2164}
2165
2166static void
2167nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
2168{
2169	ENCODE_SEQID_OP_HEAD;
2170
2171	if (!nfserr) {
2172		RESERVE_SPACE(sizeof(stateid_t));
2173		WRITE32(od->od_stateid.si_generation);
2174		WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
2175		ADJUST_ARGS();
2176	}
2177
2178	ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2179}
2180
2181static __be32
2182nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
2183		  struct nfsd4_read *read)
2184{
2185	u32 eof;
2186	int v, pn;
2187	unsigned long maxcount;
2188	long len;
2189	ENCODE_HEAD;
2190
2191	if (nfserr)
2192		return nfserr;
2193	if (resp->xbuf->page_len)
2194		return nfserr_resource;
2195
2196	RESERVE_SPACE(8); /* eof flag and byte count */
2197
2198	maxcount = svc_max_payload(resp->rqstp);
2199	if (maxcount > read->rd_length)
2200		maxcount = read->rd_length;
2201
2202	len = maxcount;
2203	v = 0;
2204	while (len > 0) {
2205		pn = resp->rqstp->rq_resused++;
2206		resp->rqstp->rq_vec[v].iov_base =
2207			page_address(resp->rqstp->rq_respages[pn]);
2208		resp->rqstp->rq_vec[v].iov_len =
2209			len < PAGE_SIZE ? len : PAGE_SIZE;
2210		v++;
2211		len -= PAGE_SIZE;
2212	}
2213	read->rd_vlen = v;
2214
2215	nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp,
2216			read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen,
2217			&maxcount);
2218
2219	if (nfserr == nfserr_symlink)
2220		nfserr = nfserr_inval;
2221	if (nfserr)
2222		return nfserr;
2223	eof = (read->rd_offset + maxcount >=
2224	       read->rd_fhp->fh_dentry->d_inode->i_size);
2225
2226	WRITE32(eof);
2227	WRITE32(maxcount);
2228	ADJUST_ARGS();
2229	resp->xbuf->head[0].iov_len = (char*)p
2230					- (char*)resp->xbuf->head[0].iov_base;
2231	resp->xbuf->page_len = maxcount;
2232
2233	/* Use rest of head for padding and remaining ops: */
2234	resp->xbuf->tail[0].iov_base = p;
2235	resp->xbuf->tail[0].iov_len = 0;
2236	if (maxcount&3) {
2237		RESERVE_SPACE(4);
2238		WRITE32(0);
2239		resp->xbuf->tail[0].iov_base += maxcount&3;
2240		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2241		ADJUST_ARGS();
2242	}
2243	return 0;
2244}
2245
2246static __be32
2247nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
2248{
2249	int maxcount;
2250	char *page;
2251	ENCODE_HEAD;
2252
2253	if (nfserr)
2254		return nfserr;
2255	if (resp->xbuf->page_len)
2256		return nfserr_resource;
2257
2258	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2259
2260	maxcount = PAGE_SIZE;
2261	RESERVE_SPACE(4);
2262
2263	nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2264	if (nfserr == nfserr_isdir)
2265		return nfserr_inval;
2266	if (nfserr)
2267		return nfserr;
2268
2269	WRITE32(maxcount);
2270	ADJUST_ARGS();
2271	resp->xbuf->head[0].iov_len = (char*)p
2272				- (char*)resp->xbuf->head[0].iov_base;
2273	resp->xbuf->page_len = maxcount;
2274
2275	/* Use rest of head for padding and remaining ops: */
2276	resp->xbuf->tail[0].iov_base = p;
2277	resp->xbuf->tail[0].iov_len = 0;
2278	if (maxcount&3) {
2279		RESERVE_SPACE(4);
2280		WRITE32(0);
2281		resp->xbuf->tail[0].iov_base += maxcount&3;
2282		resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2283		ADJUST_ARGS();
2284	}
2285	return 0;
2286}
2287
2288static __be32
2289nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
2290{
2291	int maxcount;
2292	loff_t offset;
2293	__be32 *page, *savep, *tailbase;
2294	ENCODE_HEAD;
2295
2296	if (nfserr)
2297		return nfserr;
2298	if (resp->xbuf->page_len)
2299		return nfserr_resource;
2300
2301	RESERVE_SPACE(8);  /* verifier */
2302	savep = p;
2303
2304	WRITE32(0);
2305	WRITE32(0);
2306	ADJUST_ARGS();
2307	resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2308	tailbase = p;
2309
2310	maxcount = PAGE_SIZE;
2311	if (maxcount > readdir->rd_maxcount)
2312		maxcount = readdir->rd_maxcount;
2313
2314	/*
2315	 * Convert from bytes to words, account for the two words already
2316	 * written, make sure to leave two words at the end for the next
2317	 * pointer and eof field.
2318	 */
2319	maxcount = (maxcount >> 2) - 4;
2320	if (maxcount < 0) {
2321		nfserr =  nfserr_toosmall;
2322		goto err_no_verf;
2323	}
2324
2325	page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]);
2326	readdir->common.err = 0;
2327	readdir->buflen = maxcount;
2328	readdir->buffer = page;
2329	readdir->offset = NULL;
2330
2331	offset = readdir->rd_cookie;
2332	nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2333			      &offset,
2334			      &readdir->common, nfsd4_encode_dirent);
2335	if (nfserr == nfs_ok &&
2336	    readdir->common.err == nfserr_toosmall &&
2337	    readdir->buffer == page)
2338		nfserr = nfserr_toosmall;
2339	if (nfserr == nfserr_symlink)
2340		nfserr = nfserr_notdir;
2341	if (nfserr)
2342		goto err_no_verf;
2343
2344	if (readdir->offset)
2345		xdr_encode_hyper(readdir->offset, offset);
2346
2347	p = readdir->buffer;
2348	*p++ = 0;	/* no more entries */
2349	*p++ = htonl(readdir->common.err == nfserr_eof);
2350	resp->xbuf->page_len = ((char*)p) - (char*)page_address(
2351		resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2352
2353	/* Use rest of head for padding and remaining ops: */
2354	resp->xbuf->tail[0].iov_base = tailbase;
2355	resp->xbuf->tail[0].iov_len = 0;
2356	resp->p = resp->xbuf->tail[0].iov_base;
2357	resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4;
2358
2359	return 0;
2360err_no_verf:
2361	p = savep;
2362	ADJUST_ARGS();
2363	return nfserr;
2364}
2365
2366static void
2367nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
2368{
2369	ENCODE_HEAD;
2370
2371	if (!nfserr) {
2372		RESERVE_SPACE(20);
2373		WRITECINFO(remove->rm_cinfo);
2374		ADJUST_ARGS();
2375	}
2376}
2377
2378static void
2379nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
2380{
2381	ENCODE_HEAD;
2382
2383	if (!nfserr) {
2384		RESERVE_SPACE(40);
2385		WRITECINFO(rename->rn_sinfo);
2386		WRITECINFO(rename->rn_tinfo);
2387		ADJUST_ARGS();
2388	}
2389}
2390
2391/*
2392 * The SETATTR encode routine is special -- it always encodes a bitmap,
2393 * regardless of the error status.
2394 */
2395static void
2396nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
2397{
2398	ENCODE_HEAD;
2399
2400	RESERVE_SPACE(12);
2401	if (nfserr) {
2402		WRITE32(2);
2403		WRITE32(0);
2404		WRITE32(0);
2405	}
2406	else {
2407		WRITE32(2);
2408		WRITE32(setattr->sa_bmval[0]);
2409		WRITE32(setattr->sa_bmval[1]);
2410	}
2411	ADJUST_ARGS();
2412}
2413
2414static void
2415nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
2416{
2417	ENCODE_HEAD;
2418
2419	if (!nfserr) {
2420		RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2421		WRITEMEM(&scd->se_clientid, 8);
2422		WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2423		ADJUST_ARGS();
2424	}
2425	else if (nfserr == nfserr_clid_inuse) {
2426		RESERVE_SPACE(8);
2427		WRITE32(0);
2428		WRITE32(0);
2429		ADJUST_ARGS();
2430	}
2431}
2432
2433static void
2434nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
2435{
2436	ENCODE_HEAD;
2437
2438	if (!nfserr) {
2439		RESERVE_SPACE(16);
2440		WRITE32(write->wr_bytes_written);
2441		WRITE32(write->wr_how_written);
2442		WRITEMEM(write->wr_verifier.data, 8);
2443		ADJUST_ARGS();
2444	}
2445}
2446
2447void
2448nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2449{
2450	__be32 *statp;
2451	ENCODE_HEAD;
2452
2453	RESERVE_SPACE(8);
2454	WRITE32(op->opnum);
2455	statp = p++;	/* to be backfilled at the end */
2456	ADJUST_ARGS();
2457
2458	switch (op->opnum) {
2459	case OP_ACCESS:
2460		nfsd4_encode_access(resp, op->status, &op->u.access);
2461		break;
2462	case OP_CLOSE:
2463		nfsd4_encode_close(resp, op->status, &op->u.close);
2464		break;
2465	case OP_COMMIT:
2466		nfsd4_encode_commit(resp, op->status, &op->u.commit);
2467		break;
2468	case OP_CREATE:
2469		nfsd4_encode_create(resp, op->status, &op->u.create);
2470		break;
2471	case OP_DELEGRETURN:
2472		break;
2473	case OP_GETATTR:
2474		op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
2475		break;
2476	case OP_GETFH:
2477		nfsd4_encode_getfh(resp, op->status, op->u.getfh);
2478		break;
2479	case OP_LINK:
2480		nfsd4_encode_link(resp, op->status, &op->u.link);
2481		break;
2482	case OP_LOCK:
2483		nfsd4_encode_lock(resp, op->status, &op->u.lock);
2484		break;
2485	case OP_LOCKT:
2486		nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
2487		break;
2488	case OP_LOCKU:
2489		nfsd4_encode_locku(resp, op->status, &op->u.locku);
2490		break;
2491	case OP_LOOKUP:
2492		break;
2493	case OP_LOOKUPP:
2494		break;
2495	case OP_NVERIFY:
2496		break;
2497	case OP_OPEN:
2498		nfsd4_encode_open(resp, op->status, &op->u.open);
2499		break;
2500	case OP_OPEN_CONFIRM:
2501		nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
2502		break;
2503	case OP_OPEN_DOWNGRADE:
2504		nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
2505		break;
2506	case OP_PUTFH:
2507		break;
2508	case OP_PUTROOTFH:
2509		break;
2510	case OP_READ:
2511		op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
2512		break;
2513	case OP_READDIR:
2514		op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
2515		break;
2516	case OP_READLINK:
2517		op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
2518		break;
2519	case OP_REMOVE:
2520		nfsd4_encode_remove(resp, op->status, &op->u.remove);
2521		break;
2522	case OP_RENAME:
2523		nfsd4_encode_rename(resp, op->status, &op->u.rename);
2524		break;
2525	case OP_RENEW:
2526		break;
2527	case OP_RESTOREFH:
2528		break;
2529	case OP_SAVEFH:
2530		break;
2531	case OP_SETATTR:
2532		nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2533		break;
2534	case OP_SETCLIENTID:
2535		nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
2536		break;
2537	case OP_SETCLIENTID_CONFIRM:
2538		break;
2539	case OP_VERIFY:
2540		break;
2541	case OP_WRITE:
2542		nfsd4_encode_write(resp, op->status, &op->u.write);
2543		break;
2544	case OP_RELEASE_LOCKOWNER:
2545		break;
2546	default:
2547		break;
2548	}
2549
2550	/*
2551	 * Note: We write the status directly, instead of using WRITE32(),
2552	 * since it is already in network byte order.
2553	 */
2554	*statp = op->status;
2555}
2556
2557/*
2558 * Encode the reply stored in the stateowner reply cache
2559 *
2560 * XDR note: do not encode rp->rp_buflen: the buffer contains the
2561 * previously sent already encoded operation.
2562 *
2563 * called with nfs4_lock_state() held
2564 */
2565void
2566nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2567{
2568	ENCODE_HEAD;
2569	struct nfs4_replay *rp = op->replay;
2570
2571	BUG_ON(!rp);
2572
2573	RESERVE_SPACE(8);
2574	WRITE32(op->opnum);
2575	*p++ = rp->rp_status;  /* already xdr'ed */
2576	ADJUST_ARGS();
2577
2578	RESERVE_SPACE(rp->rp_buflen);
2579	WRITEMEM(rp->rp_buf, rp->rp_buflen);
2580	ADJUST_ARGS();
2581}
2582
2583/*
2584 * END OF "GENERIC" ENCODE ROUTINES.
2585 */
2586
2587int
2588nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
2589{
2590        return xdr_ressize_check(rqstp, p);
2591}
2592
2593void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
2594{
2595	if (args->ops != args->iops) {
2596		kfree(args->ops);
2597		args->ops = args->iops;
2598	}
2599	kfree(args->tmpp);
2600	args->tmpp = NULL;
2601	while (args->to_free) {
2602		struct tmpbuf *tb = args->to_free;
2603		args->to_free = tb->next;
2604		tb->release(tb->buf);
2605		kfree(tb);
2606	}
2607}
2608
2609int
2610nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
2611{
2612	__be32 status;
2613
2614	args->p = p;
2615	args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
2616	args->pagelist = rqstp->rq_arg.pages;
2617	args->pagelen = rqstp->rq_arg.page_len;
2618	args->tmpp = NULL;
2619	args->to_free = NULL;
2620	args->ops = args->iops;
2621	args->rqstp = rqstp;
2622
2623	status = nfsd4_decode_compound(args);
2624	if (status) {
2625		nfsd4_release_compoundargs(args);
2626	}
2627	return !status;
2628}
2629
2630int
2631nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
2632{
2633	/*
2634	 * All that remains is to write the tag and operation count...
2635	 */
2636	struct kvec *iov;
2637	p = resp->tagp;
2638	*p++ = htonl(resp->taglen);
2639	memcpy(p, resp->tag, resp->taglen);
2640	p += XDR_QUADLEN(resp->taglen);
2641	*p++ = htonl(resp->opcnt);
2642
2643	if (rqstp->rq_res.page_len)
2644		iov = &rqstp->rq_res.tail[0];
2645	else
2646		iov = &rqstp->rq_res.head[0];
2647	iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
2648	BUG_ON(iov->iov_len > PAGE_SIZE);
2649	return 1;
2650}
2651
2652/*
2653 * Local variables:
2654 *  c-basic-offset: 8
2655 * End:
2656 */
2657