ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[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                 if (d_mountpoint(dentry)) {
1690                         if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, 
1691                                          &exp))) {      
1692                         /* 
1693                          * -EAGAIN is the only error returned from 
1694                          * nfsd_cross_mnt() and it indicates that an 
1695                          * up-call has  been initiated to fill in the export 
1696                          * options on exp.  When the answer comes back,
1697                          * this call will be retried.
1698                          */
1699                                 dput(dentry);
1700                                 nfserr = nfserr_dropit;
1701                                 goto error;
1702                         }
1703
1704                 }
1705
1706                 nfserr = nfsd4_encode_fattr(NULL, exp,
1707                                 dentry, p, &buflen, cd->rd_bmval,
1708                                 cd->rd_rqstp);
1709                 if (!nfserr) {
1710                         p += buflen;
1711                         goto out;
1712                 }
1713                 if (nfserr == nfserr_resource)
1714                         goto nospc;
1715
1716 error:
1717                 /*
1718                  * If we get here, we experienced a miscellaneous
1719                  * failure while writing the attributes.  If the
1720                  * client requested the RDATTR_ERROR attribute,
1721                  * we stuff the error code into this attribute
1722                  * and continue.  If this attribute was not requested,
1723                  * then in accordance with the spec, we fail the
1724                  * entire READDIR operation(!)
1725                  */
1726                 if (!(bmval0 & FATTR4_WORD0_RDATTR_ERROR)) {
1727                         cd->common.err = nfserr;
1728                         return -EINVAL;
1729                 }
1730
1731                 bmval0 = FATTR4_WORD0_RDATTR_ERROR;
1732                 bmval1 = 0;
1733                 /* falling through here will do the right thing... */
1734         }
1735
1736         /*
1737          * In the common "lightweight" case, we avoid
1738          * the overhead of nfsd4_encode_fattr() by assembling
1739          * a small fattr by hand.
1740          */
1741         if (buflen < 6)
1742                 goto nospc;
1743         *p++ = htonl(2);
1744         *p++ = htonl(bmval0);
1745         *p++ = htonl(bmval1);
1746
1747         attrlenp = p++;
1748         if (bmval0 & FATTR4_WORD0_RDATTR_ERROR)
1749                 *p++ = nfserr;       /* no htonl */
1750         if (bmval0 & FATTR4_WORD0_FILEID)
1751                 p = xdr_encode_hyper(p, (u64)ino);
1752         *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1753
1754 out:
1755         cd->buflen -= (p - cd->buffer);
1756         cd->buffer = p;
1757         cd->common.err = nfs_ok;
1758         return 0;
1759
1760 nospc:
1761         cd->common.err = nfserr_toosmall;
1762         return -EINVAL;
1763 }
1764
1765 static void
1766 nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_access *access)
1767 {
1768         ENCODE_HEAD;
1769
1770         if (!nfserr) {
1771                 RESERVE_SPACE(8);
1772                 WRITE32(access->ac_supported);
1773                 WRITE32(access->ac_resp_access);
1774                 ADJUST_ARGS();
1775         }
1776 }
1777
1778 static void
1779 nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_close *close)
1780 {
1781         ENCODE_SEQID_OP_HEAD;
1782
1783         if (!nfserr) {
1784                 RESERVE_SPACE(sizeof(stateid_t));
1785                 WRITE32(close->cl_stateid.si_generation);
1786                 WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
1787                 ADJUST_ARGS();
1788         }
1789         ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
1790 }
1791
1792
1793 static void
1794 nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_commit *commit)
1795 {
1796         ENCODE_HEAD;
1797
1798         if (!nfserr) {
1799                 RESERVE_SPACE(8);
1800                 WRITEMEM(commit->co_verf.data, 8);
1801                 ADJUST_ARGS();
1802         }
1803 }
1804
1805 static void
1806 nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_create *create)
1807 {
1808         ENCODE_HEAD;
1809
1810         if (!nfserr) {
1811                 RESERVE_SPACE(32);
1812                 WRITECINFO(create->cr_cinfo);
1813                 WRITE32(2);
1814                 WRITE32(create->cr_bmval[0]);
1815                 WRITE32(create->cr_bmval[1]);
1816                 ADJUST_ARGS();
1817         }
1818 }
1819
1820 static int
1821 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_getattr *getattr)
1822 {
1823         struct svc_fh *fhp = getattr->ga_fhp;
1824         int buflen;
1825
1826         if (nfserr)
1827                 return nfserr;
1828
1829         buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
1830         nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
1831                                     resp->p, &buflen, getattr->ga_bmval,
1832                                     resp->rqstp);
1833
1834         if (!nfserr)
1835                 resp->p += buflen;
1836         return nfserr;
1837 }
1838
1839 static void
1840 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, int nfserr, struct svc_fh *fhp)
1841 {
1842         unsigned int len;
1843         ENCODE_HEAD;
1844
1845         if (!nfserr) {
1846                 len = fhp->fh_handle.fh_size;
1847                 RESERVE_SPACE(len + 4);
1848                 WRITE32(len);
1849                 WRITEMEM(&fhp->fh_handle.fh_base, len);
1850                 ADJUST_ARGS();
1851         }
1852 }
1853
1854 /*
1855 * Including all fields other than the name, a LOCK4denied structure requires
1856 *   8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
1857 */
1858 static void
1859 nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
1860 {
1861         ENCODE_HEAD;
1862
1863         RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop->so_owner.len));
1864         WRITE64(ld->ld_start);
1865         WRITE64(ld->ld_length);
1866         WRITE32(ld->ld_type);
1867         WRITEMEM(&ld->ld_sop->so_client->cl_clientid, 8);
1868         WRITE32(ld->ld_sop->so_owner.len);
1869         WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
1870         ADJUST_ARGS();
1871 }
1872
1873 static void
1874 nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
1875 {
1876
1877         ENCODE_SEQID_OP_HEAD;
1878
1879         if (!nfserr) {
1880                 RESERVE_SPACE(4 + sizeof(stateid_t));
1881                 WRITE32(lock->lk_resp_stateid.si_generation);
1882                 WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
1883                 ADJUST_ARGS();
1884         } else if (nfserr == nfserr_denied)
1885                 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
1886
1887         ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
1888 }
1889
1890 static void
1891 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt)
1892 {
1893         if (nfserr == nfserr_denied)
1894                 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
1895 }
1896
1897 static void
1898 nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
1899 {
1900         ENCODE_SEQID_OP_HEAD;
1901
1902         if (!nfserr) {
1903                 RESERVE_SPACE(sizeof(stateid_t));
1904                 WRITE32(locku->lu_stateid.si_generation);
1905                 WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
1906                 ADJUST_ARGS();
1907         }
1908                                         
1909         ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
1910 }
1911
1912
1913 static void
1914 nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
1915 {
1916         ENCODE_HEAD;
1917
1918         if (!nfserr) {
1919                 RESERVE_SPACE(20);
1920                 WRITECINFO(link->li_cinfo);
1921                 ADJUST_ARGS();
1922         }
1923 }
1924
1925
1926 static void
1927 nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open)
1928 {
1929         ENCODE_SEQID_OP_HEAD;
1930
1931         if (nfserr)
1932                 goto out;
1933
1934         RESERVE_SPACE(36 + sizeof(stateid_t));
1935         WRITE32(open->op_stateid.si_generation);
1936         WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
1937         WRITECINFO(open->op_cinfo);
1938         WRITE32(open->op_rflags);
1939         WRITE32(2);
1940         WRITE32(open->op_bmval[0]);
1941         WRITE32(open->op_bmval[1]);
1942         WRITE32(open->op_delegate_type);
1943         ADJUST_ARGS();
1944
1945         switch (open->op_delegate_type) {
1946         case NFS4_OPEN_DELEGATE_NONE:
1947                 break;
1948         case NFS4_OPEN_DELEGATE_READ:
1949                 RESERVE_SPACE(20 + sizeof(delegation_stateid_t));
1950                 WRITEMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t));
1951                 WRITE32(0);
1952
1953                 /*
1954                  * TODO: ACE's in delegations
1955                  */
1956                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
1957                 WRITE32(0);
1958                 WRITE32(0);
1959                 WRITE32(0);   /* XXX: is NULL principal ok? */
1960                 ADJUST_ARGS();
1961                 break;
1962         case NFS4_OPEN_DELEGATE_WRITE:
1963                 RESERVE_SPACE(32 + sizeof(delegation_stateid_t));
1964                 WRITEMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t));
1965                 WRITE32(0);
1966
1967                 /*
1968                  * TODO: space_limit's in delegations
1969                  */
1970                 WRITE32(NFS4_LIMIT_SIZE);
1971                 WRITE32(~(u32)0);
1972                 WRITE32(~(u32)0);
1973
1974                 /*
1975                  * TODO: ACE's in delegations
1976                  */
1977                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
1978                 WRITE32(0);
1979                 WRITE32(0);
1980                 WRITE32(0);   /* XXX: is NULL principal ok? */
1981                 ADJUST_ARGS();
1982                 break;
1983         default:
1984                 BUG();
1985         }
1986         /* XXX save filehandle here */
1987 out:
1988         ENCODE_SEQID_OP_TAIL(open->op_stateowner);
1989 }
1990
1991 static void
1992 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
1993 {
1994         ENCODE_SEQID_OP_HEAD;
1995                                         
1996         if (!nfserr) {
1997                 RESERVE_SPACE(sizeof(stateid_t));
1998                 WRITE32(oc->oc_resp_stateid.si_generation);
1999                 WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2000                 ADJUST_ARGS();
2001         }
2002
2003         ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2004 }
2005
2006 static void
2007 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
2008 {
2009         ENCODE_SEQID_OP_HEAD;
2010                                         
2011         if (!nfserr) {
2012                 RESERVE_SPACE(sizeof(stateid_t));
2013                 WRITE32(od->od_stateid.si_generation);
2014                 WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
2015                 ADJUST_ARGS();
2016         }
2017
2018         ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2019 }
2020
2021 static int
2022 nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read)
2023 {
2024         u32 eof;
2025         int v, pn;
2026         unsigned long maxcount; 
2027         long len;
2028         ENCODE_HEAD;
2029
2030         if (nfserr)
2031                 return nfserr;
2032         if (resp->xbuf->page_len)
2033                 return nfserr_resource;
2034
2035         RESERVE_SPACE(8); /* eof flag and byte count */
2036
2037         maxcount = NFSSVC_MAXBLKSIZE;
2038         if (maxcount > read->rd_length)
2039                 maxcount = read->rd_length;
2040
2041         len = maxcount;
2042         v = 0;
2043         while (len > 0) {
2044                 pn = resp->rqstp->rq_resused;
2045                 svc_take_page(resp->rqstp);
2046                 read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]);
2047                 read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE;
2048                 v++;
2049                 len -= PAGE_SIZE;
2050         }
2051         read->rd_vlen = v;
2052
2053         nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp,
2054                            read->rd_offset,
2055                            read->rd_iov, read->rd_vlen,
2056                            &maxcount);
2057         if (nfserr == nfserr_symlink)
2058                 nfserr = nfserr_inval;
2059         if (nfserr)
2060                 return nfserr;
2061         eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size);
2062
2063         WRITE32(eof);
2064         WRITE32(maxcount);
2065         ADJUST_ARGS();
2066         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2067
2068         resp->xbuf->page_len = maxcount;
2069
2070         /* read zero bytes -> don't set up tail */
2071         if(!maxcount)
2072                 return 0;        
2073
2074         /* set up page for remaining responses */
2075         svc_take_page(resp->rqstp);
2076         resp->xbuf->tail[0].iov_base = 
2077                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2078         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2079         resp->xbuf->tail[0].iov_len = 0;
2080         resp->p = resp->xbuf->tail[0].iov_base;
2081         resp->end = resp->p + PAGE_SIZE/4;
2082
2083         if (maxcount&3) {
2084                 *(resp->p)++ = 0;
2085                 resp->xbuf->tail[0].iov_base += maxcount&3;
2086                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2087         }
2088         return 0;
2089 }
2090
2091 static int
2092 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink)
2093 {
2094         int maxcount;
2095         char *page;
2096         ENCODE_HEAD;
2097
2098         if (nfserr)
2099                 return nfserr;
2100         if (resp->xbuf->page_len)
2101                 return nfserr_resource;
2102
2103         svc_take_page(resp->rqstp);
2104         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2105
2106         maxcount = PAGE_SIZE;
2107         RESERVE_SPACE(4);
2108
2109         /*
2110          * XXX: By default, the ->readlink() VFS op will truncate symlinks
2111          * if they would overflow the buffer.  Is this kosher in NFSv4?  If
2112          * not, one easy fix is: if ->readlink() precisely fills the buffer,
2113          * assume that truncation occurred, and return NFS4ERR_RESOURCE.
2114          */
2115         nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2116         if (nfserr == nfserr_isdir)
2117                 return nfserr_inval;
2118         if (nfserr)
2119                 return nfserr;
2120
2121         WRITE32(maxcount);
2122         ADJUST_ARGS();
2123         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2124
2125         svc_take_page(resp->rqstp);
2126         resp->xbuf->tail[0].iov_base = 
2127                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2128         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2129         resp->xbuf->tail[0].iov_len = 0;
2130         resp->p = resp->xbuf->tail[0].iov_base;
2131         resp->end = resp->p + PAGE_SIZE/4;
2132
2133         resp->xbuf->page_len = maxcount;
2134         if (maxcount&3) {
2135                 *(resp->p)++ = 0;
2136                 resp->xbuf->tail[0].iov_base += maxcount&3;
2137                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2138         }
2139         return 0;
2140 }
2141
2142 static int
2143 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir)
2144 {
2145         int maxcount;
2146         loff_t offset;
2147         u32 *page, *savep;
2148         ENCODE_HEAD;
2149
2150         if (nfserr)
2151                 return nfserr;
2152         if (resp->xbuf->page_len)
2153                 return nfserr_resource;
2154
2155         RESERVE_SPACE(8);  /* verifier */
2156         savep = p;
2157
2158         /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
2159         WRITE32(0);
2160         WRITE32(0);
2161         ADJUST_ARGS();
2162         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2163
2164         maxcount = PAGE_SIZE;
2165         if (maxcount > readdir->rd_maxcount)
2166                 maxcount = readdir->rd_maxcount;
2167
2168         /*
2169          * Convert from bytes to words, account for the two words already
2170          * written, make sure to leave two words at the end for the next
2171          * pointer and eof field.
2172          */
2173         maxcount = (maxcount >> 2) - 4;
2174         if (maxcount < 0) {
2175                 nfserr =  nfserr_toosmall;
2176                 goto err_no_verf;
2177         }
2178
2179         svc_take_page(resp->rqstp);
2180         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2181         readdir->common.err = 0;
2182         readdir->buflen = maxcount;
2183         readdir->buffer = page;
2184         readdir->offset = NULL;
2185
2186         offset = readdir->rd_cookie;
2187         nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2188                               &offset,
2189                               &readdir->common, nfsd4_encode_dirent);
2190         if (nfserr == nfs_ok &&
2191             readdir->common.err == nfserr_toosmall &&
2192             readdir->buffer == page) 
2193                 nfserr = nfserr_toosmall;
2194         if (nfserr == nfserr_symlink)
2195                 nfserr = nfserr_notdir;
2196         if (nfserr)
2197                 goto err_no_verf;
2198
2199         if (readdir->offset)
2200                 xdr_encode_hyper(readdir->offset, offset);
2201
2202         p = readdir->buffer;
2203         *p++ = 0;       /* no more entries */
2204         *p++ = htonl(readdir->common.err == nfserr_eof);
2205         resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2206
2207         /* allocate a page for the tail */
2208         svc_take_page(resp->rqstp);
2209         resp->xbuf->tail[0].iov_base = 
2210                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2211         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2212         resp->xbuf->tail[0].iov_len = 0;
2213         resp->p = resp->xbuf->tail[0].iov_base;
2214         resp->end = resp->p + PAGE_SIZE/4;
2215
2216         return 0;
2217 err_no_verf:
2218         p = savep;
2219         ADJUST_ARGS();
2220         return nfserr;
2221 }
2222
2223 static void
2224 nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove)
2225 {
2226         ENCODE_HEAD;
2227
2228         if (!nfserr) {
2229                 RESERVE_SPACE(20);
2230                 WRITECINFO(remove->rm_cinfo);
2231                 ADJUST_ARGS();
2232         }
2233 }
2234
2235 static void
2236 nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename)
2237 {
2238         ENCODE_HEAD;
2239
2240         if (!nfserr) {
2241                 RESERVE_SPACE(40);
2242                 WRITECINFO(rename->rn_sinfo);
2243                 WRITECINFO(rename->rn_tinfo);
2244                 ADJUST_ARGS();
2245         }
2246 }
2247
2248 /*
2249  * The SETATTR encode routine is special -- it always encodes a bitmap,
2250  * regardless of the error status.
2251  */
2252 static void
2253 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr)
2254 {
2255         ENCODE_HEAD;
2256
2257         RESERVE_SPACE(12);
2258         if (nfserr) {
2259                 WRITE32(2);
2260                 WRITE32(0);
2261                 WRITE32(0);
2262         }
2263         else {
2264                 WRITE32(2);
2265                 WRITE32(setattr->sa_bmval[0]);
2266                 WRITE32(setattr->sa_bmval[1]);
2267         }
2268         ADJUST_ARGS();
2269 }
2270
2271 static void
2272 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd)
2273 {
2274         ENCODE_HEAD;
2275
2276         if (!nfserr) {
2277                 RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2278                 WRITEMEM(&scd->se_clientid, 8);
2279                 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2280                 ADJUST_ARGS();
2281         }
2282         else if (nfserr == nfserr_clid_inuse) {
2283                 RESERVE_SPACE(8);
2284                 WRITE32(0);
2285                 WRITE32(0);
2286                 ADJUST_ARGS();
2287         }
2288 }
2289
2290 static void
2291 nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write)
2292 {
2293         ENCODE_HEAD;
2294
2295         if (!nfserr) {
2296                 RESERVE_SPACE(16);
2297                 WRITE32(write->wr_bytes_written);
2298                 WRITE32(write->wr_how_written);
2299                 WRITEMEM(write->wr_verifier.data, 8);
2300                 ADJUST_ARGS();
2301         }
2302 }
2303
2304 void
2305 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2306 {
2307         u32 *statp;
2308         ENCODE_HEAD;
2309
2310         RESERVE_SPACE(8);
2311         WRITE32(op->opnum);
2312         statp = p++;    /* to be backfilled at the end */
2313         ADJUST_ARGS();
2314
2315         switch (op->opnum) {
2316         case OP_ACCESS:
2317                 nfsd4_encode_access(resp, op->status, &op->u.access);
2318                 break;
2319         case OP_CLOSE:
2320                 nfsd4_encode_close(resp, op->status, &op->u.close);
2321                 break;
2322         case OP_COMMIT:
2323                 nfsd4_encode_commit(resp, op->status, &op->u.commit);
2324                 break;
2325         case OP_CREATE:
2326                 nfsd4_encode_create(resp, op->status, &op->u.create);
2327                 break;
2328         case OP_GETATTR:
2329                 op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
2330                 break;
2331         case OP_GETFH:
2332                 nfsd4_encode_getfh(resp, op->status, op->u.getfh);
2333                 break;
2334         case OP_LINK:
2335                 nfsd4_encode_link(resp, op->status, &op->u.link);
2336                 break;
2337         case OP_LOCK:
2338                 nfsd4_encode_lock(resp, op->status, &op->u.lock);
2339                 break;
2340         case OP_LOCKT:
2341                 nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
2342                 break;
2343         case OP_LOCKU:
2344                 nfsd4_encode_locku(resp, op->status, &op->u.locku);
2345                 break;
2346         case OP_LOOKUP:
2347                 break;
2348         case OP_LOOKUPP:
2349                 break;
2350         case OP_NVERIFY:
2351                 break;
2352         case OP_OPEN:
2353                 nfsd4_encode_open(resp, op->status, &op->u.open);
2354                 break;
2355         case OP_OPEN_CONFIRM:
2356                 nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
2357                 break;
2358         case OP_OPEN_DOWNGRADE:
2359                 nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
2360                 break;
2361         case OP_PUTFH:
2362                 break;
2363         case OP_PUTROOTFH:
2364                 break;
2365         case OP_READ:
2366                 op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
2367                 break;
2368         case OP_READDIR:
2369                 op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
2370                 break;
2371         case OP_READLINK:
2372                 op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
2373                 break;
2374         case OP_REMOVE:
2375                 nfsd4_encode_remove(resp, op->status, &op->u.remove);
2376                 break;
2377         case OP_RENAME:
2378                 nfsd4_encode_rename(resp, op->status, &op->u.rename);
2379                 break;
2380         case OP_RENEW:
2381                 break;
2382         case OP_RESTOREFH:
2383                 break;
2384         case OP_SAVEFH:
2385                 break;
2386         case OP_SETATTR:
2387                 nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2388                 break;
2389         case OP_SETCLIENTID:
2390                 nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
2391                 break;
2392         case OP_SETCLIENTID_CONFIRM:
2393                 break;
2394         case OP_VERIFY:
2395                 break;
2396         case OP_WRITE:
2397                 nfsd4_encode_write(resp, op->status, &op->u.write);
2398                 break;
2399         case OP_RELEASE_LOCKOWNER:
2400                 break;
2401         default:
2402                 break;
2403         }
2404
2405         /*
2406          * Note: We write the status directly, instead of using WRITE32(),
2407          * since it is already in network byte order.
2408          */
2409         *statp = op->status;
2410 }
2411
2412 /* 
2413  * Encode the reply stored in the stateowner reply cache 
2414  * 
2415  * XDR note: do not encode rp->rp_buflen: the buffer contains the
2416  * previously sent already encoded operation.
2417  *
2418  * called with nfs4_lock_state() held
2419  */
2420 void
2421 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2422 {
2423         ENCODE_HEAD;
2424         struct nfs4_replay *rp = op->replay;
2425
2426         BUG_ON(!rp);
2427
2428         RESERVE_SPACE(8);
2429         WRITE32(op->opnum);
2430         *p++ = rp->rp_status;  /* already xdr'ed */
2431         ADJUST_ARGS();
2432
2433         RESERVE_SPACE(rp->rp_buflen);
2434         WRITEMEM(rp->rp_buf, rp->rp_buflen);
2435         ADJUST_ARGS();
2436         nfs4_unlock_state();
2437 }
2438
2439 /*
2440  * END OF "GENERIC" ENCODE ROUTINES.
2441  */
2442
2443 int
2444 nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
2445 {
2446         return xdr_ressize_check(rqstp, p);
2447 }
2448
2449 int
2450 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args)
2451 {
2452         int status;
2453
2454         args->p = p;
2455         args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
2456         args->pagelist = rqstp->rq_arg.pages;
2457         args->pagelen = rqstp->rq_arg.page_len;
2458         args->tmpp = NULL;
2459         args->to_free = NULL;
2460         args->ops = args->iops;
2461         args->rqstp = rqstp;
2462
2463         status = nfsd4_decode_compound(args);
2464         if (status) {
2465                 if (args->ops != args->iops) {
2466                         kfree(args->ops);
2467                         args->ops = args->iops;
2468                 }
2469                 if (args->tmpp) {
2470                         kfree(args->tmpp);
2471                         args->tmpp = NULL;
2472                 }
2473                 while (args->to_free) {
2474                         struct tmpbuf *tb = args->to_free;
2475                         args->to_free = tb->next;
2476                         kfree(tb->buf);
2477                         kfree(tb);
2478                 }
2479         }
2480         return !status;
2481 }
2482
2483 int
2484 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp)
2485 {
2486         /*
2487          * All that remains is to write the tag and operation count...
2488          */
2489         struct iovec *iov;
2490         p = resp->tagp;
2491         *p++ = htonl(resp->taglen);
2492         memcpy(p, resp->tag, resp->taglen);
2493         p += XDR_QUADLEN(resp->taglen);
2494         *p++ = htonl(resp->opcnt);
2495
2496         if (rqstp->rq_res.page_len) 
2497                 iov = &rqstp->rq_res.tail[0];
2498         else
2499                 iov = &rqstp->rq_res.head[0];
2500         iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
2501         BUG_ON(iov->iov_len > PAGE_SIZE);
2502         return 1;
2503 }
2504
2505 /*
2506  * Local variables:
2507  *  c-basic-offset: 8
2508  * End:
2509  */