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