kernel.org 2.6.11.7
[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 static int
549 nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
550 {
551         DECODE_HEAD;
552
553         close->cl_stateowner = NULL;
554         READ_BUF(4 + sizeof(stateid_t));
555         READ32(close->cl_seqid);
556         READ32(close->cl_stateid.si_generation);
557         COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t));
558
559         DECODE_TAIL;
560 }
561
562
563 static int
564 nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
565 {
566         DECODE_HEAD;
567
568         READ_BUF(12);
569         READ64(commit->co_offset);
570         READ32(commit->co_count);
571
572         DECODE_TAIL;
573 }
574
575 static int
576 nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
577 {
578         DECODE_HEAD;
579
580         READ_BUF(4);
581         READ32(create->cr_type);
582         switch (create->cr_type) {
583         case NF4LNK:
584                 READ_BUF(4);
585                 READ32(create->cr_linklen);
586                 READ_BUF(create->cr_linklen);
587                 SAVEMEM(create->cr_linkname, create->cr_linklen);
588                 if (check_utf8(create->cr_linkname, create->cr_linklen))
589                         return nfserr_inval;
590                 break;
591         case NF4BLK:
592         case NF4CHR:
593                 READ_BUF(8);
594                 READ32(create->cr_specdata1);
595                 READ32(create->cr_specdata2);
596                 break;
597         case NF4SOCK:
598         case NF4FIFO:
599         case NF4DIR:
600         default:
601                 break;
602         }
603
604         READ_BUF(4);
605         READ32(create->cr_namelen);
606         READ_BUF(create->cr_namelen);
607         SAVEMEM(create->cr_name, create->cr_namelen);
608         if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval)))
609                 return status;
610
611         if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl)))
612                 goto out;
613
614         DECODE_TAIL;
615 }
616
617 static inline int
618 nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
619 {
620         DECODE_HEAD;
621
622         READ_BUF(sizeof(stateid_t));
623         READ32(dr->dr_stateid.si_generation);
624         COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t));
625
626         DECODE_TAIL;
627 }
628
629 static inline int
630 nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
631 {
632         return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
633 }
634
635 static int
636 nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
637 {
638         DECODE_HEAD;
639
640         READ_BUF(4);
641         READ32(link->li_namelen);
642         READ_BUF(link->li_namelen);
643         SAVEMEM(link->li_name, link->li_namelen);
644         if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval)))
645                 return status;
646
647         DECODE_TAIL;
648 }
649
650 static int
651 nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
652 {
653         DECODE_HEAD;
654
655         lock->lk_stateowner = NULL;
656         /*
657         * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
658         */
659         READ_BUF(28);
660         READ32(lock->lk_type);
661         if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
662                 goto xdr_error;
663         READ32(lock->lk_reclaim);
664         READ64(lock->lk_offset);
665         READ64(lock->lk_length);
666         READ32(lock->lk_is_new);
667
668         if (lock->lk_is_new) {
669                 READ_BUF(36);
670                 READ32(lock->lk_new_open_seqid);
671                 READ32(lock->lk_new_open_stateid.si_generation);
672
673                 COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t));
674                 READ32(lock->lk_new_lock_seqid);
675                 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
676                 READ32(lock->lk_new_owner.len);
677                 READ_BUF(lock->lk_new_owner.len);
678                 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
679         } else {
680                 READ_BUF(20);
681                 READ32(lock->lk_old_lock_stateid.si_generation);
682                 COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t));
683                 READ32(lock->lk_old_lock_seqid);
684         }
685
686         DECODE_TAIL;
687 }
688
689 static int
690 nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
691 {
692         DECODE_HEAD;
693                         
694         READ_BUF(32);
695         READ32(lockt->lt_type);
696         if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
697                 goto xdr_error;
698         READ64(lockt->lt_offset);
699         READ64(lockt->lt_length);
700         COPYMEM(&lockt->lt_clientid, 8);
701         READ32(lockt->lt_owner.len);
702         READ_BUF(lockt->lt_owner.len);
703         READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
704
705         DECODE_TAIL;
706 }
707
708 static int
709 nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
710 {
711         DECODE_HEAD;
712
713         locku->lu_stateowner = NULL;
714         READ_BUF(24 + sizeof(stateid_t));
715         READ32(locku->lu_type);
716         if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
717                 goto xdr_error;
718         READ32(locku->lu_seqid);
719         READ32(locku->lu_stateid.si_generation);
720         COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
721         READ64(locku->lu_offset);
722         READ64(locku->lu_length);
723
724         DECODE_TAIL;
725 }
726
727 static int
728 nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
729 {
730         DECODE_HEAD;
731
732         READ_BUF(4);
733         READ32(lookup->lo_len);
734         READ_BUF(lookup->lo_len);
735         SAVEMEM(lookup->lo_name, lookup->lo_len);
736         if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent)))
737                 return status;
738
739         DECODE_TAIL;
740 }
741
742 static int
743 nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
744 {
745         DECODE_HEAD;
746
747         memset(open->op_bmval, 0, sizeof(open->op_bmval));
748         open->op_iattr.ia_valid = 0;
749         open->op_stateowner = NULL;
750
751         /* seqid, share_access, share_deny, clientid, ownerlen */
752         READ_BUF(16 + sizeof(clientid_t));
753         READ32(open->op_seqid);
754         READ32(open->op_share_access);
755         READ32(open->op_share_deny);
756         COPYMEM(&open->op_clientid, sizeof(clientid_t));
757         READ32(open->op_owner.len);
758
759         /* owner, open_flag */
760         READ_BUF(open->op_owner.len + 4);
761         SAVEMEM(open->op_owner.data, open->op_owner.len);
762         READ32(open->op_create);
763         switch (open->op_create) {
764         case NFS4_OPEN_NOCREATE:
765                 break;
766         case NFS4_OPEN_CREATE:
767                 READ_BUF(4);
768                 READ32(open->op_createmode);
769                 switch (open->op_createmode) {
770                 case NFS4_CREATE_UNCHECKED:
771                 case NFS4_CREATE_GUARDED:
772                         if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl)))
773                                 goto out;
774                         break;
775                 case NFS4_CREATE_EXCLUSIVE:
776                         READ_BUF(8);
777                         COPYMEM(open->op_verf.data, 8);
778                         break;
779                 default:
780                         goto xdr_error;
781                 }
782                 break;
783         default:
784                 goto xdr_error;
785         }
786
787         /* open_claim */
788         READ_BUF(4);
789         READ32(open->op_claim_type);
790         switch (open->op_claim_type) {
791         case NFS4_OPEN_CLAIM_NULL:
792         case NFS4_OPEN_CLAIM_DELEGATE_PREV:
793                 READ_BUF(4);
794                 READ32(open->op_fname.len);
795                 READ_BUF(open->op_fname.len);
796                 SAVEMEM(open->op_fname.data, open->op_fname.len);
797                 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
798                         return status;
799                 break;
800         case NFS4_OPEN_CLAIM_PREVIOUS:
801                 READ_BUF(4);
802                 READ32(open->op_delegate_type);
803                 break;
804         case NFS4_OPEN_CLAIM_DELEGATE_CUR:
805                 READ_BUF(sizeof(stateid_t) + 4);
806                 COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t));
807                 READ32(open->op_fname.len);
808                 READ_BUF(open->op_fname.len);
809                 SAVEMEM(open->op_fname.data, open->op_fname.len);
810                 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval)))
811                         return status;
812                 break;
813         default:
814                 goto xdr_error;
815         }
816
817         DECODE_TAIL;
818 }
819
820 static int
821 nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
822 {
823         DECODE_HEAD;
824                     
825         open_conf->oc_stateowner = NULL;
826         READ_BUF(4 + sizeof(stateid_t));
827         READ32(open_conf->oc_req_stateid.si_generation);
828         COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t));
829         READ32(open_conf->oc_seqid);
830                                                         
831         DECODE_TAIL;
832 }
833
834 static int
835 nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
836 {
837         DECODE_HEAD;
838                     
839         open_down->od_stateowner = NULL;
840         READ_BUF(12 + sizeof(stateid_t));
841         READ32(open_down->od_stateid.si_generation);
842         COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t));
843         READ32(open_down->od_seqid);
844         READ32(open_down->od_share_access);
845         READ32(open_down->od_share_deny);
846                                                         
847         DECODE_TAIL;
848 }
849
850 static int
851 nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
852 {
853         DECODE_HEAD;
854
855         READ_BUF(4);
856         READ32(putfh->pf_fhlen);
857         if (putfh->pf_fhlen > NFS4_FHSIZE)
858                 goto xdr_error;
859         READ_BUF(putfh->pf_fhlen);
860         SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
861
862         DECODE_TAIL;
863 }
864
865 static int
866 nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
867 {
868         DECODE_HEAD;
869
870         READ_BUF(sizeof(stateid_t) + 12);
871         READ32(read->rd_stateid.si_generation);
872         COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t));
873         READ64(read->rd_offset);
874         READ32(read->rd_length);
875
876         DECODE_TAIL;
877 }
878
879 static int
880 nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
881 {
882         DECODE_HEAD;
883
884         READ_BUF(24);
885         READ64(readdir->rd_cookie);
886         COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
887         READ32(readdir->rd_dircount);    /* just in case you needed a useless field... */
888         READ32(readdir->rd_maxcount);
889         if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
890                 goto out;
891
892         DECODE_TAIL;
893 }
894
895 static int
896 nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
897 {
898         DECODE_HEAD;
899
900         READ_BUF(4);
901         READ32(remove->rm_namelen);
902         READ_BUF(remove->rm_namelen);
903         SAVEMEM(remove->rm_name, remove->rm_namelen);
904         if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent)))
905                 return status;
906
907         DECODE_TAIL;
908 }
909
910 static int
911 nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
912 {
913         DECODE_HEAD;
914
915         READ_BUF(4);
916         READ32(rename->rn_snamelen);
917         READ_BUF(rename->rn_snamelen + 4);
918         SAVEMEM(rename->rn_sname, rename->rn_snamelen);
919         READ32(rename->rn_tnamelen);
920         READ_BUF(rename->rn_tnamelen);
921         SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
922         if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent)))
923                 return status;
924         if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval)))
925                 return status;
926
927         DECODE_TAIL;
928 }
929
930 static int
931 nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
932 {
933         DECODE_HEAD;
934
935         READ_BUF(sizeof(clientid_t));
936         COPYMEM(clientid, sizeof(clientid_t));
937
938         DECODE_TAIL;
939 }
940
941 static int
942 nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
943 {
944         DECODE_HEAD;
945
946         READ_BUF(sizeof(stateid_t));
947         READ32(setattr->sa_stateid.si_generation);
948         COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t));
949         if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl)))
950                 goto out;
951
952         DECODE_TAIL;
953 }
954
955 static int
956 nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
957 {
958         DECODE_HEAD;
959
960         READ_BUF(12);
961         COPYMEM(setclientid->se_verf.data, 8);
962         READ32(setclientid->se_namelen);
963
964         READ_BUF(setclientid->se_namelen + 8);
965         SAVEMEM(setclientid->se_name, setclientid->se_namelen);
966         READ32(setclientid->se_callback_prog);
967         READ32(setclientid->se_callback_netid_len);
968
969         READ_BUF(setclientid->se_callback_netid_len + 4);
970         SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
971         READ32(setclientid->se_callback_addr_len);
972
973         READ_BUF(setclientid->se_callback_addr_len + 4);
974         SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
975         READ32(setclientid->se_callback_ident);
976
977         DECODE_TAIL;
978 }
979
980 static int
981 nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
982 {
983         DECODE_HEAD;
984
985         READ_BUF(8 + sizeof(nfs4_verifier));
986         COPYMEM(&scd_c->sc_clientid, 8);
987         COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier));
988
989         DECODE_TAIL;
990 }
991
992 /* Also used for NVERIFY */
993 static int
994 nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
995 {
996 #if 0
997         struct nfsd4_compoundargs save = {
998                 .p = argp->p,
999                 .end = argp->end,
1000                 .rqstp = argp->rqstp,
1001         };
1002         u32             ve_bmval[2];
1003         struct iattr    ve_iattr;           /* request */
1004         struct nfs4_acl *ve_acl;            /* request */
1005 #endif
1006         DECODE_HEAD;
1007
1008         if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
1009                 goto out;
1010
1011         /* For convenience's sake, we compare raw xdr'd attributes in
1012          * nfsd4_proc_verify; however we still decode here just to return
1013          * correct error in case of bad xdr. */
1014 #if 0
1015         status = nfsd4_decode_fattr(ve_bmval, &ve_iattr, &ve_acl);
1016         if (status == nfserr_inval) {
1017                 status = nfserrno(status);
1018                 goto out;
1019         }
1020 #endif
1021         READ_BUF(4);
1022         READ32(verify->ve_attrlen);
1023         READ_BUF(verify->ve_attrlen);
1024         SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
1025
1026         DECODE_TAIL;
1027 }
1028
1029 static int
1030 nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1031 {
1032         int avail;
1033         int v;
1034         int len;
1035         DECODE_HEAD;
1036
1037         READ_BUF(sizeof(stateid_opaque_t) + 20);
1038         READ32(write->wr_stateid.si_generation);
1039         COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t));
1040         READ64(write->wr_offset);
1041         READ32(write->wr_stable_how);
1042         if (write->wr_stable_how > 2)
1043                 goto xdr_error;
1044         READ32(write->wr_buflen);
1045
1046         /* Sorry .. no magic macros for this.. *
1047          * READ_BUF(write->wr_buflen);
1048          * SAVEMEM(write->wr_buf, write->wr_buflen);
1049          */
1050         avail = (char*)argp->end - (char*)argp->p;
1051         if (avail + argp->pagelen < write->wr_buflen) {
1052                 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); 
1053                 goto xdr_error;
1054         }
1055         write->wr_vec[0].iov_base = p;
1056         write->wr_vec[0].iov_len = avail;
1057         v = 0;
1058         len = write->wr_buflen;
1059         while (len > write->wr_vec[v].iov_len) {
1060                 len -= write->wr_vec[v].iov_len;
1061                 v++;
1062                 write->wr_vec[v].iov_base = page_address(argp->pagelist[0]);
1063                 argp->pagelist++;
1064                 if (argp->pagelen >= PAGE_SIZE) {
1065                         write->wr_vec[v].iov_len = PAGE_SIZE;
1066                         argp->pagelen -= PAGE_SIZE;
1067                 } else {
1068                         write->wr_vec[v].iov_len = argp->pagelen;
1069                         argp->pagelen -= len;
1070                 }
1071         }
1072         argp->end = (u32*) (write->wr_vec[v].iov_base + write->wr_vec[v].iov_len);
1073         argp->p = (u32*)  (write->wr_vec[v].iov_base + (XDR_QUADLEN(len) << 2));
1074         write->wr_vec[v].iov_len = len;
1075         write->wr_vlen = v+1;
1076
1077         DECODE_TAIL;
1078 }
1079
1080 static int
1081 nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
1082 {
1083         DECODE_HEAD;
1084
1085         READ_BUF(12);
1086         COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
1087         READ32(rlockowner->rl_owner.len);
1088         READ_BUF(rlockowner->rl_owner.len);
1089         READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
1090
1091         DECODE_TAIL;
1092 }
1093
1094 static int
1095 nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1096 {
1097         DECODE_HEAD;
1098         struct nfsd4_op *op;
1099         int i;
1100
1101         /*
1102          * XXX: According to spec, we should check the tag
1103          * for UTF-8 compliance.  I'm postponing this for
1104          * now because it seems that some clients do use
1105          * binary tags.
1106          */
1107         READ_BUF(4);
1108         READ32(argp->taglen);
1109         READ_BUF(argp->taglen + 8);
1110         SAVEMEM(argp->tag, argp->taglen);
1111         READ32(argp->minorversion);
1112         READ32(argp->opcnt);
1113
1114         if (argp->taglen > NFSD4_MAX_TAGLEN)
1115                 goto xdr_error;
1116         if (argp->opcnt > 100)
1117                 goto xdr_error;
1118
1119         if (argp->opcnt > sizeof(argp->iops)/sizeof(argp->iops[0])) {
1120                 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1121                 if (!argp->ops) {
1122                         argp->ops = argp->iops;
1123                         printk(KERN_INFO "nfsd: couldn't allocate room for COMPOUND\n");
1124                         goto xdr_error;
1125                 }
1126         }
1127
1128         for (i = 0; i < argp->opcnt; i++) {
1129                 op = &argp->ops[i];
1130                 op->replay = NULL;
1131
1132                 /*
1133                  * We can't use READ_BUF() here because we need to handle
1134                  * a missing opcode as an OP_WRITE + 1. So we need to check
1135                  * to see if we're truly at the end of our buffer or if there
1136                  * is another page we need to flip to.
1137                  */
1138
1139                 if (argp->p == argp->end) {
1140                         if (argp->pagelen < 4) {
1141                                 /* There isn't an opcode still on the wire */
1142                                 op->opnum = OP_WRITE + 1;
1143                                 op->status = nfserr_bad_xdr;
1144                                 argp->opcnt = i+1;
1145                                 break;
1146                         }
1147
1148                         /*
1149                          * False alarm. We just hit a page boundary, but there
1150                          * is still data available.  Move pointer across page
1151                          * boundary.  *snip from READ_BUF*
1152                          */
1153                         argp->p = page_address(argp->pagelist[0]);
1154                         argp->pagelist++;
1155                         if (argp->pagelen < PAGE_SIZE) {
1156                                 argp->end = p + (argp->pagelen>>2);
1157                                 argp->pagelen = 0;
1158                         } else {
1159                                 argp->end = p + (PAGE_SIZE>>2);
1160                                 argp->pagelen -= PAGE_SIZE;
1161                         }
1162                 }
1163                 op->opnum = ntohl(*argp->p++);
1164
1165                 switch (op->opnum) {
1166                 case 2: /* Reserved operation */
1167                         op->opnum = OP_ILLEGAL;
1168                         if (argp->minorversion == 0)
1169                                 op->status = nfserr_op_illegal;
1170                         else
1171                                 op->status = nfserr_minor_vers_mismatch;
1172                         break;
1173                 case OP_ACCESS:
1174                         op->status = nfsd4_decode_access(argp, &op->u.access);
1175                         break;
1176                 case OP_CLOSE:
1177                         op->status = nfsd4_decode_close(argp, &op->u.close);
1178                         break;
1179                 case OP_COMMIT:
1180                         op->status = nfsd4_decode_commit(argp, &op->u.commit);
1181                         break;
1182                 case OP_CREATE:
1183                         op->status = nfsd4_decode_create(argp, &op->u.create);
1184                         break;
1185                 case OP_DELEGRETURN:
1186                         op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn);
1187                         break;
1188                 case OP_GETATTR:
1189                         op->status = nfsd4_decode_getattr(argp, &op->u.getattr);
1190                         break;
1191                 case OP_GETFH:
1192                         op->status = nfs_ok;
1193                         break;
1194                 case OP_LINK:
1195                         op->status = nfsd4_decode_link(argp, &op->u.link);
1196                         break;
1197                 case OP_LOCK:
1198                         op->status = nfsd4_decode_lock(argp, &op->u.lock);
1199                         break;
1200                 case OP_LOCKT:
1201                         op->status = nfsd4_decode_lockt(argp, &op->u.lockt);
1202                         break;
1203                 case OP_LOCKU:
1204                         op->status = nfsd4_decode_locku(argp, &op->u.locku);
1205                         break;
1206                 case OP_LOOKUP:
1207                         op->status = nfsd4_decode_lookup(argp, &op->u.lookup);
1208                         break;
1209                 case OP_LOOKUPP:
1210                         op->status = nfs_ok;
1211                         break;
1212                 case OP_NVERIFY:
1213                         op->status = nfsd4_decode_verify(argp, &op->u.nverify);
1214                         break;
1215                 case OP_OPEN:
1216                         op->status = nfsd4_decode_open(argp, &op->u.open);
1217                         break;
1218                 case OP_OPEN_CONFIRM:
1219                         op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm);
1220                         break;
1221                 case OP_OPEN_DOWNGRADE:
1222                         op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade);
1223                         break;
1224                 case OP_PUTFH:
1225                         op->status = nfsd4_decode_putfh(argp, &op->u.putfh);
1226                         break;
1227                 case OP_PUTROOTFH:
1228                         op->status = nfs_ok;
1229                         break;
1230                 case OP_READ:
1231                         op->status = nfsd4_decode_read(argp, &op->u.read);
1232                         break;
1233                 case OP_READDIR:
1234                         op->status = nfsd4_decode_readdir(argp, &op->u.readdir);
1235                         break;
1236                 case OP_READLINK:
1237                         op->status = nfs_ok;
1238                         break;
1239                 case OP_REMOVE:
1240                         op->status = nfsd4_decode_remove(argp, &op->u.remove);
1241                         break;
1242                 case OP_RENAME:
1243                         op->status = nfsd4_decode_rename(argp, &op->u.rename);
1244                         break;
1245                 case OP_RESTOREFH:
1246                         op->status = nfs_ok;
1247                         break;
1248                 case OP_RENEW:
1249                         op->status = nfsd4_decode_renew(argp, &op->u.renew);
1250                         break;
1251                 case OP_SAVEFH:
1252                         op->status = nfs_ok;
1253                         break;
1254                 case OP_SETATTR:
1255                         op->status = nfsd4_decode_setattr(argp, &op->u.setattr);
1256                         break;
1257                 case OP_SETCLIENTID:
1258                         op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid);
1259                         break;
1260                 case OP_SETCLIENTID_CONFIRM:
1261                         op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm);
1262                         break;
1263                 case OP_VERIFY:
1264                         op->status = nfsd4_decode_verify(argp, &op->u.verify);
1265                         break;
1266                 case OP_WRITE:
1267                         op->status = nfsd4_decode_write(argp, &op->u.write);
1268                         break;
1269                 case OP_RELEASE_LOCKOWNER:
1270                         op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner);
1271                         break;
1272                 default:
1273                         op->opnum = OP_ILLEGAL;
1274                         op->status = nfserr_op_illegal;
1275                         break;
1276                 }
1277
1278                 if (op->status) {
1279                         argp->opcnt = i+1;
1280                         break;
1281                 }
1282         }
1283
1284         DECODE_TAIL;
1285 }
1286 /*
1287  * END OF "GENERIC" DECODE ROUTINES.
1288  */
1289
1290 /*
1291  * START OF "GENERIC" ENCODE ROUTINES.
1292  *   These may look a little ugly since they are imported from a "generic"
1293  * set of XDR encode/decode routines which are intended to be shared by
1294  * all of our NFSv4 implementations (OpenBSD, MacOS X...).
1295  *
1296  * If the pain of reading these is too great, it should be a straightforward
1297  * task to translate them into Linux-specific versions which are more
1298  * consistent with the style used in NFSv2/v3...
1299  */
1300 #define ENCODE_HEAD              u32 *p
1301
1302 #define WRITE32(n)               *p++ = htonl(n)
1303 #define WRITE64(n)               do {                           \
1304         *p++ = htonl((u32)((n) >> 32));                         \
1305         *p++ = htonl((u32)(n));                                 \
1306 } while (0)
1307 #define WRITEMEM(ptr,nbytes)     do {                           \
1308         *(p + XDR_QUADLEN(nbytes) -1) = 0;                      \
1309         memcpy(p, ptr, nbytes);                                 \
1310         p += XDR_QUADLEN(nbytes);                               \
1311 } while (0)
1312 #define WRITECINFO(c)           do {                            \
1313         *p++ = htonl(c.atomic);                                 \
1314         *p++ = htonl(c.before_ctime_sec);                               \
1315         *p++ = htonl(c.before_ctime_nsec);                              \
1316         *p++ = htonl(c.after_ctime_sec);                                \
1317         *p++ = htonl(c.after_ctime_nsec);                               \
1318 } while (0)
1319
1320 #define RESERVE_SPACE(nbytes)   do {                            \
1321         p = resp->p;                                            \
1322         BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end);            \
1323 } while (0)
1324 #define ADJUST_ARGS()           resp->p = p
1325
1326 /*
1327  * Header routine to setup seqid operation replay cache
1328  */
1329 #define ENCODE_SEQID_OP_HEAD                                    \
1330         u32 *p;                                                 \
1331         u32 *save;                                              \
1332                                                                 \
1333         save = resp->p;
1334
1335 /*
1336  * Routine for encoding the result of a
1337  * "seqid-mutating" NFSv4 operation.  This is
1338  * where seqids are incremented, and the
1339  * replay cache is filled.
1340  */
1341
1342 #define ENCODE_SEQID_OP_TAIL(stateowner) do {                   \
1343         if (seqid_mutating_err(nfserr) && stateowner) {         \
1344                 if (stateowner->so_confirmed)                   \
1345                         stateowner->so_seqid++;                 \
1346                 stateowner->so_replay.rp_status = nfserr;       \
1347                 stateowner->so_replay.rp_buflen =               \
1348                           (((char *)(resp)->p - (char *)save)); \
1349                 memcpy(stateowner->so_replay.rp_buf, save,      \
1350                         stateowner->so_replay.rp_buflen);       \
1351         } } while (0);
1352
1353
1354 static u32 nfs4_ftypes[16] = {
1355         NF4BAD,  NF4FIFO, NF4CHR, NF4BAD,
1356         NF4DIR,  NF4BAD,  NF4BLK, NF4BAD,
1357         NF4REG,  NF4BAD,  NF4LNK, NF4BAD,
1358         NF4SOCK, NF4BAD,  NF4LNK, NF4BAD,
1359 };
1360
1361 static int
1362 nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1363                         u32 **p, int *buflen)
1364 {
1365         int status;
1366
1367         if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4)
1368                 return nfserr_resource;
1369         if (whotype != NFS4_ACL_WHO_NAMED)
1370                 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
1371         else if (group)
1372                 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
1373         else
1374                 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
1375         if (status < 0)
1376                 return nfserrno(status);
1377         *p = xdr_encode_opaque(*p, NULL, status);
1378         *buflen -= (XDR_QUADLEN(status) << 2) + 4;
1379         BUG_ON(*buflen < 0);
1380         return 0;
1381 }
1382
1383 static inline int
1384 nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, u32 **p, int *buflen)
1385 {
1386         return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
1387 }
1388
1389 static inline int
1390 nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, u32 **p, int *buflen)
1391 {
1392         return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
1393 }
1394
1395 static inline int
1396 nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
1397                 u32 **p, int *buflen)
1398 {
1399         return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
1400 }
1401
1402
1403 /*
1404  * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
1405  * ourselves.
1406  *
1407  * @countp is the buffer size in _words_; upon successful return this becomes
1408  * replaced with the number of words written.
1409  */
1410 int
1411 nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1412                 struct dentry *dentry, u32 *buffer, int *countp, u32 *bmval,
1413                 struct svc_rqst *rqstp)
1414 {
1415         u32 bmval0 = bmval[0];
1416         u32 bmval1 = bmval[1];
1417         struct kstat stat;
1418         struct svc_fh tempfh;
1419         struct kstatfs statfs;
1420         int buflen = *countp << 2;
1421         u32 *attrlenp;
1422         u32 dummy;
1423         u64 dummy64;
1424         u32 *p = buffer;
1425         int status;
1426         int aclsupport = 0;
1427         struct nfs4_acl *acl = NULL;
1428
1429         BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
1430         BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0);
1431         BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1);
1432
1433         status = vfs_getattr(exp->ex_mnt, dentry, &stat);
1434         if (status)
1435                 goto out_nfserr;
1436         if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) ||
1437             (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
1438                        FATTR4_WORD1_SPACE_TOTAL))) {
1439                 status = vfs_statfs(dentry->d_inode->i_sb, &statfs);
1440                 if (status)
1441                         goto out_nfserr;
1442         }
1443         if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
1444                 fh_init(&tempfh, NFS4_FHSIZE);
1445                 status = fh_compose(&tempfh, exp, dentry, NULL);
1446                 if (status)
1447                         goto out;
1448                 fhp = &tempfh;
1449         }
1450         if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT
1451                         | FATTR4_WORD0_SUPPORTED_ATTRS)) {
1452                 status = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
1453                 aclsupport = (status == 0);
1454                 if (bmval0 & FATTR4_WORD0_ACL) {
1455                         if (status == -EOPNOTSUPP)
1456                                 bmval0 &= ~FATTR4_WORD0_ACL;
1457                         else if (status != 0)
1458                                 goto out_nfserr;
1459                 }
1460         }
1461         if ((buflen -= 16) < 0)
1462                 goto out_resource;
1463
1464         WRITE32(2);
1465         WRITE32(bmval0);
1466         WRITE32(bmval1);
1467         attrlenp = p++;                /* to be backfilled later */
1468
1469         if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
1470                 if ((buflen -= 12) < 0)
1471                         goto out_resource;
1472                 WRITE32(2);
1473                 WRITE32(aclsupport ?
1474                         NFSD_SUPPORTED_ATTRS_WORD0 :
1475                         NFSD_SUPPORTED_ATTRS_WORD0 & ~FATTR4_WORD0_ACL);
1476                 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1);
1477         }
1478         if (bmval0 & FATTR4_WORD0_TYPE) {
1479                 if ((buflen -= 4) < 0)
1480                         goto out_resource;
1481                 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12];
1482                 if (dummy == NF4BAD)
1483                         goto out_serverfault;
1484                 WRITE32(dummy);
1485         }
1486         if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
1487                 if ((buflen -= 4) < 0)
1488                         goto out_resource;
1489                 WRITE32( NFS4_FH_NOEXPIRE_WITH_OPEN | NFS4_FH_VOL_RENAME );
1490         }
1491         if (bmval0 & FATTR4_WORD0_CHANGE) {
1492                 /*
1493                  * Note: This _must_ be consistent with the scheme for writing
1494                  * change_info, so any changes made here must be reflected there
1495                  * as well.  (See xdr4.h:set_change_info() and the WRITECINFO()
1496                  * macro above.)
1497                  */
1498                 if ((buflen -= 8) < 0)
1499                         goto out_resource;
1500                 WRITE32(stat.ctime.tv_sec);
1501                 WRITE32(stat.ctime.tv_nsec);
1502         }
1503         if (bmval0 & FATTR4_WORD0_SIZE) {
1504                 if ((buflen -= 8) < 0)
1505                         goto out_resource;
1506                 WRITE64(stat.size);
1507         }
1508         if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
1509                 if ((buflen -= 4) < 0)
1510                         goto out_resource;
1511                 WRITE32(1);
1512         }
1513         if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
1514                 if ((buflen -= 4) < 0)
1515                         goto out_resource;
1516                 WRITE32(1);
1517         }
1518         if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
1519                 if ((buflen -= 4) < 0)
1520                         goto out_resource;
1521                 WRITE32(0);
1522         }
1523         if (bmval0 & FATTR4_WORD0_FSID) {
1524                 if ((buflen -= 16) < 0)
1525                         goto out_resource;
1526                 if (is_fsid(fhp, rqstp->rq_reffh)) {
1527                         WRITE64((u64)exp->ex_fsid);
1528                         WRITE64((u64)0);
1529                 } else {
1530                         WRITE32(0);
1531                         WRITE32(MAJOR(stat.dev));
1532                         WRITE32(0);
1533                         WRITE32(MINOR(stat.dev));
1534                 }
1535         }
1536         if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
1537                 if ((buflen -= 4) < 0)
1538                         goto out_resource;
1539                 WRITE32(0);
1540         }
1541         if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
1542                 if ((buflen -= 4) < 0)
1543                         goto out_resource;
1544                 WRITE32(NFSD_LEASE_TIME);
1545         }
1546         if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
1547                 if ((buflen -= 4) < 0)
1548                         goto out_resource;
1549                 WRITE32(0);
1550         }
1551         if (bmval0 & FATTR4_WORD0_ACL) {
1552                 struct nfs4_ace *ace;
1553                 struct list_head *h;
1554
1555                 if (acl == NULL) {
1556                         if ((buflen -= 4) < 0)
1557                                 goto out_resource;
1558
1559                         WRITE32(0);
1560                         goto out_acl;
1561                 }
1562                 if ((buflen -= 4) < 0)
1563                         goto out_resource;
1564                 WRITE32(acl->naces);
1565
1566                 list_for_each(h, &acl->ace_head) {
1567                         ace = list_entry(h, struct nfs4_ace, l_ace);
1568
1569                         if ((buflen -= 4*3) < 0)
1570                                 goto out_resource;
1571                         WRITE32(ace->type);
1572                         WRITE32(ace->flag);
1573                         WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
1574                         status = nfsd4_encode_aclname(rqstp, ace->whotype,
1575                                 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
1576                                 &p, &buflen);
1577                         if (status == nfserr_resource)
1578                                 goto out_resource;
1579                         if (status)
1580                                 goto out;
1581                 }
1582         }
1583 out_acl:
1584         if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
1585                 if ((buflen -= 4) < 0)
1586                         goto out_resource;
1587                 WRITE32(aclsupport ?
1588                         ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
1589         }
1590         if (bmval0 & FATTR4_WORD0_CANSETTIME) {
1591                 if ((buflen -= 4) < 0)
1592                         goto out_resource;
1593                 WRITE32(1);
1594         }
1595         if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
1596                 if ((buflen -= 4) < 0)
1597                         goto out_resource;
1598                 WRITE32(1);
1599         }
1600         if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
1601                 if ((buflen -= 4) < 0)
1602                         goto out_resource;
1603                 WRITE32(1);
1604         }
1605         if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
1606                 if ((buflen -= 4) < 0)
1607                         goto out_resource;
1608                 WRITE32(1);
1609         }
1610         if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
1611                 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4;
1612                 if (buflen < 0)
1613                         goto out_resource;
1614                 WRITE32(fhp->fh_handle.fh_size);
1615                 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size);
1616         }
1617         if (bmval0 & FATTR4_WORD0_FILEID) {
1618                 if ((buflen -= 8) < 0)
1619                         goto out_resource;
1620                 WRITE64((u64) stat.ino);
1621         }
1622         if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
1623                 if ((buflen -= 8) < 0)
1624                         goto out_resource;
1625                 WRITE64((u64) statfs.f_ffree);
1626         }
1627         if (bmval0 & FATTR4_WORD0_FILES_FREE) {
1628                 if ((buflen -= 8) < 0)
1629                         goto out_resource;
1630                 WRITE64((u64) statfs.f_ffree);
1631         }
1632         if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
1633                 if ((buflen -= 8) < 0)
1634                         goto out_resource;
1635                 WRITE64((u64) statfs.f_files);
1636         }
1637         if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
1638                 if ((buflen -= 4) < 0)
1639                         goto out_resource;
1640                 WRITE32(1);
1641         }
1642         if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
1643                 if ((buflen -= 8) < 0)
1644                         goto out_resource;
1645                 WRITE64(~(u64)0);
1646         }
1647         if (bmval0 & FATTR4_WORD0_MAXLINK) {
1648                 if ((buflen -= 4) < 0)
1649                         goto out_resource;
1650                 WRITE32(255);
1651         }
1652         if (bmval0 & FATTR4_WORD0_MAXNAME) {
1653                 if ((buflen -= 4) < 0)
1654                         goto out_resource;
1655                 WRITE32(~(u32) 0);
1656         }
1657         if (bmval0 & FATTR4_WORD0_MAXREAD) {
1658                 if ((buflen -= 8) < 0)
1659                         goto out_resource;
1660                 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1661         }
1662         if (bmval0 & FATTR4_WORD0_MAXWRITE) {
1663                 if ((buflen -= 8) < 0)
1664                         goto out_resource;
1665                 WRITE64((u64) NFSSVC_MAXBLKSIZE);
1666         }
1667         if (bmval1 & FATTR4_WORD1_MODE) {
1668                 if ((buflen -= 4) < 0)
1669                         goto out_resource;
1670                 WRITE32(stat.mode & S_IALLUGO);
1671         }
1672         if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
1673                 if ((buflen -= 4) < 0)
1674                         goto out_resource;
1675                 WRITE32(1);
1676         }
1677         if (bmval1 & FATTR4_WORD1_NUMLINKS) {
1678                 if ((buflen -= 4) < 0)
1679                         goto out_resource;
1680                 WRITE32(stat.nlink);
1681         }
1682         if (bmval1 & FATTR4_WORD1_OWNER) {
1683                 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen);
1684                 if (status == nfserr_resource)
1685                         goto out_resource;
1686                 if (status)
1687                         goto out;
1688         }
1689         if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
1690                 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen);
1691                 if (status == nfserr_resource)
1692                         goto out_resource;
1693                 if (status)
1694                         goto out;
1695         }
1696         if (bmval1 & FATTR4_WORD1_RAWDEV) {
1697                 if ((buflen -= 8) < 0)
1698                         goto out_resource;
1699                 WRITE32((u32) MAJOR(stat.rdev));
1700                 WRITE32((u32) MINOR(stat.rdev));
1701         }
1702         if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
1703                 if ((buflen -= 8) < 0)
1704                         goto out_resource;
1705                 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
1706                 WRITE64(dummy64);
1707         }
1708         if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
1709                 if ((buflen -= 8) < 0)
1710                         goto out_resource;
1711                 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
1712                 WRITE64(dummy64);
1713         }
1714         if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
1715                 if ((buflen -= 8) < 0)
1716                         goto out_resource;
1717                 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
1718                 WRITE64(dummy64);
1719         }
1720         if (bmval1 & FATTR4_WORD1_SPACE_USED) {
1721                 if ((buflen -= 8) < 0)
1722                         goto out_resource;
1723                 dummy64 = (u64)stat.blocks << 9;
1724                 WRITE64(dummy64);
1725         }
1726         if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
1727                 if ((buflen -= 12) < 0)
1728                         goto out_resource;
1729                 WRITE32(0);
1730                 WRITE32(stat.atime.tv_sec);
1731                 WRITE32(stat.atime.tv_nsec);
1732         }
1733         if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
1734                 if ((buflen -= 12) < 0)
1735                         goto out_resource;
1736                 WRITE32(0);
1737                 WRITE32(1);
1738                 WRITE32(0);
1739         }
1740         if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
1741                 if ((buflen -= 12) < 0)
1742                         goto out_resource;
1743                 WRITE32(0);
1744                 WRITE32(stat.ctime.tv_sec);
1745                 WRITE32(stat.ctime.tv_nsec);
1746         }
1747         if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
1748                 if ((buflen -= 12) < 0)
1749                         goto out_resource;
1750                 WRITE32(0);
1751                 WRITE32(stat.mtime.tv_sec);
1752                 WRITE32(stat.mtime.tv_nsec);
1753         }
1754         if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
1755                 struct dentry *mnt_pnt, *mnt_root;
1756
1757                 if ((buflen -= 8) < 0)
1758                         goto out_resource;
1759                 mnt_root = exp->ex_mnt->mnt_root;
1760                 if (mnt_root->d_inode == dentry->d_inode) {
1761                         mnt_pnt = exp->ex_mnt->mnt_mountpoint;
1762                         WRITE64((u64) mnt_pnt->d_inode->i_ino);
1763                 } else
1764                         WRITE64((u64) stat.ino);
1765         }
1766         *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1767         *countp = p - buffer;
1768         status = nfs_ok;
1769
1770 out:
1771         nfs4_acl_free(acl);
1772         if (fhp == &tempfh)
1773                 fh_put(&tempfh);
1774         return status;
1775 out_nfserr:
1776         status = nfserrno(status);
1777         goto out;
1778 out_resource:
1779         *countp = 0;
1780         status = nfserr_resource;
1781         goto out;
1782 out_serverfault:
1783         status = nfserr_serverfault;
1784         goto out;
1785 }
1786
1787 static int
1788 nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd,
1789                 const char *name, int namlen, u32 *p, int *buflen)
1790 {
1791         struct svc_export *exp = cd->rd_fhp->fh_export;
1792         struct dentry *dentry;
1793         int nfserr;
1794
1795         dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen);
1796         if (IS_ERR(dentry))
1797                 return nfserrno(PTR_ERR(dentry));
1798
1799         exp_get(exp);
1800         if (d_mountpoint(dentry)) {
1801                 if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
1802                 /*
1803                  * -EAGAIN is the only error returned from
1804                  * nfsd_cross_mnt() and it indicates that an
1805                  * up-call has  been initiated to fill in the export
1806                  * options on exp.  When the answer comes back,
1807                  * this call will be retried.
1808                  */
1809                         nfserr = nfserr_dropit;
1810                         goto out_put;
1811                 }
1812
1813         }
1814         nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval,
1815                                         cd->rd_rqstp);
1816 out_put:
1817         dput(dentry);
1818         exp_put(exp);
1819         return nfserr;
1820 }
1821
1822 static u32 *
1823 nfsd4_encode_rdattr_error(u32 *p, int buflen, int nfserr)
1824 {
1825         u32 *attrlenp;
1826
1827         if (buflen < 6)
1828                 return NULL;
1829         *p++ = htonl(2);
1830         *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
1831         *p++ = htonl(0);                         /* bmval1 */
1832
1833         attrlenp = p++;
1834         *p++ = nfserr;       /* no htonl */
1835         *attrlenp = htonl((char *)p - (char *)attrlenp - 4);
1836         return p;
1837 }
1838
1839 static int
1840 nfsd4_encode_dirent(struct readdir_cd *ccd, const char *name, int namlen,
1841                     loff_t offset, ino_t ino, unsigned int d_type)
1842 {
1843         struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
1844         int buflen;
1845         u32 *p = cd->buffer;
1846         int nfserr = nfserr_toosmall;
1847
1848         /* In nfsv4, "." and ".." never make it onto the wire.. */
1849         if (name && isdotent(name, namlen)) {
1850                 cd->common.err = nfs_ok;
1851                 return 0;
1852         }
1853
1854         if (cd->offset)
1855                 xdr_encode_hyper(cd->offset, (u64) offset);
1856
1857         buflen = cd->buflen - 4 - XDR_QUADLEN(namlen);
1858         if (buflen < 0)
1859                 goto fail;
1860
1861         *p++ = xdr_one;                             /* mark entry present */
1862         cd->offset = p;                             /* remember pointer */
1863         p = xdr_encode_hyper(p, NFS_OFFSET_MAX);    /* offset of next entry */
1864         p = xdr_encode_array(p, name, namlen);      /* name length & name */
1865
1866         nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen);
1867         switch (nfserr) {
1868         case nfs_ok:
1869                 p += buflen;
1870                 break;
1871         case nfserr_resource:
1872                 nfserr = nfserr_toosmall;
1873                 goto fail;
1874         case nfserr_dropit:
1875                 goto fail;
1876         default:
1877                 /*
1878                  * If the client requested the RDATTR_ERROR attribute,
1879                  * we stuff the error code into this attribute
1880                  * and continue.  If this attribute was not requested,
1881                  * then in accordance with the spec, we fail the
1882                  * entire READDIR operation(!)
1883                  */
1884                 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
1885                         goto fail;
1886                 nfserr = nfserr_toosmall;
1887                 p = nfsd4_encode_rdattr_error(p, buflen, nfserr);
1888                 if (p == NULL)
1889                         goto fail;
1890         }
1891         cd->buflen -= (p - cd->buffer);
1892         cd->buffer = p;
1893         cd->common.err = nfs_ok;
1894         return 0;
1895 fail:
1896         cd->common.err = nfserr;
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 ? ld->ld_sop->so_owner.len : 0));
1999         WRITE64(ld->ld_start);
2000         WRITE64(ld->ld_length);
2001         WRITE32(ld->ld_type);
2002         if (ld->ld_sop) {
2003                 WRITEMEM(&ld->ld_clientid, 8);
2004                 WRITE32(ld->ld_sop->so_owner.len);
2005                 WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len);
2006                 kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner);
2007         }  else {  /* non - nfsv4 lock in conflict, no clientid nor owner */
2008                 WRITE64((u64)0); /* clientid */
2009                 WRITE32(0); /* length of owner name */
2010         }
2011         ADJUST_ARGS();
2012 }
2013
2014 static void
2015 nfsd4_encode_lock(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lock *lock)
2016 {
2017
2018         ENCODE_SEQID_OP_HEAD;
2019
2020         if (!nfserr) {
2021                 RESERVE_SPACE(4 + sizeof(stateid_t));
2022                 WRITE32(lock->lk_resp_stateid.si_generation);
2023                 WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2024                 ADJUST_ARGS();
2025         } else if (nfserr == nfserr_denied)
2026                 nfsd4_encode_lock_denied(resp, &lock->lk_denied);
2027
2028         ENCODE_SEQID_OP_TAIL(lock->lk_stateowner);
2029 }
2030
2031 static void
2032 nfsd4_encode_lockt(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_lockt *lockt)
2033 {
2034         if (nfserr == nfserr_denied)
2035                 nfsd4_encode_lock_denied(resp, &lockt->lt_denied);
2036 }
2037
2038 static void
2039 nfsd4_encode_locku(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_locku *locku)
2040 {
2041         ENCODE_SEQID_OP_HEAD;
2042
2043         if (!nfserr) {
2044                 RESERVE_SPACE(sizeof(stateid_t));
2045                 WRITE32(locku->lu_stateid.si_generation);
2046                 WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t));
2047                 ADJUST_ARGS();
2048         }
2049                                         
2050         ENCODE_SEQID_OP_TAIL(locku->lu_stateowner);
2051 }
2052
2053
2054 static void
2055 nfsd4_encode_link(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_link *link)
2056 {
2057         ENCODE_HEAD;
2058
2059         if (!nfserr) {
2060                 RESERVE_SPACE(20);
2061                 WRITECINFO(link->li_cinfo);
2062                 ADJUST_ARGS();
2063         }
2064 }
2065
2066
2067 static void
2068 nfsd4_encode_open(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open *open)
2069 {
2070         ENCODE_SEQID_OP_HEAD;
2071
2072         if (nfserr)
2073                 goto out;
2074
2075         RESERVE_SPACE(36 + sizeof(stateid_t));
2076         WRITE32(open->op_stateid.si_generation);
2077         WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t));
2078         WRITECINFO(open->op_cinfo);
2079         WRITE32(open->op_rflags);
2080         WRITE32(2);
2081         WRITE32(open->op_bmval[0]);
2082         WRITE32(open->op_bmval[1]);
2083         WRITE32(open->op_delegate_type);
2084         ADJUST_ARGS();
2085
2086         switch (open->op_delegate_type) {
2087         case NFS4_OPEN_DELEGATE_NONE:
2088                 break;
2089         case NFS4_OPEN_DELEGATE_READ:
2090                 RESERVE_SPACE(20 + sizeof(stateid_t));
2091                 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
2092                 WRITE32(0);
2093
2094                 /*
2095                  * TODO: ACE's in delegations
2096                  */
2097                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2098                 WRITE32(0);
2099                 WRITE32(0);
2100                 WRITE32(0);   /* XXX: is NULL principal ok? */
2101                 ADJUST_ARGS();
2102                 break;
2103         case NFS4_OPEN_DELEGATE_WRITE:
2104                 RESERVE_SPACE(32 + sizeof(stateid_t));
2105                 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t));
2106                 WRITE32(0);
2107
2108                 /*
2109                  * TODO: space_limit's in delegations
2110                  */
2111                 WRITE32(NFS4_LIMIT_SIZE);
2112                 WRITE32(~(u32)0);
2113                 WRITE32(~(u32)0);
2114
2115                 /*
2116                  * TODO: ACE's in delegations
2117                  */
2118                 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
2119                 WRITE32(0);
2120                 WRITE32(0);
2121                 WRITE32(0);   /* XXX: is NULL principal ok? */
2122                 ADJUST_ARGS();
2123                 break;
2124         default:
2125                 BUG();
2126         }
2127         /* XXX save filehandle here */
2128 out:
2129         ENCODE_SEQID_OP_TAIL(open->op_stateowner);
2130 }
2131
2132 static void
2133 nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_confirm *oc)
2134 {
2135         ENCODE_SEQID_OP_HEAD;
2136                                         
2137         if (!nfserr) {
2138                 RESERVE_SPACE(sizeof(stateid_t));
2139                 WRITE32(oc->oc_resp_stateid.si_generation);
2140                 WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t));
2141                 ADJUST_ARGS();
2142         }
2143
2144         ENCODE_SEQID_OP_TAIL(oc->oc_stateowner);
2145 }
2146
2147 static void
2148 nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_open_downgrade *od)
2149 {
2150         ENCODE_SEQID_OP_HEAD;
2151                                         
2152         if (!nfserr) {
2153                 RESERVE_SPACE(sizeof(stateid_t));
2154                 WRITE32(od->od_stateid.si_generation);
2155                 WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t));
2156                 ADJUST_ARGS();
2157         }
2158
2159         ENCODE_SEQID_OP_TAIL(od->od_stateowner);
2160 }
2161
2162 static int
2163 nfsd4_encode_read(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_read *read)
2164 {
2165         u32 eof;
2166         int v, pn;
2167         unsigned long maxcount; 
2168         long len;
2169         ENCODE_HEAD;
2170
2171         if (nfserr)
2172                 return nfserr;
2173         if (resp->xbuf->page_len)
2174                 return nfserr_resource;
2175
2176         RESERVE_SPACE(8); /* eof flag and byte count */
2177
2178         maxcount = NFSSVC_MAXBLKSIZE;
2179         if (maxcount > read->rd_length)
2180                 maxcount = read->rd_length;
2181
2182         len = maxcount;
2183         v = 0;
2184         while (len > 0) {
2185                 pn = resp->rqstp->rq_resused;
2186                 svc_take_page(resp->rqstp);
2187                 read->rd_iov[v].iov_base = page_address(resp->rqstp->rq_respages[pn]);
2188                 read->rd_iov[v].iov_len = len < PAGE_SIZE ? len : PAGE_SIZE;
2189                 v++;
2190                 len -= PAGE_SIZE;
2191         }
2192         read->rd_vlen = v;
2193
2194         nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp,
2195                            read->rd_offset,
2196                            read->rd_iov, read->rd_vlen,
2197                            &maxcount);
2198         if (nfserr == nfserr_symlink)
2199                 nfserr = nfserr_inval;
2200         if (nfserr)
2201                 return nfserr;
2202         eof = (read->rd_offset + maxcount >= read->rd_fhp->fh_dentry->d_inode->i_size);
2203
2204         WRITE32(eof);
2205         WRITE32(maxcount);
2206         ADJUST_ARGS();
2207         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2208
2209         resp->xbuf->page_len = maxcount;
2210
2211         /* read zero bytes -> don't set up tail */
2212         if(!maxcount)
2213                 return 0;        
2214
2215         /* set up page for remaining responses */
2216         svc_take_page(resp->rqstp);
2217         resp->xbuf->tail[0].iov_base = 
2218                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2219         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2220         resp->xbuf->tail[0].iov_len = 0;
2221         resp->p = resp->xbuf->tail[0].iov_base;
2222         resp->end = resp->p + PAGE_SIZE/4;
2223
2224         if (maxcount&3) {
2225                 *(resp->p)++ = 0;
2226                 resp->xbuf->tail[0].iov_base += maxcount&3;
2227                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2228         }
2229         return 0;
2230 }
2231
2232 static int
2233 nfsd4_encode_readlink(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readlink *readlink)
2234 {
2235         int maxcount;
2236         char *page;
2237         ENCODE_HEAD;
2238
2239         if (nfserr)
2240                 return nfserr;
2241         if (resp->xbuf->page_len)
2242                 return nfserr_resource;
2243
2244         svc_take_page(resp->rqstp);
2245         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2246
2247         maxcount = PAGE_SIZE;
2248         RESERVE_SPACE(4);
2249
2250         /*
2251          * XXX: By default, the ->readlink() VFS op will truncate symlinks
2252          * if they would overflow the buffer.  Is this kosher in NFSv4?  If
2253          * not, one easy fix is: if ->readlink() precisely fills the buffer,
2254          * assume that truncation occurred, and return NFS4ERR_RESOURCE.
2255          */
2256         nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount);
2257         if (nfserr == nfserr_isdir)
2258                 return nfserr_inval;
2259         if (nfserr)
2260                 return nfserr;
2261
2262         WRITE32(maxcount);
2263         ADJUST_ARGS();
2264         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2265
2266         svc_take_page(resp->rqstp);
2267         resp->xbuf->tail[0].iov_base = 
2268                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2269         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2270         resp->xbuf->tail[0].iov_len = 0;
2271         resp->p = resp->xbuf->tail[0].iov_base;
2272         resp->end = resp->p + PAGE_SIZE/4;
2273
2274         resp->xbuf->page_len = maxcount;
2275         if (maxcount&3) {
2276                 *(resp->p)++ = 0;
2277                 resp->xbuf->tail[0].iov_base += maxcount&3;
2278                 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3);
2279         }
2280         return 0;
2281 }
2282
2283 static int
2284 nfsd4_encode_readdir(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_readdir *readdir)
2285 {
2286         int maxcount;
2287         loff_t offset;
2288         u32 *page, *savep;
2289         ENCODE_HEAD;
2290
2291         if (nfserr)
2292                 return nfserr;
2293         if (resp->xbuf->page_len)
2294                 return nfserr_resource;
2295
2296         RESERVE_SPACE(8);  /* verifier */
2297         savep = p;
2298
2299         /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
2300         WRITE32(0);
2301         WRITE32(0);
2302         ADJUST_ARGS();
2303         resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base;
2304
2305         maxcount = PAGE_SIZE;
2306         if (maxcount > readdir->rd_maxcount)
2307                 maxcount = readdir->rd_maxcount;
2308
2309         /*
2310          * Convert from bytes to words, account for the two words already
2311          * written, make sure to leave two words at the end for the next
2312          * pointer and eof field.
2313          */
2314         maxcount = (maxcount >> 2) - 4;
2315         if (maxcount < 0) {
2316                 nfserr =  nfserr_toosmall;
2317                 goto err_no_verf;
2318         }
2319
2320         svc_take_page(resp->rqstp);
2321         page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2322         readdir->common.err = 0;
2323         readdir->buflen = maxcount;
2324         readdir->buffer = page;
2325         readdir->offset = NULL;
2326
2327         offset = readdir->rd_cookie;
2328         nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
2329                               &offset,
2330                               &readdir->common, nfsd4_encode_dirent);
2331         if (nfserr == nfs_ok &&
2332             readdir->common.err == nfserr_toosmall &&
2333             readdir->buffer == page) 
2334                 nfserr = nfserr_toosmall;
2335         if (nfserr == nfserr_symlink)
2336                 nfserr = nfserr_notdir;
2337         if (nfserr)
2338                 goto err_no_verf;
2339
2340         if (readdir->offset)
2341                 xdr_encode_hyper(readdir->offset, offset);
2342
2343         p = readdir->buffer;
2344         *p++ = 0;       /* no more entries */
2345         *p++ = htonl(readdir->common.err == nfserr_eof);
2346         resp->xbuf->page_len = ((char*)p) - (char*)page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2347
2348         /* allocate a page for the tail */
2349         svc_take_page(resp->rqstp);
2350         resp->xbuf->tail[0].iov_base = 
2351                 page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]);
2352         resp->rqstp->rq_restailpage = resp->rqstp->rq_resused-1;
2353         resp->xbuf->tail[0].iov_len = 0;
2354         resp->p = resp->xbuf->tail[0].iov_base;
2355         resp->end = resp->p + PAGE_SIZE/4;
2356
2357         return 0;
2358 err_no_verf:
2359         p = savep;
2360         ADJUST_ARGS();
2361         return nfserr;
2362 }
2363
2364 static void
2365 nfsd4_encode_remove(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_remove *remove)
2366 {
2367         ENCODE_HEAD;
2368
2369         if (!nfserr) {
2370                 RESERVE_SPACE(20);
2371                 WRITECINFO(remove->rm_cinfo);
2372                 ADJUST_ARGS();
2373         }
2374 }
2375
2376 static void
2377 nfsd4_encode_rename(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_rename *rename)
2378 {
2379         ENCODE_HEAD;
2380
2381         if (!nfserr) {
2382                 RESERVE_SPACE(40);
2383                 WRITECINFO(rename->rn_sinfo);
2384                 WRITECINFO(rename->rn_tinfo);
2385                 ADJUST_ARGS();
2386         }
2387 }
2388
2389 /*
2390  * The SETATTR encode routine is special -- it always encodes a bitmap,
2391  * regardless of the error status.
2392  */
2393 static void
2394 nfsd4_encode_setattr(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setattr *setattr)
2395 {
2396         ENCODE_HEAD;
2397
2398         RESERVE_SPACE(12);
2399         if (nfserr) {
2400                 WRITE32(2);
2401                 WRITE32(0);
2402                 WRITE32(0);
2403         }
2404         else {
2405                 WRITE32(2);
2406                 WRITE32(setattr->sa_bmval[0]);
2407                 WRITE32(setattr->sa_bmval[1]);
2408         }
2409         ADJUST_ARGS();
2410 }
2411
2412 static void
2413 nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_setclientid *scd)
2414 {
2415         ENCODE_HEAD;
2416
2417         if (!nfserr) {
2418                 RESERVE_SPACE(8 + sizeof(nfs4_verifier));
2419                 WRITEMEM(&scd->se_clientid, 8);
2420                 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier));
2421                 ADJUST_ARGS();
2422         }
2423         else if (nfserr == nfserr_clid_inuse) {
2424                 RESERVE_SPACE(8);
2425                 WRITE32(0);
2426                 WRITE32(0);
2427                 ADJUST_ARGS();
2428         }
2429 }
2430
2431 static void
2432 nfsd4_encode_write(struct nfsd4_compoundres *resp, int nfserr, struct nfsd4_write *write)
2433 {
2434         ENCODE_HEAD;
2435
2436         if (!nfserr) {
2437                 RESERVE_SPACE(16);
2438                 WRITE32(write->wr_bytes_written);
2439                 WRITE32(write->wr_how_written);
2440                 WRITEMEM(write->wr_verifier.data, 8);
2441                 ADJUST_ARGS();
2442         }
2443 }
2444
2445 void
2446 nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2447 {
2448         u32 *statp;
2449         ENCODE_HEAD;
2450
2451         RESERVE_SPACE(8);
2452         WRITE32(op->opnum);
2453         statp = p++;    /* to be backfilled at the end */
2454         ADJUST_ARGS();
2455
2456         switch (op->opnum) {
2457         case OP_ACCESS:
2458                 nfsd4_encode_access(resp, op->status, &op->u.access);
2459                 break;
2460         case OP_CLOSE:
2461                 nfsd4_encode_close(resp, op->status, &op->u.close);
2462                 break;
2463         case OP_COMMIT:
2464                 nfsd4_encode_commit(resp, op->status, &op->u.commit);
2465                 break;
2466         case OP_CREATE:
2467                 nfsd4_encode_create(resp, op->status, &op->u.create);
2468                 break;
2469         case OP_DELEGRETURN:
2470                 break;
2471         case OP_GETATTR:
2472                 op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr);
2473                 break;
2474         case OP_GETFH:
2475                 nfsd4_encode_getfh(resp, op->status, op->u.getfh);
2476                 break;
2477         case OP_LINK:
2478                 nfsd4_encode_link(resp, op->status, &op->u.link);
2479                 break;
2480         case OP_LOCK:
2481                 nfsd4_encode_lock(resp, op->status, &op->u.lock);
2482                 break;
2483         case OP_LOCKT:
2484                 nfsd4_encode_lockt(resp, op->status, &op->u.lockt);
2485                 break;
2486         case OP_LOCKU:
2487                 nfsd4_encode_locku(resp, op->status, &op->u.locku);
2488                 break;
2489         case OP_LOOKUP:
2490                 break;
2491         case OP_LOOKUPP:
2492                 break;
2493         case OP_NVERIFY:
2494                 break;
2495         case OP_OPEN:
2496                 nfsd4_encode_open(resp, op->status, &op->u.open);
2497                 break;
2498         case OP_OPEN_CONFIRM:
2499                 nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm);
2500                 break;
2501         case OP_OPEN_DOWNGRADE:
2502                 nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade);
2503                 break;
2504         case OP_PUTFH:
2505                 break;
2506         case OP_PUTROOTFH:
2507                 break;
2508         case OP_READ:
2509                 op->status = nfsd4_encode_read(resp, op->status, &op->u.read);
2510                 break;
2511         case OP_READDIR:
2512                 op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir);
2513                 break;
2514         case OP_READLINK:
2515                 op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink);
2516                 break;
2517         case OP_REMOVE:
2518                 nfsd4_encode_remove(resp, op->status, &op->u.remove);
2519                 break;
2520         case OP_RENAME:
2521                 nfsd4_encode_rename(resp, op->status, &op->u.rename);
2522                 break;
2523         case OP_RENEW:
2524                 break;
2525         case OP_RESTOREFH:
2526                 break;
2527         case OP_SAVEFH:
2528                 break;
2529         case OP_SETATTR:
2530                 nfsd4_encode_setattr(resp, op->status, &op->u.setattr);
2531                 break;
2532         case OP_SETCLIENTID:
2533                 nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid);
2534                 break;
2535         case OP_SETCLIENTID_CONFIRM:
2536                 break;
2537         case OP_VERIFY:
2538                 break;
2539         case OP_WRITE:
2540                 nfsd4_encode_write(resp, op->status, &op->u.write);
2541                 break;
2542         case OP_RELEASE_LOCKOWNER:
2543                 break;
2544         default:
2545                 break;
2546         }
2547
2548         /*
2549          * Note: We write the status directly, instead of using WRITE32(),
2550          * since it is already in network byte order.
2551          */
2552         *statp = op->status;
2553 }
2554
2555 /* 
2556  * Encode the reply stored in the stateowner reply cache 
2557  * 
2558  * XDR note: do not encode rp->rp_buflen: the buffer contains the
2559  * previously sent already encoded operation.
2560  *
2561  * called with nfs4_lock_state() held
2562  */
2563 void
2564 nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
2565 {
2566         ENCODE_HEAD;
2567         struct nfs4_replay *rp = op->replay;
2568
2569         BUG_ON(!rp);
2570
2571         RESERVE_SPACE(8);
2572         WRITE32(op->opnum);
2573         *p++ = rp->rp_status;  /* already xdr'ed */
2574         ADJUST_ARGS();
2575
2576         RESERVE_SPACE(rp->rp_buflen);
2577         WRITEMEM(rp->rp_buf, rp->rp_buflen);
2578         ADJUST_ARGS();
2579 }
2580
2581 /*
2582  * END OF "GENERIC" ENCODE ROUTINES.
2583  */
2584
2585 int
2586 nfs4svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
2587 {
2588         return xdr_ressize_check(rqstp, p);
2589 }
2590
2591 void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args)
2592 {
2593         if (args->ops != args->iops) {
2594                 kfree(args->ops);
2595                 args->ops = args->iops;
2596         }
2597         if (args->tmpp) {
2598                 kfree(args->tmpp);
2599                 args->tmpp = NULL;
2600         }
2601         while (args->to_free) {
2602                 struct tmpbuf *tb = args->to_free;
2603                 args->to_free = tb->next;
2604                 tb->release(tb->buf);
2605                 kfree(tb);
2606         }
2607 }
2608
2609 int
2610 nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundargs *args)
2611 {
2612         int status;
2613
2614         args->p = p;
2615         args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
2616         args->pagelist = rqstp->rq_arg.pages;
2617         args->pagelen = rqstp->rq_arg.page_len;
2618         args->tmpp = NULL;
2619         args->to_free = NULL;
2620         args->ops = args->iops;
2621         args->rqstp = rqstp;
2622
2623         status = nfsd4_decode_compound(args);
2624         if (status) {
2625                 nfsd4_release_compoundargs(args);
2626         }
2627         return !status;
2628 }
2629
2630 int
2631 nfs4svc_encode_compoundres(struct svc_rqst *rqstp, u32 *p, struct nfsd4_compoundres *resp)
2632 {
2633         /*
2634          * All that remains is to write the tag and operation count...
2635          */
2636         struct kvec *iov;
2637         p = resp->tagp;
2638         *p++ = htonl(resp->taglen);
2639         memcpy(p, resp->tag, resp->taglen);
2640         p += XDR_QUADLEN(resp->taglen);
2641         *p++ = htonl(resp->opcnt);
2642
2643         if (rqstp->rq_res.page_len) 
2644                 iov = &rqstp->rq_res.tail[0];
2645         else
2646                 iov = &rqstp->rq_res.head[0];
2647         iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
2648         BUG_ON(iov->iov_len > PAGE_SIZE);
2649         return 1;
2650 }
2651
2652 /*
2653  * Local variables:
2654  *  c-basic-offset: 8
2655  * End:
2656  */