patch-2_6_7-vs1_9_1_12
[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 #include <linux/vserver/xid.h>
59
60 #define NFSDDBG_FACILITY                NFSDDBG_XDR
61
62 static const char utf8_byte_len[256] = {
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         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,
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,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,
69         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,
70         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
71 };
72
73 static inline int
74 is_legal_utf8_sequence(unsigned char *source, int length)
75 {
76         unsigned char *ptr;
77         unsigned char c;
78
79         if (length==1) return 1;
80
81         /* Check for overlong sequence, and check second byte */
82         c = *(source + 1);
83         switch (*source) {
84         case 0xE0: /* 3 bytes */
85                 if ( c < 0xA0 ) return 0;
86                 break;
87         case 0xF0: /* 4 bytes */
88                 if ( c < 0x90 ) return 0;
89                 break;
90         case 0xF8: /* 5 bytes */
91                 if ( c < 0xC8 ) return 0;
92                 break;
93         case 0xFC: /* 6 bytes */
94                 if ( c < 0x84 ) return 0;
95                 break;
96         default:
97                 if ( (c & 0xC0) != 0x80) return 0;
98         }
99
100         /* Check that trailing bytes look like 10xxxxxx */
101         for (ptr = source++ + length - 1; ptr>source; ptr--)
102                 if ( ((*ptr) & 0xC0) != 0x80 ) return 0;
103         return 1;
104 }
105
106 /* This does some screening on disallowed unicode characters.  It is NOT
107  * comprehensive.
108  */
109 static int
110 is_allowed_utf8_char(unsigned char *source, int length)
111 {
112         /* We assume length and source point to a valid utf8 sequence */
113         unsigned char c;
114
115         /* Disallow F0000 and up (in utf8, F3B08080) */
116         if (*source > 0xF3 ) return 0;
117         c = *(source + 1);
118         switch (*source) {
119         case 0xF3:
120                 if (c >= 0xB0) return 0;
121                 break;
122         /* Disallow D800-F8FF (in utf8, EDA080-EFA3BF */
123         case 0xED:
124                 if (c >= 0xA0) return 0;
125                 break;
126         case 0xEE:
127                 return 0;
128                 break;
129         case 0xEF:
130                 if (c <= 0xA3) return 0;
131         /* Disallow FFF9-FFFF (EFBFB9-EFBFBF) */
132                 if (c==0xBF)
133                         /* Don't need to check <=0xBF, since valid utf8 */
134                         if ( *(source+2) >= 0xB9) return 0;
135                 break;
136         }
137         return 1;
138 }
139
140 /* This routine should really check to see that the proper stringprep
141  * mappings have been applied.  Instead, we do a simple screen of some
142  * of the more obvious illegal values by calling is_allowed_utf8_char.
143  * This will allow many illegal strings through, but if a client behaves,
144  * it will get full functionality.  The other option (apart from full
145  * stringprep checking) is to limit everything to an easily handled subset,
146  * such as 7-bit ascii.
147  *
148  * Note - currently calling routines ignore return value except as boolean.
149  */
150 static int
151 check_utf8(char *str, int len)
152 {
153         unsigned char *chunk, *sourceend;
154         int chunklen;
155
156         chunk = str;
157         sourceend = str + len;
158
159         while (chunk < sourceend) {
160                 chunklen = utf8_byte_len[*chunk];
161                 if (!chunklen)
162                         return nfserr_inval;
163                 if (chunk + chunklen > sourceend)
164                         return nfserr_inval;
165                 if (!is_legal_utf8_sequence(chunk, chunklen))
166                         return nfserr_inval;
167                 if (!is_allowed_utf8_char(chunk, chunklen))
168                         return nfserr_inval;
169                 if ( (chunklen==1) && (!*chunk) )
170                         return nfserr_inval; /* Disallow embedded nulls */
171                 chunk += chunklen;
172         }
173
174         return 0;
175 }
176
177 static int
178 check_filename(char *str, int len, int err)
179 {
180         int i;
181
182         if (len == 0)
183                 return nfserr_inval;
184         if (isdotent(str, len))
185                 return err;
186         for (i = 0; i < len; i++)
187                 if (str[i] == '/')
188                         return err;
189         return check_utf8(str, len);
190 }
191
192 /*
193  * START OF "GENERIC" DECODE ROUTINES.
194  *   These may look a little ugly since they are imported from a "generic"
195  * set of XDR encode/decode routines which are intended to be shared by
196  * all of our NFSv4 implementations (OpenBSD, MacOS X...).
197  *
198  * If the pain of reading these is too great, it should be a straightforward
199  * task to translate them into Linux-specific versions which are more
200  * consistent with the style used in NFSv2/v3...
201  */
202 #define DECODE_HEAD                             \
203         u32 *p;                                 \
204         int status
205 #define DECODE_TAIL                             \
206         status = 0;                             \
207 out:                                            \
208         return status;                          \
209 xdr_error:                                      \
210         printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
211         status = nfserr_bad_xdr;                \
212         goto out
213
214 #define READ32(x)         (x) = ntohl(*p++)
215 #define READ64(x)         do {                  \
216         (x) = (u64)ntohl(*p++) << 32;           \
217         (x) |= ntohl(*p++);                     \
218 } while (0)
219 #define READTIME(x)       do {                  \
220         p++;                                    \
221         (x) = ntohl(*p++);                      \
222         p++;                                    \
223 } while (0)
224 #define READMEM(x,nbytes) do {                  \
225         x = (char *)p;                          \
226         p += XDR_QUADLEN(nbytes);               \
227 } while (0)
228 #define SAVEMEM(x,nbytes) do {                  \
229         if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
230                 savemem(argp, p, nbytes) :      \
231                 (char *)p)) {                   \
232                 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
233                 goto xdr_error;                 \
234                 }                               \
235         p += XDR_QUADLEN(nbytes);               \
236 } while (0)
237 #define COPYMEM(x,nbytes) do {                  \
238         memcpy((x), p, nbytes);                 \
239         p += XDR_QUADLEN(nbytes);               \
240 } while (0)
241
242 /* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
243 #define READ_BUF(nbytes)  do {                  \
244         if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) {     \
245                 p = argp->p;                    \
246                 argp->p += XDR_QUADLEN(nbytes); \
247         } else if (!(p = read_buf(argp, nbytes))) { \
248                 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \
249                 goto xdr_error;                 \
250         }                                       \
251 } while (0)
252
253 u32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes)
254 {
255         /* We want more bytes than seem to be available.
256          * Maybe we need a new page, maybe we have just run out
257          */
258         int avail = (char*)argp->end - (char*)argp->p;
259         u32 *p;
260         if (avail + argp->pagelen < nbytes)
261                 return NULL;
262         if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
263                 return NULL;
264         /* ok, we can do it with the current plus the next page */
265         if (nbytes <= sizeof(argp->tmp))
266                 p = argp->tmp;
267         else {
268                 if (argp->tmpp)
269                         kfree(argp->tmpp);
270                 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
271                 if (!p)
272                         return NULL;
273                 
274         }
275         memcpy(p, argp->p, avail);
276         /* step to next page */
277         argp->p = page_address(argp->pagelist[0]);
278         argp->pagelist++;
279         if (argp->pagelen < PAGE_SIZE) {
280                 argp->end = p + (argp->pagelen>>2);
281                 argp->pagelen = 0;
282         } else {
283                 argp->end = p + (PAGE_SIZE>>2);
284                 argp->pagelen -= PAGE_SIZE;
285         }
286         memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
287         argp->p += XDR_QUADLEN(nbytes - avail);
288         return p;
289 }
290
291 char *savemem(struct nfsd4_compoundargs *argp, u32 *p, int nbytes)
292 {
293         struct tmpbuf *tb;
294         if (p == argp->tmp) {
295                 p = kmalloc(nbytes, GFP_KERNEL);
296                 if (!p) return NULL;
297                 memcpy(p, argp->tmp, nbytes);
298         } else {
299                 if (p != argp->tmpp)
300                         BUG();
301                 argp->tmpp = NULL;
302         }
303         tb = kmalloc(sizeof(*tb), GFP_KERNEL);
304         if (!tb) {
305                 kfree(p);
306                 return NULL;
307         }
308         tb->buf = p;
309         tb->next = argp->to_free;
310         argp->to_free = tb;
311         return (char*)p;
312 }
313
314
315 static int
316 nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
317 {
318         u32 bmlen;
319         DECODE_HEAD;
320
321         bmval[0] = 0;
322         bmval[1] = 0;
323
324         READ_BUF(4);
325         READ32(bmlen);
326         if (bmlen > 1000)
327                 goto xdr_error;
328
329         READ_BUF(bmlen << 2);
330         if (bmlen > 0)
331                 READ32(bmval[0]);
332         if (bmlen > 1)
333                 READ32(bmval[1]);
334
335         DECODE_TAIL;
336 }
337
338 static int
339 nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr)
340 {
341         int expected_len, len = 0;
342         u32 dummy32;
343         char *buf;
344
345         DECODE_HEAD;
346         iattr->ia_valid = 0;
347         if ((status = nfsd4_decode_bitmap(argp, bmval)))
348                 return status;
349
350         /*
351          * According to spec, unsupported attributes return ERR_NOTSUPP;
352          * read-only attributes return ERR_INVAL.
353          */
354         if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1))
355                 return nfserr_attrnotsupp;
356         if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1))
357                 return nfserr_inval;
358
359         READ_BUF(4);
360         READ32(expected_len);
361
362         if (bmval[0] & FATTR4_WORD0_SIZE) {
363                 READ_BUF(8);
364                 len += 8;
365                 READ64(iattr->ia_size);
366                 iattr->ia_valid |= ATTR_SIZE;
367         }
368         if (bmval[1] & FATTR4_WORD1_MODE) {
369                 READ_BUF(4);
370                 len += 4;
371                 READ32(iattr->ia_mode);
372                 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
373                 iattr->ia_valid |= ATTR_MODE;
374         }
375         if (bmval[1] & FATTR4_WORD1_OWNER) {
376                 READ_BUF(4);
377                 len += 4;
378                 READ32(dummy32);
379                 READ_BUF(dummy32);
380                 len += (XDR_QUADLEN(dummy32) << 2);
381                 READMEM(buf, dummy32);
382                 if (check_utf8(buf, dummy32))
383                         return nfserr_inval;
384                 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
385                         goto out_nfserr;
386                 iattr->ia_valid |= ATTR_UID;
387         }
388         if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
389                 READ_BUF(4);
390                 len += 4;
391                 READ32(dummy32);
392                 READ_BUF(dummy32);
393                 len += (XDR_QUADLEN(dummy32) << 2);
394                 READMEM(buf, dummy32);
395                 if (check_utf8(buf, dummy32))
396                         return nfserr_inval;
397                 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
398                         goto out_nfserr;
399                 iattr->ia_valid |= ATTR_GID;
400         }
401         if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
402                 READ_BUF(4);
403                 len += 4;
404                 READ32(dummy32);
405                 switch (dummy32) {
406                 case NFS4_SET_TO_CLIENT_TIME:
407                         /* We require the high 32 bits of 'seconds' to be 0, and we ignore
408                            all 32 bits of 'nseconds'. */
409                         READ_BUF(12);
410                         len += 12;
411                         READ32(dummy32);
412                         if (dummy32)
413                                 return nfserr_inval;
414                         READ32(iattr->ia_atime.tv_sec);
415                         READ32(iattr->ia_atime.tv_nsec);
416                         if (iattr->ia_atime.tv_nsec >= (u32)1000000000)
417                                 return nfserr_inval;
418                         iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
419                         break;
420                 case NFS4_SET_TO_SERVER_TIME:
421                         iattr->ia_valid |= ATTR_ATIME;
422                         break;
423                 default:
424                         goto xdr_error;
425                 }
426         }
427         if (bmval[1] & FATTR4_WORD1_TIME_METADATA) {
428                 /* We require the high 32 bits of 'seconds' to be 0, and we ignore
429                    all 32 bits of 'nseconds'. */
430                 READ_BUF(12);
431                 len += 12;
432                 READ32(dummy32);
433                 if (dummy32)
434                         return nfserr_inval;
435                 READ32(iattr->ia_ctime.tv_sec);
436                 READ32(iattr->ia_ctime.tv_nsec);
437                 if (iattr->ia_ctime.tv_nsec >= (u32)1000000000)
438                         return nfserr_inval;
439                 iattr->ia_valid |= ATTR_CTIME;
440         }
441         if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
442                 READ_BUF(4);
443                 len += 4;
444                 READ32(dummy32);
445                 switch (dummy32) {
446                 case NFS4_SET_TO_CLIENT_TIME:
447                         /* We require the high 32 bits of 'seconds' to be 0, and we ignore
448                            all 32 bits of 'nseconds'. */
449                         READ_BUF(12);
450                         len += 12;
451                         READ32(dummy32);
452                         if (dummy32)
453                                 return nfserr_inval;
454                         READ32(iattr->ia_mtime.tv_sec);
455                         READ32(iattr->ia_mtime.tv_nsec);
456                         if (iattr->ia_mtime.tv_nsec >= (u32)1000000000)
457                                 return nfserr_inval;
458                         iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
459                         break;
460                 case NFS4_SET_TO_SERVER_TIME:
461                         iattr->ia_valid |= ATTR_MTIME;
462                         break;
463                 default:
464                         goto xdr_error;
465                 }
466         }
467         if (len != expected_len)
468                 goto xdr_error;
469
470         DECODE_TAIL;
471
472 out_nfserr:
473         status = nfserrno(status);
474         goto out;
475 }
476
477 static int
478 nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
479 {
480         DECODE_HEAD;
481
482         READ_BUF(4);
483         READ32(access->ac_req_access);
484
485         DECODE_TAIL;
486 }
487
488 #define NFS4_STATE_NOT_LOCKED   ((void *)-1)
489
490 static int
491 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
492 {
493         DECODE_HEAD;
494
495         close->cl_stateowner = NFS4_STATE_NOT_LOCKED;
496         READ_BUF(4 + sizeof(stateid_t));
497         READ32(close->cl_seqid);
498         READ32(close->cl_stateid.si_generation);
499         COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
500
501         DECODE_TAIL;
502 }
503
504
505 static int
506 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
507 {
508         DECODE_HEAD;
509
510         READ_BUF(12);
511         READ64(commit->co_offset);
512         READ32(commit->co_count);
513
514         DECODE_TAIL;
515 }
516
517 static int
518 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
519 {
520         DECODE_HEAD;
521
522         READ_BUF(4);
523         READ32(create->cr_type);
524         switch (create->cr_type) {
525         case NF4LNK:
526                 READ_BUF(4);
527                 READ32(create->cr_linklen);
528                 READ_BUF(create->cr_linklen);
529                 SAVEMEM(create->cr_linkname, create->cr_linklen);
530                 if (check_utf8(create->cr_linkname, create->cr_linklen))
531                         return nfserr_inval;
532                 break;
533         case NF4BLK:
534         case NF4CHR:
535                 READ_BUF(8);
536                 READ32(create->cr_specdata1);
537                 READ32(create->cr_specdata2);
538                 break;
539         case NF4SOCK:
540         case NF4FIFO:
541         case NF4DIR:
542         default:
543                 break;
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 static inline int
1293 xdr_padding(int l)
1294 {
1295        return 3 - ((l - 1) & 3); /* smallest i>=0 such that (l+i)%4 = 0 */
1296 }
1297
1298 static int
1299 nfsd4_encode_name(struct svc_rqst *rqstp, int group, uid_t id,
1300                         u32 **p, int *buflen)
1301 {
1302         int status;
1303         u32 len;
1304
1305         if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1306                 return nfserr_resource;
1307         if (group)
1308                 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1309         else
1310                 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1311         if (status < 0)
1312                 return nfserrno(status);
1313         len = (unsigned)status;
1314         *(*p)++ = htonl(len);
1315         memset((u8 *)*p + len, 0, xdr_padding(len));
1316         *p += XDR_QUADLEN(len);
1317         *buflen -= (XDR_QUADLEN(len) << 2) + 4;
1318         BUG_ON(*buflen < 0);
1319         return 0;
1320 }
1321
1322 static inline int
1323 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
1324 {
1325         return nfsd4_encode_name(rqstp, uid, 0, p, buflen);
1326 }
1327
1328 static inline int
1329 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
1330 {
1331         return nfsd4_encode_name(rqstp, gid, 1, p, buflen);
1332 }
1333
1334
1335 /*
1336  * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
1337  * ourselves.
1338  *
1339  * @countp is the buffer size in _words_; upon successful return this becomes
1340  * replaced with the number of words written.
1341  */
1342 int
1343 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1344                 struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval,
1345                 struct svc_rqst *rqstp)
1346 {
1347         u32 bmval0 = bmval[0];
1348         u32 bmval1 = bmval[1];
1349         struct kstat stat;
1350         struct svc_fh tempfh;
1351         struct kstatfs statfs;
1352         int buflen = *countp << 2;
1353         u32 *attrlenp;
1354         u32 dummy;
1355         u64 dummy64;
1356         u32 *p = buffer;
1357         int status;
1358
1359         BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1360         BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
1361         BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
1362
1363         status = vfs_getattr(exp->ex_mnt, dentry, &stat);
1364         if (status)
1365                 goto out_nfserr;
1366         if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
1367             (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1368                        FATTR4_WORD1_SPACE_TOTAL))) {
1369                 status = vfs_statfs(dentry->d_inode->i_sb, &statfs);
1370                 if (status)
1371                         goto out_nfserr;
1372         }
1373         if ((bmval0 & FATTR4_WORD0_FILEHANDLE) && !fhp) {
1374                 fh_init(&tempfh, NFS4_FHSIZE);
1375                 status = fh_compose(&tempfh, exp, dentry, NULL);
1376                 if (status)
1377                         goto out;
1378                 fhp = &tempfh;
1379         }
1380         if ((buflen -= 16) < 0)
1381                 goto out_resource;
1382
1383         WRITE32(2);
1384         WRITE32(bmval0);
1385         WRITE32(bmval1);
1386         attrlenp = p++;                /* to be backfilled later */
1387
1388         if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1389                 if ((buflen -= 12) < 0)
1390                         goto out_resource;
1391                 WRITE32(2);
1392                 WRITE32(NFSD_SUPPORTED_ATTRS_WORD0);
1393                 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
1394         }
1395         if (bmval0 & FATTR4_WORD0_TYPE) {
1396                 if ((buflen -= 4) < 0)
1397                         goto out_resource;
1398                 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1399                 if (dummy == NF4BAD)
1400                         goto out_serverfault;
1401                 WRITE32(dummy);
1402         }
1403         if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1404                 if ((buflen -= 4) < 0)
1405                         goto out_resource;
1406                 WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
1407         }
1408         if (bmval0 & FATTR4_WORD0_CHANGE) {
1409                 /*
1410                  * Note: This _must_ be consistent with the scheme for writing
1411                  * change_info, so any changes made here must be reflected there
1412                  * as well.  (See xdr4.h:set_change_info() and the WRITECINFO()
1413                  * macro above.)
1414                  */
1415                 if ((buflen -= 8) < 0)
1416                         goto out_resource;
1417                 WRITE32(stat.ctime.tv_sec);
1418                 WRITE32(stat.ctime.tv_nsec);
1419         }
1420         if (bmval0 & FATTR4_WORD0_SIZE) {
1421                 if ((buflen -= 8) < 0)
1422                         goto out_resource;
1423                 WRITE64(stat.size);
1424         }
1425         if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1426                 if ((buflen -= 4) < 0)
1427                         goto out_resource;
1428                 WRITE32(1);
1429         }
1430         if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1431                 if ((buflen -= 4) < 0)
1432                         goto out_resource;
1433                 WRITE32(1);
1434         }
1435         if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1436                 if ((buflen -= 4) < 0)
1437                         goto out_resource;
1438                 WRITE32(0);
1439         }
1440         if (bmval0 & FATTR4_WORD0_FSID) {
1441                 if ((buflen -= 16) < 0)
1442                         goto out_resource;
1443                 WRITE32(0);
1444                 WRITE32(MAJOR(stat.dev));
1445                 WRITE32(0);
1446                 WRITE32(MINOR(stat.dev));
1447         }
1448         if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1449                 if ((buflen -= 4) < 0)
1450                         goto out_resource;
1451                 WRITE32(0);
1452         }
1453         if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1454                 if ((buflen -= 4) < 0)
1455                         goto out_resource;
1456                 WRITE32(NFSD_LEASE_TIME);
1457         }
1458         if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1459                 if ((buflen -= 4) < 0)
1460                         goto out_resource;
1461                 WRITE32(0);
1462         }
1463         if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1464                 if ((buflen -= 4) < 0)
1465                         goto out_resource;
1466                 WRITE32(0);
1467         }
1468         if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1469                 if ((buflen -= 4) < 0)
1470                         goto out_resource;
1471                 WRITE32(1);
1472         }
1473         if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1474                 if ((buflen -= 4) < 0)
1475                         goto out_resource;
1476                 WRITE32(1);
1477         }
1478         if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1479                 if ((buflen -= 4) < 0)
1480                         goto out_resource;
1481                 WRITE32(1);
1482         }
1483         if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1484                 if ((buflen -= 4) < 0)
1485                         goto out_resource;
1486                 WRITE32(1);
1487         }
1488         if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1489                 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1490                 if (buflen < 0)
1491                         goto out_resource;
1492                 WRITE32(fhp->fh_handle.fh_size);
1493                 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1494         }
1495         if (bmval0 & FATTR4_WORD0_FILEID) {
1496                 if ((buflen -= 8) < 0)
1497                         goto out_resource;
1498                 WRITE64((u64) stat.ino);
1499         }
1500         if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1501                 if ((buflen -= 8) < 0)
1502                         goto out_resource;
1503                 WRITE64((u64) statfs.f_ffree);
1504         }
1505         if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1506                 if ((buflen -= 8) < 0)
1507                         goto out_resource;
1508                 WRITE64((u64) statfs.f_ffree);
1509         }
1510         if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1511                 if ((buflen -= 8) < 0)
1512                         goto out_resource;
1513                 WRITE64((u64) statfs.f_files);
1514         }
1515         if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1516                 if ((buflen -= 4) < 0)
1517                         goto out_resource;
1518                 WRITE32(1);
1519         }
1520         if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
1521                 if ((buflen -= 8) < 0)
1522                         goto out_resource;
1523                 WRITE64(~(u64)0);
1524         }
1525         if (bmval0 & FATTR4_WORD0_MAXLINK) {
1526                 if ((buflen -= 4) < 0)
1527                         goto out_resource;
1528                 WRITE32(255);
1529         }
1530         if (bmval0 & FATTR4_WORD0_MAXNAME) {
1531                 if ((buflen -= 4) < 0)
1532                         goto out_resource;
1533                 WRITE32(~(u32) 0);
1534         }
1535         if (bmval0 & FATTR4_WORD0_MAXREAD) {
1536                 if ((buflen -= 8) < 0)
1537                         goto out_resource;
1538                 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1539         }
1540         if (bmval0 & FATTR4_WORD0_MAXWRITE) {
1541                 if ((buflen -= 8) < 0)
1542                         goto out_resource;
1543                 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1544         }
1545         if (bmval1 & FATTR4_WORD1_MODE) {
1546                 if ((buflen -= 4) < 0)
1547                         goto out_resource;
1548                 WRITE32(stat.mode & S_IALLUGO);
1549         }
1550         if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
1551                 if ((buflen -= 4) < 0)
1552                         goto out_resource;
1553                 WRITE32(1);
1554         }
1555         if (bmval1 & FATTR4_WORD1_NUMLINKS) {
1556                 if ((buflen -= 4) < 0)
1557                         goto out_resource;
1558                 WRITE32(stat.nlink);
1559         }
1560         if (bmval1 & FATTR4_WORD1_OWNER) {
1561                 status = nfsd4_encode_user(rqstp,
1562                         XIDINO_UID(stat.uid, stat.xid), &p, &buflen);
1563                 if (status == nfserr_resource)
1564                         goto out_resource;
1565                 if (status)
1566                         goto out;
1567         }
1568         if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
1569                 status = nfsd4_encode_group(rqstp,
1570                         XIDINO_GID(stat.gid, stat.xid), &p, &buflen);
1571                 if (status == nfserr_resource)
1572                         goto out_resource;
1573                 if (status)
1574                         goto out;
1575         }
1576         if (bmval1 & FATTR4_WORD1_RAWDEV) {
1577                 if ((buflen -= 8) < 0)
1578                         goto out_resource;
1579                 WRITE32((u32) MAJOR(stat.rdev));
1580                 WRITE32((u32) MINOR(stat.rdev));
1581         }
1582         if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
1583                 if ((buflen -= 8) < 0)
1584                         goto out_resource;
1585                 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
1586                 WRITE64(dummy64);
1587         }
1588         if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
1589                 if ((buflen -= 8) < 0)
1590                         goto out_resource;
1591                 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
1592                 WRITE64(dummy64);
1593         }
1594         if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
1595                 if ((buflen -= 8) < 0)
1596                         goto out_resource;
1597                 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
1598                 WRITE64(dummy64);
1599         }
1600         if (bmval1 & FATTR4_WORD1_SPACE_USED) {
1601                 if ((buflen -= 8) < 0)
1602                         goto out_resource;
1603                 dummy64 = (u64)stat.blocks << 9;
1604                 WRITE64(dummy64);
1605         }
1606         if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
1607                 if ((buflen -= 12) < 0)
1608                         goto out_resource;
1609                 WRITE32(0);
1610                 WRITE32(stat.atime.tv_sec);
1611                 WRITE32(stat.atime.tv_nsec);
1612         }
1613         if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
1614                 if ((buflen -= 12) < 0)
1615                         goto out_resource;
1616                 WRITE32(0);
1617                 WRITE32(1);
1618                 WRITE32(0);
1619         }
1620         if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
1621                 if ((buflen -= 12) < 0)
1622                         goto out_resource;
1623                 WRITE32(0);
1624                 WRITE32(stat.ctime.tv_sec);
1625                 WRITE32(stat.ctime.tv_nsec);
1626         }
1627         if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
1628                 if ((buflen -= 12) < 0)
1629                         goto out_resource;
1630                 WRITE32(0);
1631                 WRITE32(stat.mtime.tv_sec);
1632                 WRITE32(stat.mtime.tv_nsec);
1633         }
1634         if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
1635                 struct dentry *mnt_pnt, *mnt_root;
1636
1637                 if ((buflen -= 8) < 0)
1638                         goto out_resource;
1639                 mnt_root = exp->ex_mnt->mnt_root;
1640                 if (mnt_root->d_inode == dentry->d_inode) {
1641                         mnt_pnt = exp->ex_mnt->mnt_mountpoint;
1642                         WRITE64((u64) mnt_pnt->d_inode->i_ino);
1643                 } else
1644                         WRITE64((u64) stat.ino);
1645         }
1646         *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1647         *countp = p - buffer;
1648         status = nfs_ok;
1649
1650 out:
1651         if (fhp == &tempfh)
1652                 fh_put(&tempfh);
1653         return status;
1654 out_nfserr:
1655         status = nfserrno(status);
1656         goto out;
1657 out_resource:
1658         *countp = 0;
1659         status = nfserr_resource;
1660         goto out;
1661 out_serverfault:
1662         status = nfserr_serverfault;
1663         goto out;
1664 }
1665
1666 static int
1667 nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
1668                     loff_t offset, ino_t ino, unsigned int d_type)
1669 {
1670         struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
1671         int buflen;
1672         u32 *p = cd->buffer;
1673         u32 *attrlenp;
1674         struct dentry *dentry;
1675         struct svc_export *exp = cd->rd_fhp->fh_export;
1676         u32 bmval0, bmval1;
1677         int nfserr = 0;
1678
1679         /* In nfsv4, "." and ".." never make it onto the wire.. */
1680         if (name && isdotent(name, namlen)) {
1681                 cd->common.err = nfs_ok;
1682                 return 0;
1683         }
1684
1685         if (cd->offset)
1686                 xdr_encode_hyper(cd->offset, (u64) offset);
1687
1688         buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
1689         if (buflen < 0)
1690                 goto nospc;
1691
1692         *p++ = xdr_one;                             /* mark entry present */
1693         cd->offset = p;                             /* remember pointer */
1694         p = xdr_encode_hyper(p, NFS_OFFSET_MAX);    /* offset of next entry */
1695         p = xdr_encode_array(p, name, namlen);      /* name length & name */
1696
1697         /*
1698          * Now we come to the ugly part: writing the fattr for this entry.
1699          */
1700         bmval0 = cd->rd_bmval[0];
1701         bmval1 = cd->rd_bmval[1];
1702         if ((bmval0 & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_FILEID)) || bmval1)  {
1703                 /*
1704                  * "Heavyweight" case: we have no choice except to
1705                  * call nfsd4_encode_fattr(). 
1706                  */
1707                 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
1708                 if (IS_ERR(dentry)) {
1709                         nfserr = nfserrno(PTR_ERR(dentry));
1710                         goto error;
1711                 }
1712
1713                 exp_get(exp);
1714                 if (d_mountpoint(dentry)) {
1715                         if ((nfserr = nfsd_cross_mnt(cd->rd_rqstp, &dentry, 
1716                                          &exp))) {      
1717                         /* 
1718                          * -EAGAIN is the only error returned from 
1719                          * nfsd_cross_mnt() and it indicates that an 
1720                          * up-call has  been initiated to fill in the export 
1721                          * options on exp.  When the answer comes back,
1722                          * this call will be retried.
1723                          */
1724                                 dput(dentry);
1725                                 exp_put(exp);
1726                                 nfserr = nfserr_dropit;
1727                                 goto error;
1728                         }
1729
1730                 }
1731
1732                 nfserr = nfsd4_encode_fattr(NULL, exp,
1733                                 dentry, p, &buflen, cd->rd_bmval,
1734                                 cd->rd_rqstp);
1735                 dput(dentry);
1736                 exp_put(exp);
1737                 if (!nfserr) {
1738                         p += buflen;
1739                         goto out;
1740                 }
1741                 if (nfserr == nfserr_resource)
1742                         goto nospc;
1743
1744 error:
1745                 /*
1746                  * If we get here, we experienced a miscellaneous
1747                  * failure while writing the attributes.  If the
1748                  * client requested the RDATTR_ERROR attribute,
1749                  * we stuff the error code into this attribute
1750                  * and continue.  If this attribute was not requested,
1751                  * then in accordance with the spec, we fail the
1752                  * entire READDIR operation(!)
1753                  */
1754                 if (!(bmval0 & FATTR4_WORD0_RDATTR_ERROR)) {
1755                         cd->common.err = nfserr;
1756                         return -EINVAL;
1757                 }
1758
1759                 bmval0 = FATTR4_WORD0_RDATTR_ERROR;
1760                 bmval1 = 0;
1761                 /* falling through here will do the right thing... */
1762         }
1763
1764         /*
1765          * In the common "lightweight" case, we avoid
1766          * the overhead of nfsd4_encode_fattr() by assembling
1767          * a small fattr by hand.
1768          */
1769         if (buflen < 6)
1770                 goto nospc;
1771         *p++ = htonl(2);
1772         *p++ = htonl(bmval0);
1773         *p++ = htonl(bmval1);
1774
1775         attrlenp = p++;
1776         if (bmval0 & FATTR4_WORD0_RDATTR_ERROR)
1777                 *p++ = nfserr;       /* no htonl */
1778         if (bmval0 & FATTR4_WORD0_FILEID)
1779                 p = xdr_encode_hyper(p, (u64)ino);
1780         *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1781
1782 out:
1783         cd->buflen -= (p - cd->buffer);
1784         cd->buffer = p;
1785         cd->common.err = nfs_ok;
1786         return 0;
1787
1788 nospc:
1789         cd->common.err = nfserr_toosmall;
1790         return -EINVAL;
1791 }
1792
1793 static void
1794 nfsd4_encode_access(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_access *access)
1795 {
1796         ENCODE_HEAD;
1797
1798         if (!nfserr) {
1799                 RESERVE_SPACE(8);
1800                 WRITE32(access->ac_supported);
1801                 WRITE32(access->ac_resp_access);
1802                 ADJUST_ARGS();
1803         }
1804 }
1805
1806 static void
1807 nfsd4_encode_close(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_close *close)
1808 {
1809         ENCODE_SEQID_OP_HEAD;
1810
1811         if (!nfserr) {
1812                 RESERVE_SPACE(sizeof(stateid_t));
1813                 WRITE32(close->cl_stateid.si_generation);
1814                 WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
1815                 ADJUST_ARGS();
1816         }
1817         ENCODE_SEQID_OP_TAIL(close->cl_stateowner);
1818 }
1819
1820
1821 static void
1822 nfsd4_encode_commit(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_commit *commit)
1823 {
1824         ENCODE_HEAD;
1825
1826         if (!nfserr) {
1827                 RESERVE_SPACE(8);
1828                 WRITEMEM(commit->co_verf.data, 8);
1829                 ADJUST_ARGS();
1830         }
1831 }
1832
1833 static void
1834 nfsd4_encode_create(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_create *create)
1835 {
1836         ENCODE_HEAD;
1837
1838         if (!nfserr) {
1839                 RESERVE_SPACE(32);
1840                 WRITECINFO(create->cr_cinfo);
1841                 WRITE32(2);
1842                 WRITE32(create->cr_bmval[0]);
1843                 WRITE32(create->cr_bmval[1]);
1844                 ADJUST_ARGS();
1845         }
1846 }
1847
1848 static int
1849 nfsd4_encode_getattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_getattr *getattr)
1850 {
1851         struct svc_fh *fhp = getattr->ga_fhp;
1852         int buflen;
1853
1854         if (nfserr)
1855                 return nfserr;
1856
1857         buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2);
1858         nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry,
1859                                     resp->p, &buflen, getattr->ga_bmval,
1860                                     resp->rqstp);
1861
1862         if (!nfserr)
1863                 resp->p += buflen;
1864         return nfserr;
1865 }
1866
1867 static void
1868 nfsd4_encode_getfh(struct nfsd4_compoundres *resp, int nfserr, struct svc_fh *fhp)
1869 {
1870         unsigned int len;
1871         ENCODE_HEAD;
1872
1873         if (!nfserr) {
1874                 len = fhp->fh_handle.fh_size;
1875                 RESERVE_SPACE(len + 4);
1876                 WRITE32(len);
1877                 WRITEMEM(&fhp->fh_handle.fh_base, len);
1878                 ADJUST_ARGS();
1879         }
1880 }
1881
1882 /*
1883 * Including all fields other than the name, a LOCK4denied structure requires
1884 *   8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
1885 */
1886 static void
1887 nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld)
1888 {
1889         ENCODE_HEAD;
1890
1891         RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop->so_owner.len));
1892         WRITE64(ld->ld_start);
1893         WRITE64(ld->ld_length);
1894         WRITE32(ld->ld_type);
1895         WRITEMEM(&ld->ld_sop->so_client->cl_clientid, 8);
1896         WRITE32(ld->ld_sop->so_owner.len);
1897         WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
1898         ADJUST_ARGS();
1899 }
1900
1901 static void
1902 nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
1903 {
1904
1905         ENCODE_SEQID_OP_HEAD;
1906
1907         if (!nfserr) {
1908                 RESERVE_SPACE(4 + sizeof(stateid_t));
1909                 WRITE32(lock->lk_resp_stateid.si_generation);
1910                 WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
1911                 ADJUST_ARGS();
1912         } else if (nfserr == nfserr_denied)
1913                 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
1914
1915         ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
1916 }
1917
1918 static void
1919 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt)
1920 {
1921         if (nfserr == nfserr_denied)
1922                 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
1923 }
1924
1925 static void
1926 nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
1927 {
1928         ENCODE_SEQID_OP_HEAD;
1929
1930         if (!nfserr) {
1931                 RESERVE_SPACE(sizeof(stateid_t));
1932                 WRITE32(locku->lu_stateid.si_generation);
1933                 WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
1934                 ADJUST_ARGS();
1935         }
1936                                         
1937         ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
1938 }
1939
1940
1941 static void
1942 nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
1943 {
1944         ENCODE_HEAD;
1945
1946         if (!nfserr) {
1947                 RESERVE_SPACE(20);
1948                 WRITECINFO(link->li_cinfo);
1949                 ADJUST_ARGS();
1950         }
1951 }
1952
1953
1954 static void
1955 nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open)
1956 {
1957         ENCODE_SEQID_OP_HEAD;
1958
1959         if (nfserr)
1960                 goto out;
1961
1962         RESERVE_SPACE(36 + sizeof(stateid_t));
1963         WRITE32(open->op_stateid.si_generation);
1964         WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
1965         WRITECINFO(open->op_cinfo);
1966         WRITE32(open->op_rflags);
1967         WRITE32(2);
1968         WRITE32(open->op_bmval[0]);
1969         WRITE32(open->op_bmval[1]);
1970         WRITE32(open->op_delegate_type);
1971         ADJUST_ARGS();
1972
1973         switch (open->op_delegate_type) {
1974         case NFS4_OPEN_DELEGATE_NONE:
1975                 break;
1976         case NFS4_OPEN_DELEGATE_READ:
1977                 RESERVE_SPACE(20 + sizeof(delegation_stateid_t));
1978                 WRITEMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t));
1979                 WRITE32(0);
1980
1981                 /*
1982                  * TODO: ACE's in delegations
1983                  */
1984                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
1985                 WRITE32(0);
1986                 WRITE32(0);
1987                 WRITE32(0);   /* XXX: is NULL principal ok? */
1988                 ADJUST_ARGS();
1989                 break;
1990         case NFS4_OPEN_DELEGATE_WRITE:
1991                 RESERVE_SPACE(32 + sizeof(delegation_stateid_t));
1992                 WRITEMEM(&open->op_delegate_stateid, sizeof(delegation_stateid_t));
1993                 WRITE32(0);
1994
1995                 /*
1996                  * TODO: space_limit's in delegations
1997                  */
1998                 WRITE32(NFS4_LIMIT_SIZE);
1999                 WRITE32(~(u32)0);
2000                 WRITE32(~(u32)0);
2001
2002                 /*
2003                  * TODO: ACE's in delegations
2004                  */
2005                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2006                 WRITE32(0);
2007                 WRITE32(0);
2008                 WRITE32(0);   /* XXX: is NULL principal ok? */
2009                 ADJUST_ARGS();
2010                 break;
2011         default:
2012                 BUG();
2013         }
2014         /* XXX save filehandle here */
2015 out:
2016         ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2017 }
2018
2019 static void
2020 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
2021 {
2022         ENCODE_SEQID_OP_HEAD;
2023                                         
2024         if (!nfserr) {
2025                 RESERVE_SPACE(sizeof(stateid_t));
2026                 WRITE32(oc->oc_resp_stateid.si_generation);
2027                 WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2028                 ADJUST_ARGS();
2029         }
2030
2031         ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2032 }
2033
2034 static void
2035 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
2036 {
2037         ENCODE_SEQID_OP_HEAD;
2038                                         
2039         if (!nfserr) {
2040                 RESERVE_SPACE(sizeof(stateid_t));
2041                 WRITE32(od->od_stateid.si_generation);
2042                 WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
2043                 ADJUST_ARGS();
2044         }
2045
2046         ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2047 }
2048
2049 static int
2050 nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read)
2051 {
2052         u32 eof;
2053         int v, pn;
2054         unsigned long maxcount; 
2055         long len;
2056         ENCODE_HEAD;
2057
2058         if (nfserr)
2059                 return nfserr;
2060         if (resp->xbuf->page_len)
2061                 return nfserr_resource;
2062
2063         RESERVE_SPACE(8); /* eof flag and byte count */
2064
2065         maxcount = NFSSVC_MAXBLKSIZE;
2066         if (maxcount > read->rd_length)
2067                 maxcount = read->rd_length;
2068
2069         len = maxcount;
2070         v = 0;
2071         while (len > 0) {
2072                 pn = resp->rqstp->rq_resused;
2073                 svc_take_page(resp->rqstp);
2074                 read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]);
2075                 read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE;
2076                 v++;
2077                 len -= PAGE_SIZE;
2078         }
2079         read->rd_vlen = v;
2080
2081         nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp,
2082                            read->rd_offset,
2083                            read->rd_iov, read->rd_vlen,
2084                            &maxcount);
2085         if (nfserr == nfserr_symlink)
2086                 nfserr = nfserr_inval;
2087         if (nfserr)
2088                 return nfserr;
2089         eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size);
2090
2091         WRITE32(eof);
2092         WRITE32(maxcount);
2093         ADJUST_ARGS();
2094         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2095
2096         resp->xbuf->page_len = maxcount;
2097
2098         /* read zero bytes -> don't set up tail */
2099         if(!maxcount)
2100                 return 0;        
2101
2102         /* set up page for remaining responses */
2103         svc_take_page(resp->rqstp);
2104         resp->xbuf->tail[0].iov_base = 
2105                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2106         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2107         resp->xbuf->tail[0].iov_len = 0;
2108         resp->p = resp->xbuf->tail[0].iov_base;
2109         resp->end = resp->p + PAGE_SIZE/4;
2110
2111         if (maxcount&3) {
2112                 *(resp->p)++ = 0;
2113                 resp->xbuf->tail[0].iov_base += maxcount&3;
2114                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2115         }
2116         return 0;
2117 }
2118
2119 static int
2120 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink)
2121 {
2122         int maxcount;
2123         char *page;
2124         ENCODE_HEAD;
2125
2126         if (nfserr)
2127                 return nfserr;
2128         if (resp->xbuf->page_len)
2129                 return nfserr_resource;
2130
2131         svc_take_page(resp->rqstp);
2132         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2133
2134         maxcount = PAGE_SIZE;
2135         RESERVE_SPACE(4);
2136
2137         /*
2138          * XXX: By default, the ->readlink() VFS op will truncate symlinks
2139          * if they would overflow the buffer.  Is this kosher in NFSv4?  If
2140          * not, one easy fix is: if ->readlink() precisely fills the buffer,
2141          * assume that truncation occurred, and return NFS4ERR_RESOURCE.
2142          */
2143         nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2144         if (nfserr == nfserr_isdir)
2145                 return nfserr_inval;
2146         if (nfserr)
2147                 return nfserr;
2148
2149         WRITE32(maxcount);
2150         ADJUST_ARGS();
2151         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2152
2153         svc_take_page(resp->rqstp);
2154         resp->xbuf->tail[0].iov_base = 
2155                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2156         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2157         resp->xbuf->tail[0].iov_len = 0;
2158         resp->p = resp->xbuf->tail[0].iov_base;
2159         resp->end = resp->p + PAGE_SIZE/4;
2160
2161         resp->xbuf->page_len = maxcount;
2162         if (maxcount&3) {
2163                 *(resp->p)++ = 0;
2164                 resp->xbuf->tail[0].iov_base += maxcount&3;
2165                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2166         }
2167         return 0;
2168 }
2169
2170 static int
2171 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir)
2172 {
2173         int maxcount;
2174         loff_t offset;
2175         u32 *page, *savep;
2176         ENCODE_HEAD;
2177
2178         if (nfserr)
2179                 return nfserr;
2180         if (resp->xbuf->page_len)
2181                 return nfserr_resource;
2182
2183         RESERVE_SPACE(8);  /* verifier */
2184         savep = p;
2185
2186         /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
2187         WRITE32(0);
2188         WRITE32(0);
2189         ADJUST_ARGS();
2190         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2191
2192         maxcount = PAGE_SIZE;
2193         if (maxcount > readdir->rd_maxcount)
2194                 maxcount = readdir->rd_maxcount;
2195
2196         /*
2197          * Convert from bytes to words, account for the two words already
2198          * written, make sure to leave two words at the end for the next
2199          * pointer and eof field.
2200          */
2201         maxcount = (maxcount >> 2) - 4;
2202         if (maxcount < 0) {
2203                 nfserr =  nfserr_toosmall;
2204                 goto err_no_verf;
2205         }
2206
2207         svc_take_page(resp->rqstp);
2208         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2209         readdir->common.err = 0;
2210         readdir->buflen = maxcount;
2211         readdir->buffer = page;
2212         readdir->offset = NULL;
2213
2214         offset = readdir->rd_cookie;
2215         nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2216                               &offset,
2217                               &readdir->common, nfsd4_encode_dirent);
2218         if (nfserr == nfs_ok &&
2219             readdir->common.err == nfserr_toosmall &&
2220             readdir->buffer == page) 
2221                 nfserr = nfserr_toosmall;
2222         if (nfserr == nfserr_symlink)
2223                 nfserr = nfserr_notdir;
2224         if (nfserr)
2225                 goto err_no_verf;
2226
2227         if (readdir->offset)
2228                 xdr_encode_hyper(readdir->offset, offset);
2229
2230         p = readdir->buffer;
2231         *p++ = 0;       /* no more entries */
2232         *p++ = htonl(readdir->common.err == nfserr_eof);
2233         resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2234
2235         /* allocate a page for the tail */
2236         svc_take_page(resp->rqstp);
2237         resp->xbuf->tail[0].iov_base = 
2238                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2239         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2240         resp->xbuf->tail[0].iov_len = 0;
2241         resp->p = resp->xbuf->tail[0].iov_base;
2242         resp->end = resp->p + PAGE_SIZE/4;
2243
2244         return 0;
2245 err_no_verf:
2246         p = savep;
2247         ADJUST_ARGS();
2248         return nfserr;
2249 }
2250
2251 static void
2252 nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove)
2253 {
2254         ENCODE_HEAD;
2255
2256         if (!nfserr) {
2257                 RESERVE_SPACE(20);
2258                 WRITECINFO(remove->rm_cinfo);
2259                 ADJUST_ARGS();
2260         }
2261 }
2262
2263 static void
2264 nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename)
2265 {
2266         ENCODE_HEAD;
2267
2268         if (!nfserr) {
2269                 RESERVE_SPACE(40);
2270                 WRITECINFO(rename->rn_sinfo);
2271                 WRITECINFO(rename->rn_tinfo);
2272                 ADJUST_ARGS();
2273         }
2274 }
2275
2276 /*
2277  * The SETATTR encode routine is special -- it always encodes a bitmap,
2278  * regardless of the error status.
2279  */
2280 static void
2281 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr)
2282 {
2283         ENCODE_HEAD;
2284
2285         RESERVE_SPACE(12);
2286         if (nfserr) {
2287                 WRITE32(2);
2288                 WRITE32(0);
2289                 WRITE32(0);
2290         }
2291         else {
2292                 WRITE32(2);
2293                 WRITE32(setattr->sa_bmval[0]);
2294                 WRITE32(setattr->sa_bmval[1]);
2295         }
2296         ADJUST_ARGS();
2297 }
2298
2299 static void
2300 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd)
2301 {
2302         ENCODE_HEAD;
2303
2304         if (!nfserr) {
2305                 RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2306                 WRITEMEM(&scd->se_clientid, 8);
2307                 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2308                 ADJUST_ARGS();
2309         }
2310         else if (nfserr == nfserr_clid_inuse) {
2311                 RESERVE_SPACE(8);
2312                 WRITE32(0);
2313                 WRITE32(0);
2314                 ADJUST_ARGS();
2315         }
2316 }
2317
2318 static void
2319 nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write)
2320 {
2321         ENCODE_HEAD;
2322
2323         if (!nfserr) {
2324                 RESERVE_SPACE(16);
2325                 WRITE32(write->wr_bytes_written);
2326                 WRITE32(write->wr_how_written);
2327                 WRITEMEM(write->wr_verifier.data, 8);
2328                 ADJUST_ARGS();
2329         }
2330 }
2331
2332 void
2333 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2334 {
2335         u32 *statp;
2336         ENCODE_HEAD;
2337
2338         RESERVE_SPACE(8);
2339         WRITE32(op->opnum);
2340         statp = p++;    /* to be backfilled at the end */
2341         ADJUST_ARGS();
2342
2343         switch (op->opnum) {
2344         case OP_ACCESS:
2345                 nfsd4_encode_access(resp, op->status, &op->u.access);
2346                 break;
2347         case OP_CLOSE:
2348                 nfsd4_encode_close(resp, op->status, &op->u.close);
2349                 break;
2350         case OP_COMMIT:
2351                 nfsd4_encode_commit(resp, op->status, &op->u.commit);
2352                 break;
2353         case OP_CREATE:
2354                 nfsd4_encode_create(resp, op->status, &op->u.create);
2355                 break;
2356         case OP_GETATTR:
2357                 op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
2358                 break;
2359         case OP_GETFH:
2360                 nfsd4_encode_getfh(resp, op->status, op->u.getfh);
2361                 break;
2362         case OP_LINK:
2363                 nfsd4_encode_link(resp, op->status, &op->u.link);
2364                 break;
2365         case OP_LOCK:
2366                 nfsd4_encode_lock(resp, op->status, &op->u.lock);
2367                 break;
2368         case OP_LOCKT:
2369                 nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
2370                 break;
2371         case OP_LOCKU:
2372                 nfsd4_encode_locku(resp, op->status, &op->u.locku);
2373                 break;
2374         case OP_LOOKUP:
2375                 break;
2376         case OP_LOOKUPP:
2377                 break;
2378         case OP_NVERIFY:
2379                 break;
2380         case OP_OPEN:
2381                 nfsd4_encode_open(resp, op->status, &op->u.open);
2382                 break;
2383         case OP_OPEN_CONFIRM:
2384                 nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
2385                 break;
2386         case OP_OPEN_DOWNGRADE:
2387                 nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
2388                 break;
2389         case OP_PUTFH:
2390                 break;
2391         case OP_PUTROOTFH:
2392                 break;
2393         case OP_READ:
2394                 op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
2395                 break;
2396         case OP_READDIR:
2397                 op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
2398                 break;
2399         case OP_READLINK:
2400                 op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
2401                 break;
2402         case OP_REMOVE:
2403                 nfsd4_encode_remove(resp, op->status, &op->u.remove);
2404                 break;
2405         case OP_RENAME:
2406                 nfsd4_encode_rename(resp, op->status, &op->u.rename);
2407                 break;
2408         case OP_RENEW:
2409                 break;
2410         case OP_RESTOREFH:
2411                 break;
2412         case OP_SAVEFH:
2413                 break;
2414         case OP_SETATTR:
2415                 nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2416                 break;
2417         case OP_SETCLIENTID:
2418                 nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
2419                 break;
2420         case OP_SETCLIENTID_CONFIRM:
2421                 break;
2422         case OP_VERIFY:
2423                 break;
2424         case OP_WRITE:
2425                 nfsd4_encode_write(resp, op->status, &op->u.write);
2426                 break;
2427         case OP_RELEASE_LOCKOWNER:
2428                 break;
2429         default:
2430                 break;
2431         }
2432
2433         /*
2434          * Note: We write the status directly, instead of using WRITE32(),
2435          * since it is already in network byte order.
2436          */
2437         *statp = op->status;
2438 }
2439
2440 /* 
2441  * Encode the reply stored in the stateowner reply cache 
2442  * 
2443  * XDR note: do not encode rp->rp_buflen: the buffer contains the
2444  * previously sent already encoded operation.
2445  *
2446  * called with nfs4_lock_state() held
2447  */
2448 void
2449 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2450 {
2451         ENCODE_HEAD;
2452         struct nfs4_replay *rp = op->replay;
2453
2454         BUG_ON(!rp);
2455
2456         RESERVE_SPACE(8);
2457         WRITE32(op->opnum);
2458         *p++ = rp->rp_status;  /* already xdr'ed */
2459         ADJUST_ARGS();
2460
2461         RESERVE_SPACE(rp->rp_buflen);
2462         WRITEMEM(rp->rp_buf, rp->rp_buflen);
2463         ADJUST_ARGS();
2464         nfs4_unlock_state();
2465 }
2466
2467 /*
2468  * END OF "GENERIC" ENCODE ROUTINES.
2469  */
2470
2471 int
2472 nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
2473 {
2474         return xdr_ressize_check(rqstp, p);
2475 }
2476
2477 int
2478 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args)
2479 {
2480         int status;
2481
2482         args->p = p;
2483         args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
2484         args->pagelist = rqstp->rq_arg.pages;
2485         args->pagelen = rqstp->rq_arg.page_len;
2486         args->tmpp = NULL;
2487         args->to_free = NULL;
2488         args->ops = args->iops;
2489         args->rqstp = rqstp;
2490
2491         status = nfsd4_decode_compound(args);
2492         if (status) {
2493                 if (args->ops != args->iops) {
2494                         kfree(args->ops);
2495                         args->ops = args->iops;
2496                 }
2497                 if (args->tmpp) {
2498                         kfree(args->tmpp);
2499                         args->tmpp = NULL;
2500                 }
2501                 while (args->to_free) {
2502                         struct tmpbuf *tb = args->to_free;
2503                         args->to_free = tb->next;
2504                         kfree(tb->buf);
2505                         kfree(tb);
2506                 }
2507         }
2508         return !status;
2509 }
2510
2511 int
2512 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp)
2513 {
2514         /*
2515          * All that remains is to write the tag and operation count...
2516          */
2517         struct iovec *iov;
2518         p = resp->tagp;
2519         *p++ = htonl(resp->taglen);
2520         memcpy(p, resp->tag, resp->taglen);
2521         p += XDR_QUADLEN(resp->taglen);
2522         *p++ = htonl(resp->opcnt);
2523
2524         if (rqstp->rq_res.page_len) 
2525                 iov = &rqstp->rq_res.tail[0];
2526         else
2527                 iov = &rqstp->rq_res.head[0];
2528         iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
2529         BUG_ON(iov->iov_len > PAGE_SIZE);
2530         return 1;
2531 }
2532
2533 /*
2534  * Local variables:
2535  *  c-basic-offset: 8
2536  * End:
2537  */