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