]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/nfsd/nfs4xdr.c
sunrpc: use DEFINE_SPINLOCK()
[mirror_ubuntu-artful-kernel.git] / fs / nfsd / nfs4xdr.c
CommitLineData
1da177e4 1/*
1da177e4
LT
2 * Server-side XDR for NFSv4
3 *
4 * Copyright (c) 2002 The Regents of the University of Michigan.
5 * All rights reserved.
6 *
7 * Kendrick Smith <kmsmith@umich.edu>
8 * Andy Adamson <andros@umich.edu>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
24 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
30 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1da177e4
LT
34 */
35
96bcad50 36#include <linux/file.h>
5a0e3ad6 37#include <linux/slab.h>
1da177e4 38#include <linux/namei.h>
341eb184 39#include <linux/statfs.h>
0733d213 40#include <linux/utsname.h>
17456804 41#include <linux/pagemap.h>
4796f457 42#include <linux/sunrpc/svcauth_gss.h>
9a74af21 43
2ca72e17
BF
44#include "idmap.h"
45#include "acl.h"
9a74af21 46#include "xdr4.h"
0a3adade 47#include "vfs.h"
17456804 48#include "state.h"
1091006c 49#include "cache.h"
3d733711 50#include "netns.h"
9cf514cc 51#include "pnfs.h"
2ca72e17 52
18032ca0
DQ
53#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
54#include <linux/security.h>
55#endif
56
57
1da177e4
LT
58#define NFSDDBG_FACILITY NFSDDBG_XDR
59
916d2d84
BF
60u32 nfsd_suppattrs[3][3] = {
61 {NFSD4_SUPPORTED_ATTRS_WORD0,
62 NFSD4_SUPPORTED_ATTRS_WORD1,
63 NFSD4_SUPPORTED_ATTRS_WORD2},
64
65 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
66 NFSD4_1_SUPPORTED_ATTRS_WORD1,
67 NFSD4_1_SUPPORTED_ATTRS_WORD2},
68
69 {NFSD4_1_SUPPORTED_ATTRS_WORD0,
70 NFSD4_1_SUPPORTED_ATTRS_WORD1,
71 NFSD4_2_SUPPORTED_ATTRS_WORD2},
72};
73
42ca0993
BF
74/*
75 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing
76 * directory in order to indicate to the client that a filesystem boundary is present
77 * We use a fixed fsid for a referral
78 */
79#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL
80#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL
81
b37ad28b 82static __be32
a36b1725 83check_filename(char *str, int len)
1da177e4
LT
84{
85 int i;
86
87 if (len == 0)
88 return nfserr_inval;
89 if (isdotent(str, len))
a36b1725 90 return nfserr_badname;
1da177e4
LT
91 for (i = 0; i < len; i++)
92 if (str[i] == '/')
a36b1725 93 return nfserr_badname;
1da177e4
LT
94 return 0;
95}
96
1da177e4 97#define DECODE_HEAD \
2ebbc012 98 __be32 *p; \
b37ad28b 99 __be32 status
1da177e4
LT
100#define DECODE_TAIL \
101 status = 0; \
102out: \
103 return status; \
104xdr_error: \
817cb9d4
CL
105 dprintk("NFSD: xdr error (%s:%d)\n", \
106 __FILE__, __LINE__); \
1da177e4
LT
107 status = nfserr_bad_xdr; \
108 goto out
109
1da177e4
LT
110#define READMEM(x,nbytes) do { \
111 x = (char *)p; \
112 p += XDR_QUADLEN(nbytes); \
113} while (0)
114#define SAVEMEM(x,nbytes) do { \
115 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \
116 savemem(argp, p, nbytes) : \
117 (char *)p)) { \
817cb9d4
CL
118 dprintk("NFSD: xdr error (%s:%d)\n", \
119 __FILE__, __LINE__); \
1da177e4
LT
120 goto xdr_error; \
121 } \
122 p += XDR_QUADLEN(nbytes); \
123} while (0)
124#define COPYMEM(x,nbytes) do { \
125 memcpy((x), p, nbytes); \
126 p += XDR_QUADLEN(nbytes); \
127} while (0)
128
129/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */
130#define READ_BUF(nbytes) do { \
131 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \
132 p = argp->p; \
133 argp->p += XDR_QUADLEN(nbytes); \
134 } else if (!(p = read_buf(argp, nbytes))) { \
817cb9d4
CL
135 dprintk("NFSD: xdr error (%s:%d)\n", \
136 __FILE__, __LINE__); \
1da177e4
LT
137 goto xdr_error; \
138 } \
139} while (0)
140
590b7431
BF
141static void next_decode_page(struct nfsd4_compoundargs *argp)
142{
590b7431 143 argp->p = page_address(argp->pagelist[0]);
365da4ad 144 argp->pagelist++;
590b7431
BF
145 if (argp->pagelen < PAGE_SIZE) {
146 argp->end = argp->p + (argp->pagelen>>2);
147 argp->pagelen = 0;
148 } else {
149 argp->end = argp->p + (PAGE_SIZE>>2);
150 argp->pagelen -= PAGE_SIZE;
151 }
152}
153
ca2a05aa 154static __be32 *read_buf(struct nfsd4_compoundargs *argp, u32 nbytes)
1da177e4
LT
155{
156 /* We want more bytes than seem to be available.
157 * Maybe we need a new page, maybe we have just run out
158 */
ca2a05aa 159 unsigned int avail = (char *)argp->end - (char *)argp->p;
2ebbc012 160 __be32 *p;
1da177e4
LT
161 if (avail + argp->pagelen < nbytes)
162 return NULL;
163 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */
164 return NULL;
165 /* ok, we can do it with the current plus the next page */
166 if (nbytes <= sizeof(argp->tmp))
167 p = argp->tmp;
168 else {
f99d49ad 169 kfree(argp->tmpp);
1da177e4
LT
170 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL);
171 if (!p)
172 return NULL;
173
174 }
ca2a05aa
BF
175 /*
176 * The following memcpy is safe because read_buf is always
177 * called with nbytes > avail, and the two cases above both
178 * guarantee p points to at least nbytes bytes.
179 */
1da177e4 180 memcpy(p, argp->p, avail);
590b7431 181 next_decode_page(argp);
1da177e4
LT
182 memcpy(((char*)p)+avail, argp->p, (nbytes - avail));
183 argp->p += XDR_QUADLEN(nbytes - avail);
184 return p;
185}
186
60adfc50
AA
187static int zero_clientid(clientid_t *clid)
188{
189 return (clid->cl_boot == 0) && (clid->cl_id == 0);
190}
191
2d8498db 192/**
d5e23383 193 * svcxdr_tmpalloc - allocate memory to be freed after compound processing
ce043ac8
BF
194 * @argp: NFSv4 compound argument structure
195 * @p: pointer to be freed (with kfree())
2d8498db
CH
196 *
197 * Marks @p to be freed when processing the compound operation
198 * described in @argp finishes.
199 */
d5e23383
BF
200static void *
201svcxdr_tmpalloc(struct nfsd4_compoundargs *argp, u32 len)
1da177e4 202{
d5e23383 203 struct svcxdr_tmpbuf *tb;
1da177e4 204
d5e23383 205 tb = kmalloc(sizeof(*tb) + len, GFP_KERNEL);
1da177e4 206 if (!tb)
d5e23383 207 return NULL;
1da177e4
LT
208 tb->next = argp->to_free;
209 argp->to_free = tb;
d5e23383 210 return tb->buf;
1da177e4
LT
211}
212
29c353b3
BF
213/*
214 * For xdr strings that need to be passed to other kernel api's
215 * as null-terminated strings.
216 *
217 * Note null-terminating in place usually isn't safe since the
218 * buffer might end on a page boundary.
219 */
220static char *
221svcxdr_dupstr(struct nfsd4_compoundargs *argp, void *buf, u32 len)
222{
d5e23383 223 char *p = svcxdr_tmpalloc(argp, len + 1);
29c353b3
BF
224
225 if (!p)
226 return NULL;
227 memcpy(p, buf, len);
228 p[len] = '\0';
29c353b3 229 return p;
1da177e4
LT
230}
231
2d8498db
CH
232/**
233 * savemem - duplicate a chunk of memory for later processing
234 * @argp: NFSv4 compound argument structure to be freed with
235 * @p: pointer to be duplicated
236 * @nbytes: length to be duplicated
237 *
238 * Returns a pointer to a copy of @nbytes bytes of memory at @p
239 * that are preserved until processing of the NFSv4 compound
240 * operation described by @argp finishes.
241 */
2ebbc012 242static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes)
1da177e4 243{
d5e23383
BF
244 void *ret;
245
246 ret = svcxdr_tmpalloc(argp, nbytes);
247 if (!ret)
1da177e4 248 return NULL;
d5e23383
BF
249 memcpy(ret, p, nbytes);
250 return ret;
1da177e4
LT
251}
252
4c94e13e
CH
253/*
254 * We require the high 32 bits of 'seconds' to be 0, and
255 * we ignore all 32 bits of 'nseconds'.
256 */
257static __be32
258nfsd4_decode_time(struct nfsd4_compoundargs *argp, struct timespec *tv)
259{
260 DECODE_HEAD;
261 u64 sec;
262
263 READ_BUF(12);
264 p = xdr_decode_hyper(p, &sec);
265 tv->tv_sec = sec;
266 tv->tv_nsec = be32_to_cpup(p++);
267 if (tv->tv_nsec >= (u32)1000000000)
268 return nfserr_inval;
269
270 DECODE_TAIL;
271}
272
b37ad28b 273static __be32
1da177e4
LT
274nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval)
275{
276 u32 bmlen;
277 DECODE_HEAD;
278
279 bmval[0] = 0;
280 bmval[1] = 0;
7e705706 281 bmval[2] = 0;
1da177e4
LT
282
283 READ_BUF(4);
06553991 284 bmlen = be32_to_cpup(p++);
1da177e4
LT
285 if (bmlen > 1000)
286 goto xdr_error;
287
288 READ_BUF(bmlen << 2);
289 if (bmlen > 0)
06553991 290 bmval[0] = be32_to_cpup(p++);
1da177e4 291 if (bmlen > 1)
06553991 292 bmval[1] = be32_to_cpup(p++);
7e705706 293 if (bmlen > 2)
06553991 294 bmval[2] = be32_to_cpup(p++);
1da177e4
LT
295
296 DECODE_TAIL;
297}
298
b37ad28b 299static __be32
3c8e0316 300nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval,
18032ca0
DQ
301 struct iattr *iattr, struct nfs4_acl **acl,
302 struct xdr_netobj *label)
1da177e4
LT
303{
304 int expected_len, len = 0;
305 u32 dummy32;
306 char *buf;
307
308 DECODE_HEAD;
309 iattr->ia_valid = 0;
310 if ((status = nfsd4_decode_bitmap(argp, bmval)))
311 return status;
312
e864c189
BF
313 if (bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0
314 || bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1
315 || bmval[2] & ~NFSD_WRITEABLE_ATTRS_WORD2) {
316 if (nfsd_attrs_supported(argp->minorversion, bmval))
317 return nfserr_inval;
318 return nfserr_attrnotsupp;
319 }
320
1da177e4 321 READ_BUF(4);
06553991 322 expected_len = be32_to_cpup(p++);
1da177e4
LT
323
324 if (bmval[0] & FATTR4_WORD0_SIZE) {
325 READ_BUF(8);
326 len += 8;
542d1ab3 327 p = xdr_decode_hyper(p, &iattr->ia_size);
1da177e4
LT
328 iattr->ia_valid |= ATTR_SIZE;
329 }
330 if (bmval[0] & FATTR4_WORD0_ACL) {
64a817cf 331 u32 nace;
28e05dd8 332 struct nfs4_ace *ace;
1da177e4
LT
333
334 READ_BUF(4); len += 4;
06553991 335 nace = be32_to_cpup(p++);
1da177e4 336
28e05dd8 337 if (nace > NFS4_ACL_MAX)
798df338 338 return nfserr_fbig;
28e05dd8 339
d5e23383 340 *acl = svcxdr_tmpalloc(argp, nfs4_acl_bytes(nace));
eba1c99c
KM
341 if (*acl == NULL)
342 return nfserr_jukebox;
343
28e05dd8
BF
344 (*acl)->naces = nace;
345 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
1da177e4 346 READ_BUF(16); len += 16;
06553991
BF
347 ace->type = be32_to_cpup(p++);
348 ace->flag = be32_to_cpup(p++);
349 ace->access_mask = be32_to_cpup(p++);
350 dummy32 = be32_to_cpup(p++);
1da177e4
LT
351 READ_BUF(dummy32);
352 len += XDR_QUADLEN(dummy32) << 2;
353 READMEM(buf, dummy32);
28e05dd8 354 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
3c726023 355 status = nfs_ok;
28e05dd8 356 if (ace->whotype != NFS4_ACL_WHO_NAMED)
ab8e4aee 357 ;
28e05dd8 358 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
3c726023 359 status = nfsd_map_name_to_gid(argp->rqstp,
ab8e4aee 360 buf, dummy32, &ace->who_gid);
1da177e4 361 else
3c726023 362 status = nfsd_map_name_to_uid(argp->rqstp,
ab8e4aee 363 buf, dummy32, &ace->who_uid);
3c726023
BF
364 if (status)
365 return status;
1da177e4
LT
366 }
367 } else
368 *acl = NULL;
369 if (bmval[1] & FATTR4_WORD1_MODE) {
370 READ_BUF(4);
371 len += 4;
06553991 372 iattr->ia_mode = be32_to_cpup(p++);
1da177e4
LT
373 iattr->ia_mode &= (S_IFMT | S_IALLUGO);
374 iattr->ia_valid |= ATTR_MODE;
375 }
376 if (bmval[1] & FATTR4_WORD1_OWNER) {
377 READ_BUF(4);
378 len += 4;
06553991 379 dummy32 = be32_to_cpup(p++);
1da177e4
LT
380 READ_BUF(dummy32);
381 len += (XDR_QUADLEN(dummy32) << 2);
382 READMEM(buf, dummy32);
47c85291
N
383 if ((status = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid)))
384 return status;
1da177e4
LT
385 iattr->ia_valid |= ATTR_UID;
386 }
387 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) {
388 READ_BUF(4);
389 len += 4;
06553991 390 dummy32 = be32_to_cpup(p++);
1da177e4
LT
391 READ_BUF(dummy32);
392 len += (XDR_QUADLEN(dummy32) << 2);
393 READMEM(buf, dummy32);
47c85291
N
394 if ((status = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid)))
395 return status;
1da177e4
LT
396 iattr->ia_valid |= ATTR_GID;
397 }
398 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
399 READ_BUF(4);
400 len += 4;
06553991 401 dummy32 = be32_to_cpup(p++);
1da177e4
LT
402 switch (dummy32) {
403 case NFS4_SET_TO_CLIENT_TIME:
1da177e4 404 len += 12;
4c94e13e
CH
405 status = nfsd4_decode_time(argp, &iattr->ia_atime);
406 if (status)
407 return status;
1da177e4
LT
408 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
409 break;
410 case NFS4_SET_TO_SERVER_TIME:
411 iattr->ia_valid |= ATTR_ATIME;
412 break;
413 default:
414 goto xdr_error;
415 }
416 }
1da177e4
LT
417 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
418 READ_BUF(4);
419 len += 4;
06553991 420 dummy32 = be32_to_cpup(p++);
1da177e4
LT
421 switch (dummy32) {
422 case NFS4_SET_TO_CLIENT_TIME:
1da177e4 423 len += 12;
4c94e13e
CH
424 status = nfsd4_decode_time(argp, &iattr->ia_mtime);
425 if (status)
426 return status;
1da177e4
LT
427 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
428 break;
429 case NFS4_SET_TO_SERVER_TIME:
430 iattr->ia_valid |= ATTR_MTIME;
431 break;
432 default:
433 goto xdr_error;
434 }
435 }
18032ca0
DQ
436
437 label->len = 0;
438#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
439 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
440 READ_BUF(4);
441 len += 4;
06553991 442 dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */
18032ca0
DQ
443 READ_BUF(4);
444 len += 4;
06553991 445 dummy32 = be32_to_cpup(p++); /* pi: we don't use it either */
18032ca0
DQ
446 READ_BUF(4);
447 len += 4;
06553991 448 dummy32 = be32_to_cpup(p++);
18032ca0 449 READ_BUF(dummy32);
1ec8c0c4 450 if (dummy32 > NFS4_MAXLABELLEN)
18032ca0
DQ
451 return nfserr_badlabel;
452 len += (XDR_QUADLEN(dummy32) << 2);
453 READMEM(buf, dummy32);
29c353b3
BF
454 label->len = dummy32;
455 label->data = svcxdr_dupstr(argp, buf, dummy32);
18032ca0
DQ
456 if (!label->data)
457 return nfserr_jukebox;
18032ca0
DQ
458 }
459#endif
e864c189 460 if (len != expected_len)
1da177e4
LT
461 goto xdr_error;
462
463 DECODE_TAIL;
1da177e4
LT
464}
465
e31a1b66
BH
466static __be32
467nfsd4_decode_stateid(struct nfsd4_compoundargs *argp, stateid_t *sid)
468{
469 DECODE_HEAD;
470
471 READ_BUF(sizeof(stateid_t));
06553991 472 sid->si_generation = be32_to_cpup(p++);
e31a1b66
BH
473 COPYMEM(&sid->si_opaque, sizeof(stateid_opaque_t));
474
475 DECODE_TAIL;
476}
477
b37ad28b 478static __be32
1da177e4
LT
479nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access)
480{
481 DECODE_HEAD;
482
483 READ_BUF(4);
06553991 484 access->ac_req_access = be32_to_cpup(p++);
1da177e4
LT
485
486 DECODE_TAIL;
487}
488
acb2887e
BF
489static __be32 nfsd4_decode_cb_sec(struct nfsd4_compoundargs *argp, struct nfsd4_cb_sec *cbs)
490{
491 DECODE_HEAD;
12fc3e92 492 u32 dummy, uid, gid;
acb2887e
BF
493 char *machine_name;
494 int i;
495 int nr_secflavs;
496
497 /* callback_sec_params4 */
498 READ_BUF(4);
06553991 499 nr_secflavs = be32_to_cpup(p++);
57569a70
BF
500 if (nr_secflavs)
501 cbs->flavor = (u32)(-1);
502 else
503 /* Is this legal? Be generous, take it to mean AUTH_NONE: */
504 cbs->flavor = 0;
acb2887e
BF
505 for (i = 0; i < nr_secflavs; ++i) {
506 READ_BUF(4);
06553991 507 dummy = be32_to_cpup(p++);
acb2887e
BF
508 switch (dummy) {
509 case RPC_AUTH_NULL:
510 /* Nothing to read */
12fc3e92
BF
511 if (cbs->flavor == (u32)(-1))
512 cbs->flavor = RPC_AUTH_NULL;
acb2887e
BF
513 break;
514 case RPC_AUTH_UNIX:
515 READ_BUF(8);
516 /* stamp */
06553991 517 dummy = be32_to_cpup(p++);
acb2887e
BF
518
519 /* machine name */
06553991 520 dummy = be32_to_cpup(p++);
acb2887e
BF
521 READ_BUF(dummy);
522 SAVEMEM(machine_name, dummy);
523
524 /* uid, gid */
525 READ_BUF(8);
06553991
BF
526 uid = be32_to_cpup(p++);
527 gid = be32_to_cpup(p++);
acb2887e
BF
528
529 /* more gids */
530 READ_BUF(4);
06553991 531 dummy = be32_to_cpup(p++);
acb2887e 532 READ_BUF(dummy * 4);
12fc3e92 533 if (cbs->flavor == (u32)(-1)) {
03bc6d1c
EB
534 kuid_t kuid = make_kuid(&init_user_ns, uid);
535 kgid_t kgid = make_kgid(&init_user_ns, gid);
536 if (uid_valid(kuid) && gid_valid(kgid)) {
537 cbs->uid = kuid;
538 cbs->gid = kgid;
539 cbs->flavor = RPC_AUTH_UNIX;
540 } else {
541 dprintk("RPC_AUTH_UNIX with invalid"
542 "uid or gid ignoring!\n");
543 }
12fc3e92 544 }
acb2887e
BF
545 break;
546 case RPC_AUTH_GSS:
547 dprintk("RPC_AUTH_GSS callback secflavor "
548 "not supported!\n");
549 READ_BUF(8);
550 /* gcbp_service */
06553991 551 dummy = be32_to_cpup(p++);
acb2887e 552 /* gcbp_handle_from_server */
06553991 553 dummy = be32_to_cpup(p++);
acb2887e
BF
554 READ_BUF(dummy);
555 p += XDR_QUADLEN(dummy);
556 /* gcbp_handle_from_client */
557 READ_BUF(4);
06553991 558 dummy = be32_to_cpup(p++);
acb2887e
BF
559 READ_BUF(dummy);
560 break;
561 default:
562 dprintk("Illegal callback secflavor\n");
563 return nfserr_inval;
564 }
565 }
566 DECODE_TAIL;
567}
568
cb73a9f4
BF
569static __be32 nfsd4_decode_backchannel_ctl(struct nfsd4_compoundargs *argp, struct nfsd4_backchannel_ctl *bc)
570{
571 DECODE_HEAD;
572
573 READ_BUF(4);
06553991 574 bc->bc_cb_program = be32_to_cpup(p++);
cb73a9f4
BF
575 nfsd4_decode_cb_sec(argp, &bc->bc_cb_sec);
576
577 DECODE_TAIL;
578}
579
1d1bc8f2
BF
580static __be32 nfsd4_decode_bind_conn_to_session(struct nfsd4_compoundargs *argp, struct nfsd4_bind_conn_to_session *bcts)
581{
582 DECODE_HEAD;
1d1bc8f2
BF
583
584 READ_BUF(NFS4_MAX_SESSIONID_LEN + 8);
585 COPYMEM(bcts->sessionid.data, NFS4_MAX_SESSIONID_LEN);
06553991 586 bcts->dir = be32_to_cpup(p++);
6ce2357f
BS
587 /* XXX: skipping ctsa_use_conn_in_rdma_mode. Perhaps Tom Tucker
588 * could help us figure out we should be using it. */
1d1bc8f2
BF
589 DECODE_TAIL;
590}
591
b37ad28b 592static __be32
1da177e4
LT
593nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close)
594{
595 DECODE_HEAD;
596
e31a1b66 597 READ_BUF(4);
06553991 598 close->cl_seqid = be32_to_cpup(p++);
e31a1b66 599 return nfsd4_decode_stateid(argp, &close->cl_stateid);
1da177e4
LT
600
601 DECODE_TAIL;
602}
603
604
b37ad28b 605static __be32
1da177e4
LT
606nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit)
607{
608 DECODE_HEAD;
609
610 READ_BUF(12);
542d1ab3 611 p = xdr_decode_hyper(p, &commit->co_offset);
06553991 612 commit->co_count = be32_to_cpup(p++);
1da177e4
LT
613
614 DECODE_TAIL;
615}
616
b37ad28b 617static __be32
1da177e4
LT
618nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create)
619{
620 DECODE_HEAD;
621
622 READ_BUF(4);
06553991 623 create->cr_type = be32_to_cpup(p++);
1da177e4
LT
624 switch (create->cr_type) {
625 case NF4LNK:
626 READ_BUF(4);
7fb84306
BF
627 create->cr_datalen = be32_to_cpup(p++);
628 READ_BUF(create->cr_datalen);
29c353b3 629 create->cr_data = svcxdr_dupstr(argp, p, create->cr_datalen);
7fb84306 630 if (!create->cr_data)
76f47128 631 return nfserr_jukebox;
1da177e4
LT
632 break;
633 case NF4BLK:
634 case NF4CHR:
635 READ_BUF(8);
06553991
BF
636 create->cr_specdata1 = be32_to_cpup(p++);
637 create->cr_specdata2 = be32_to_cpup(p++);
1da177e4
LT
638 break;
639 case NF4SOCK:
640 case NF4FIFO:
641 case NF4DIR:
642 default:
643 break;
644 }
645
646 READ_BUF(4);
06553991 647 create->cr_namelen = be32_to_cpup(p++);
1da177e4
LT
648 READ_BUF(create->cr_namelen);
649 SAVEMEM(create->cr_name, create->cr_namelen);
a36b1725 650 if ((status = check_filename(create->cr_name, create->cr_namelen)))
1da177e4
LT
651 return status;
652
3c8e0316 653 status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr,
18032ca0 654 &create->cr_acl, &create->cr_label);
c0d6fc8a 655 if (status)
1da177e4
LT
656 goto out;
657
658 DECODE_TAIL;
659}
660
b37ad28b 661static inline __be32
1da177e4
LT
662nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr)
663{
e31a1b66 664 return nfsd4_decode_stateid(argp, &dr->dr_stateid);
1da177e4
LT
665}
666
b37ad28b 667static inline __be32
1da177e4
LT
668nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr)
669{
670 return nfsd4_decode_bitmap(argp, getattr->ga_bmval);
671}
672
b37ad28b 673static __be32
1da177e4
LT
674nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link)
675{
676 DECODE_HEAD;
677
678 READ_BUF(4);
06553991 679 link->li_namelen = be32_to_cpup(p++);
1da177e4
LT
680 READ_BUF(link->li_namelen);
681 SAVEMEM(link->li_name, link->li_namelen);
a36b1725 682 if ((status = check_filename(link->li_name, link->li_namelen)))
1da177e4
LT
683 return status;
684
685 DECODE_TAIL;
686}
687
b37ad28b 688static __be32
1da177e4
LT
689nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock)
690{
691 DECODE_HEAD;
692
1da177e4
LT
693 /*
694 * type, reclaim(boolean), offset, length, new_lock_owner(boolean)
695 */
696 READ_BUF(28);
06553991 697 lock->lk_type = be32_to_cpup(p++);
1da177e4
LT
698 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT))
699 goto xdr_error;
06553991 700 lock->lk_reclaim = be32_to_cpup(p++);
542d1ab3
BF
701 p = xdr_decode_hyper(p, &lock->lk_offset);
702 p = xdr_decode_hyper(p, &lock->lk_length);
06553991 703 lock->lk_is_new = be32_to_cpup(p++);
1da177e4
LT
704
705 if (lock->lk_is_new) {
e31a1b66 706 READ_BUF(4);
06553991 707 lock->lk_new_open_seqid = be32_to_cpup(p++);
e31a1b66
BH
708 status = nfsd4_decode_stateid(argp, &lock->lk_new_open_stateid);
709 if (status)
710 return status;
711 READ_BUF(8 + sizeof(clientid_t));
06553991 712 lock->lk_new_lock_seqid = be32_to_cpup(p++);
1da177e4 713 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t));
06553991 714 lock->lk_new_owner.len = be32_to_cpup(p++);
1da177e4
LT
715 READ_BUF(lock->lk_new_owner.len);
716 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len);
717 } else {
e31a1b66
BH
718 status = nfsd4_decode_stateid(argp, &lock->lk_old_lock_stateid);
719 if (status)
720 return status;
721 READ_BUF(4);
06553991 722 lock->lk_old_lock_seqid = be32_to_cpup(p++);
1da177e4
LT
723 }
724
725 DECODE_TAIL;
726}
727
b37ad28b 728static __be32
1da177e4
LT
729nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt)
730{
731 DECODE_HEAD;
732
733 READ_BUF(32);
06553991 734 lockt->lt_type = be32_to_cpup(p++);
1da177e4
LT
735 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT))
736 goto xdr_error;
542d1ab3
BF
737 p = xdr_decode_hyper(p, &lockt->lt_offset);
738 p = xdr_decode_hyper(p, &lockt->lt_length);
1da177e4 739 COPYMEM(&lockt->lt_clientid, 8);
06553991 740 lockt->lt_owner.len = be32_to_cpup(p++);
1da177e4
LT
741 READ_BUF(lockt->lt_owner.len);
742 READMEM(lockt->lt_owner.data, lockt->lt_owner.len);
743
744 DECODE_TAIL;
745}
746
b37ad28b 747static __be32
1da177e4
LT
748nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku)
749{
750 DECODE_HEAD;
751
e31a1b66 752 READ_BUF(8);
06553991 753 locku->lu_type = be32_to_cpup(p++);
1da177e4
LT
754 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT))
755 goto xdr_error;
06553991 756 locku->lu_seqid = be32_to_cpup(p++);
e31a1b66
BH
757 status = nfsd4_decode_stateid(argp, &locku->lu_stateid);
758 if (status)
759 return status;
760 READ_BUF(16);
542d1ab3
BF
761 p = xdr_decode_hyper(p, &locku->lu_offset);
762 p = xdr_decode_hyper(p, &locku->lu_length);
1da177e4
LT
763
764 DECODE_TAIL;
765}
766
b37ad28b 767static __be32
1da177e4
LT
768nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup)
769{
770 DECODE_HEAD;
771
772 READ_BUF(4);
06553991 773 lookup->lo_len = be32_to_cpup(p++);
1da177e4
LT
774 READ_BUF(lookup->lo_len);
775 SAVEMEM(lookup->lo_name, lookup->lo_len);
a36b1725 776 if ((status = check_filename(lookup->lo_name, lookup->lo_len)))
1da177e4
LT
777 return status;
778
779 DECODE_TAIL;
780}
781
2c8bd7e0 782static __be32 nfsd4_decode_share_access(struct nfsd4_compoundargs *argp, u32 *share_access, u32 *deleg_want, u32 *deleg_when)
04f9e664
BF
783{
784 __be32 *p;
785 u32 w;
786
787 READ_BUF(4);
06553991 788 w = be32_to_cpup(p++);
2c8bd7e0
BH
789 *share_access = w & NFS4_SHARE_ACCESS_MASK;
790 *deleg_want = w & NFS4_SHARE_WANT_MASK;
791 if (deleg_when)
792 *deleg_when = w & NFS4_SHARE_WHEN_MASK;
793
04f9e664
BF
794 switch (w & NFS4_SHARE_ACCESS_MASK) {
795 case NFS4_SHARE_ACCESS_READ:
796 case NFS4_SHARE_ACCESS_WRITE:
797 case NFS4_SHARE_ACCESS_BOTH:
798 break;
799 default:
800 return nfserr_bad_xdr;
801 }
fc0d14fe 802 w &= ~NFS4_SHARE_ACCESS_MASK;
04f9e664
BF
803 if (!w)
804 return nfs_ok;
805 if (!argp->minorversion)
806 return nfserr_bad_xdr;
807 switch (w & NFS4_SHARE_WANT_MASK) {
808 case NFS4_SHARE_WANT_NO_PREFERENCE:
809 case NFS4_SHARE_WANT_READ_DELEG:
810 case NFS4_SHARE_WANT_WRITE_DELEG:
811 case NFS4_SHARE_WANT_ANY_DELEG:
812 case NFS4_SHARE_WANT_NO_DELEG:
813 case NFS4_SHARE_WANT_CANCEL:
814 break;
815 default:
816 return nfserr_bad_xdr;
817 }
92bac8c5 818 w &= ~NFS4_SHARE_WANT_MASK;
04f9e664
BF
819 if (!w)
820 return nfs_ok;
2c8bd7e0
BH
821
822 if (!deleg_when) /* open_downgrade */
823 return nfserr_inval;
04f9e664
BF
824 switch (w) {
825 case NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL:
826 case NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED:
c668fc6d
BH
827 case (NFS4_SHARE_SIGNAL_DELEG_WHEN_RESRC_AVAIL |
828 NFS4_SHARE_PUSH_DELEG_WHEN_UNCONTENDED):
04f9e664
BF
829 return nfs_ok;
830 }
831xdr_error:
832 return nfserr_bad_xdr;
833}
834
835static __be32 nfsd4_decode_share_deny(struct nfsd4_compoundargs *argp, u32 *x)
836{
837 __be32 *p;
838
839 READ_BUF(4);
06553991 840 *x = be32_to_cpup(p++);
04f9e664 841 /* Note: unlinke access bits, deny bits may be zero. */
01cd4afa 842 if (*x & ~NFS4_SHARE_DENY_BOTH)
04f9e664
BF
843 return nfserr_bad_xdr;
844 return nfs_ok;
845xdr_error:
846 return nfserr_bad_xdr;
847}
848
a084daf5
BF
849static __be32 nfsd4_decode_opaque(struct nfsd4_compoundargs *argp, struct xdr_netobj *o)
850{
851 __be32 *p;
852
853 READ_BUF(4);
06553991 854 o->len = be32_to_cpup(p++);
a084daf5
BF
855
856 if (o->len == 0 || o->len > NFS4_OPAQUE_LIMIT)
857 return nfserr_bad_xdr;
858
859 READ_BUF(o->len);
860 SAVEMEM(o->data, o->len);
861 return nfs_ok;
862xdr_error:
863 return nfserr_bad_xdr;
864}
865
b37ad28b 866static __be32
1da177e4
LT
867nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open)
868{
869 DECODE_HEAD;
2c8bd7e0 870 u32 dummy;
1da177e4
LT
871
872 memset(open->op_bmval, 0, sizeof(open->op_bmval));
873 open->op_iattr.ia_valid = 0;
fe0750e5 874 open->op_openowner = NULL;
1da177e4 875
9d313b17 876 open->op_xdr_error = 0;
1da177e4 877 /* seqid, share_access, share_deny, clientid, ownerlen */
04f9e664 878 READ_BUF(4);
06553991 879 open->op_seqid = be32_to_cpup(p++);
2c8bd7e0
BH
880 /* decode, yet ignore deleg_when until supported */
881 status = nfsd4_decode_share_access(argp, &open->op_share_access,
882 &open->op_deleg_want, &dummy);
04f9e664
BF
883 if (status)
884 goto xdr_error;
885 status = nfsd4_decode_share_deny(argp, &open->op_share_deny);
886 if (status)
887 goto xdr_error;
a084daf5 888 READ_BUF(sizeof(clientid_t));
1da177e4 889 COPYMEM(&open->op_clientid, sizeof(clientid_t));
a084daf5
BF
890 status = nfsd4_decode_opaque(argp, &open->op_owner);
891 if (status)
892 goto xdr_error;
893 READ_BUF(4);
06553991 894 open->op_create = be32_to_cpup(p++);
1da177e4
LT
895 switch (open->op_create) {
896 case NFS4_OPEN_NOCREATE:
897 break;
898 case NFS4_OPEN_CREATE:
899 READ_BUF(4);
06553991 900 open->op_createmode = be32_to_cpup(p++);
1da177e4
LT
901 switch (open->op_createmode) {
902 case NFS4_CREATE_UNCHECKED:
903 case NFS4_CREATE_GUARDED:
c0d6fc8a 904 status = nfsd4_decode_fattr(argp, open->op_bmval,
18032ca0 905 &open->op_iattr, &open->op_acl, &open->op_label);
c0d6fc8a 906 if (status)
1da177e4
LT
907 goto out;
908 break;
909 case NFS4_CREATE_EXCLUSIVE:
ab4684d1
CL
910 READ_BUF(NFS4_VERIFIER_SIZE);
911 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
1da177e4 912 break;
79fb54ab
BH
913 case NFS4_CREATE_EXCLUSIVE4_1:
914 if (argp->minorversion < 1)
915 goto xdr_error;
ab4684d1
CL
916 READ_BUF(NFS4_VERIFIER_SIZE);
917 COPYMEM(open->op_verf.data, NFS4_VERIFIER_SIZE);
79fb54ab 918 status = nfsd4_decode_fattr(argp, open->op_bmval,
18032ca0 919 &open->op_iattr, &open->op_acl, &open->op_label);
79fb54ab
BH
920 if (status)
921 goto out;
922 break;
1da177e4
LT
923 default:
924 goto xdr_error;
925 }
926 break;
927 default:
928 goto xdr_error;
929 }
930
931 /* open_claim */
932 READ_BUF(4);
06553991 933 open->op_claim_type = be32_to_cpup(p++);
1da177e4
LT
934 switch (open->op_claim_type) {
935 case NFS4_OPEN_CLAIM_NULL:
936 case NFS4_OPEN_CLAIM_DELEGATE_PREV:
937 READ_BUF(4);
06553991 938 open->op_fname.len = be32_to_cpup(p++);
1da177e4
LT
939 READ_BUF(open->op_fname.len);
940 SAVEMEM(open->op_fname.data, open->op_fname.len);
a36b1725 941 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
1da177e4
LT
942 return status;
943 break;
944 case NFS4_OPEN_CLAIM_PREVIOUS:
945 READ_BUF(4);
06553991 946 open->op_delegate_type = be32_to_cpup(p++);
1da177e4
LT
947 break;
948 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
e31a1b66
BH
949 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
950 if (status)
951 return status;
952 READ_BUF(4);
06553991 953 open->op_fname.len = be32_to_cpup(p++);
1da177e4
LT
954 READ_BUF(open->op_fname.len);
955 SAVEMEM(open->op_fname.data, open->op_fname.len);
a36b1725 956 if ((status = check_filename(open->op_fname.data, open->op_fname.len)))
1da177e4
LT
957 return status;
958 break;
8b289b2c
BF
959 case NFS4_OPEN_CLAIM_FH:
960 case NFS4_OPEN_CLAIM_DELEG_PREV_FH:
961 if (argp->minorversion < 1)
962 goto xdr_error;
963 /* void */
964 break;
965 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
966 if (argp->minorversion < 1)
967 goto xdr_error;
968 status = nfsd4_decode_stateid(argp, &open->op_delegate_stateid);
969 if (status)
970 return status;
971 break;
1da177e4
LT
972 default:
973 goto xdr_error;
974 }
975
976 DECODE_TAIL;
977}
978
b37ad28b 979static __be32
1da177e4
LT
980nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf)
981{
982 DECODE_HEAD;
e1a90ebd
AS
983
984 if (argp->minorversion >= 1)
985 return nfserr_notsupp;
986
e31a1b66
BH
987 status = nfsd4_decode_stateid(argp, &open_conf->oc_req_stateid);
988 if (status)
989 return status;
990 READ_BUF(4);
06553991 991 open_conf->oc_seqid = be32_to_cpup(p++);
e1a90ebd 992
1da177e4
LT
993 DECODE_TAIL;
994}
995
b37ad28b 996static __be32
1da177e4
LT
997nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down)
998{
999 DECODE_HEAD;
1000
e31a1b66
BH
1001 status = nfsd4_decode_stateid(argp, &open_down->od_stateid);
1002 if (status)
1003 return status;
04f9e664 1004 READ_BUF(4);
06553991 1005 open_down->od_seqid = be32_to_cpup(p++);
2c8bd7e0
BH
1006 status = nfsd4_decode_share_access(argp, &open_down->od_share_access,
1007 &open_down->od_deleg_want, NULL);
04f9e664
BF
1008 if (status)
1009 return status;
1010 status = nfsd4_decode_share_deny(argp, &open_down->od_share_deny);
1011 if (status)
1012 return status;
1da177e4
LT
1013 DECODE_TAIL;
1014}
1015
b37ad28b 1016static __be32
1da177e4
LT
1017nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh)
1018{
1019 DECODE_HEAD;
1020
1021 READ_BUF(4);
06553991 1022 putfh->pf_fhlen = be32_to_cpup(p++);
1da177e4
LT
1023 if (putfh->pf_fhlen > NFS4_FHSIZE)
1024 goto xdr_error;
1025 READ_BUF(putfh->pf_fhlen);
1026 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen);
1027
1028 DECODE_TAIL;
1029}
1030
e1a90ebd
AS
1031static __be32
1032nfsd4_decode_putpubfh(struct nfsd4_compoundargs *argp, void *p)
1033{
1034 if (argp->minorversion == 0)
1035 return nfs_ok;
1036 return nfserr_notsupp;
1037}
1038
b37ad28b 1039static __be32
1da177e4
LT
1040nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read)
1041{
1042 DECODE_HEAD;
1043
e31a1b66
BH
1044 status = nfsd4_decode_stateid(argp, &read->rd_stateid);
1045 if (status)
1046 return status;
1047 READ_BUF(12);
542d1ab3 1048 p = xdr_decode_hyper(p, &read->rd_offset);
06553991 1049 read->rd_length = be32_to_cpup(p++);
1da177e4
LT
1050
1051 DECODE_TAIL;
1052}
1053
b37ad28b 1054static __be32
1da177e4
LT
1055nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir)
1056{
1057 DECODE_HEAD;
1058
1059 READ_BUF(24);
542d1ab3 1060 p = xdr_decode_hyper(p, &readdir->rd_cookie);
1da177e4 1061 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data));
06553991
BF
1062 readdir->rd_dircount = be32_to_cpup(p++);
1063 readdir->rd_maxcount = be32_to_cpup(p++);
1da177e4
LT
1064 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval)))
1065 goto out;
1066
1067 DECODE_TAIL;
1068}
1069
b37ad28b 1070static __be32
1da177e4
LT
1071nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove)
1072{
1073 DECODE_HEAD;
1074
1075 READ_BUF(4);
06553991 1076 remove->rm_namelen = be32_to_cpup(p++);
1da177e4
LT
1077 READ_BUF(remove->rm_namelen);
1078 SAVEMEM(remove->rm_name, remove->rm_namelen);
a36b1725 1079 if ((status = check_filename(remove->rm_name, remove->rm_namelen)))
1da177e4
LT
1080 return status;
1081
1082 DECODE_TAIL;
1083}
1084
b37ad28b 1085static __be32
1da177e4
LT
1086nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename)
1087{
1088 DECODE_HEAD;
1089
1090 READ_BUF(4);
06553991 1091 rename->rn_snamelen = be32_to_cpup(p++);
4aed9c46 1092 READ_BUF(rename->rn_snamelen);
1da177e4 1093 SAVEMEM(rename->rn_sname, rename->rn_snamelen);
4aed9c46 1094 READ_BUF(4);
06553991 1095 rename->rn_tnamelen = be32_to_cpup(p++);
1da177e4
LT
1096 READ_BUF(rename->rn_tnamelen);
1097 SAVEMEM(rename->rn_tname, rename->rn_tnamelen);
a36b1725 1098 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen)))
1da177e4 1099 return status;
a36b1725 1100 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen)))
1da177e4
LT
1101 return status;
1102
1103 DECODE_TAIL;
1104}
1105
b37ad28b 1106static __be32
1da177e4
LT
1107nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid)
1108{
1109 DECODE_HEAD;
1110
e1a90ebd
AS
1111 if (argp->minorversion >= 1)
1112 return nfserr_notsupp;
1113
1da177e4
LT
1114 READ_BUF(sizeof(clientid_t));
1115 COPYMEM(clientid, sizeof(clientid_t));
1116
1117 DECODE_TAIL;
1118}
1119
dcb488a3
AA
1120static __be32
1121nfsd4_decode_secinfo(struct nfsd4_compoundargs *argp,
1122 struct nfsd4_secinfo *secinfo)
1123{
1124 DECODE_HEAD;
1125
1126 READ_BUF(4);
06553991 1127 secinfo->si_namelen = be32_to_cpup(p++);
dcb488a3
AA
1128 READ_BUF(secinfo->si_namelen);
1129 SAVEMEM(secinfo->si_name, secinfo->si_namelen);
a36b1725 1130 status = check_filename(secinfo->si_name, secinfo->si_namelen);
dcb488a3
AA
1131 if (status)
1132 return status;
1133 DECODE_TAIL;
1134}
1135
04f4ad16
BF
1136static __be32
1137nfsd4_decode_secinfo_no_name(struct nfsd4_compoundargs *argp,
1138 struct nfsd4_secinfo_no_name *sin)
1139{
1140 DECODE_HEAD;
1141
1142 READ_BUF(4);
06553991 1143 sin->sin_style = be32_to_cpup(p++);
04f4ad16
BF
1144 DECODE_TAIL;
1145}
1146
b37ad28b 1147static __be32
1da177e4
LT
1148nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr)
1149{
e31a1b66 1150 __be32 status;
1da177e4 1151
e31a1b66
BH
1152 status = nfsd4_decode_stateid(argp, &setattr->sa_stateid);
1153 if (status)
1154 return status;
3c8e0316 1155 return nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr,
18032ca0 1156 &setattr->sa_acl, &setattr->sa_label);
1da177e4
LT
1157}
1158
b37ad28b 1159static __be32
1da177e4
LT
1160nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid)
1161{
1162 DECODE_HEAD;
1163
e1a90ebd
AS
1164 if (argp->minorversion >= 1)
1165 return nfserr_notsupp;
1166
ab4684d1
CL
1167 READ_BUF(NFS4_VERIFIER_SIZE);
1168 COPYMEM(setclientid->se_verf.data, NFS4_VERIFIER_SIZE);
1da177e4 1169
a084daf5
BF
1170 status = nfsd4_decode_opaque(argp, &setclientid->se_name);
1171 if (status)
1172 return nfserr_bad_xdr;
1173 READ_BUF(8);
06553991
BF
1174 setclientid->se_callback_prog = be32_to_cpup(p++);
1175 setclientid->se_callback_netid_len = be32_to_cpup(p++);
4aed9c46 1176 READ_BUF(setclientid->se_callback_netid_len);
1da177e4 1177 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len);
4aed9c46 1178 READ_BUF(4);
06553991 1179 setclientid->se_callback_addr_len = be32_to_cpup(p++);
1da177e4 1180
4aed9c46 1181 READ_BUF(setclientid->se_callback_addr_len);
1da177e4 1182 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len);
4aed9c46 1183 READ_BUF(4);
06553991 1184 setclientid->se_callback_ident = be32_to_cpup(p++);
1da177e4
LT
1185
1186 DECODE_TAIL;
1187}
1188
b37ad28b 1189static __be32
1da177e4
LT
1190nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c)
1191{
1192 DECODE_HEAD;
1193
e1a90ebd
AS
1194 if (argp->minorversion >= 1)
1195 return nfserr_notsupp;
1196
ab4684d1 1197 READ_BUF(8 + NFS4_VERIFIER_SIZE);
1da177e4 1198 COPYMEM(&scd_c->sc_clientid, 8);
ab4684d1 1199 COPYMEM(&scd_c->sc_confirm, NFS4_VERIFIER_SIZE);
1da177e4
LT
1200
1201 DECODE_TAIL;
1202}
1203
1204/* Also used for NVERIFY */
b37ad28b 1205static __be32
1da177e4
LT
1206nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify)
1207{
1da177e4
LT
1208 DECODE_HEAD;
1209
1210 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval)))
1211 goto out;
1212
1213 /* For convenience's sake, we compare raw xdr'd attributes in
e5f95703
BF
1214 * nfsd4_proc_verify */
1215
1da177e4 1216 READ_BUF(4);
06553991 1217 verify->ve_attrlen = be32_to_cpup(p++);
1da177e4
LT
1218 READ_BUF(verify->ve_attrlen);
1219 SAVEMEM(verify->ve_attrval, verify->ve_attrlen);
1220
1221 DECODE_TAIL;
1222}
1223
b37ad28b 1224static __be32
1da177e4
LT
1225nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write)
1226{
1227 int avail;
1da177e4
LT
1228 int len;
1229 DECODE_HEAD;
1230
e31a1b66
BH
1231 status = nfsd4_decode_stateid(argp, &write->wr_stateid);
1232 if (status)
1233 return status;
1234 READ_BUF(16);
542d1ab3 1235 p = xdr_decode_hyper(p, &write->wr_offset);
06553991 1236 write->wr_stable_how = be32_to_cpup(p++);
1da177e4
LT
1237 if (write->wr_stable_how > 2)
1238 goto xdr_error;
06553991 1239 write->wr_buflen = be32_to_cpup(p++);
1da177e4
LT
1240
1241 /* Sorry .. no magic macros for this.. *
1242 * READ_BUF(write->wr_buflen);
1243 * SAVEMEM(write->wr_buf, write->wr_buflen);
1244 */
1245 avail = (char*)argp->end - (char*)argp->p;
1246 if (avail + argp->pagelen < write->wr_buflen) {
817cb9d4
CL
1247 dprintk("NFSD: xdr error (%s:%d)\n",
1248 __FILE__, __LINE__);
1da177e4
LT
1249 goto xdr_error;
1250 }
70cc7f75
BF
1251 write->wr_head.iov_base = p;
1252 write->wr_head.iov_len = avail;
70cc7f75 1253 write->wr_pagelist = argp->pagelist;
5a80a54d
BF
1254
1255 len = XDR_QUADLEN(write->wr_buflen) << 2;
1256 if (len >= avail) {
1257 int pages;
1258
1259 len -= avail;
1260
1261 pages = len >> PAGE_SHIFT;
1262 argp->pagelist += pages;
1263 argp->pagelen -= pages * PAGE_SIZE;
1264 len -= pages * PAGE_SIZE;
1265
1266 argp->p = (__be32 *)page_address(argp->pagelist[0]);
365da4ad 1267 argp->pagelist++;
5a80a54d 1268 argp->end = argp->p + XDR_QUADLEN(PAGE_SIZE);
1da177e4 1269 }
5a80a54d 1270 argp->p += XDR_QUADLEN(len);
1da177e4
LT
1271
1272 DECODE_TAIL;
1273}
1274
b37ad28b 1275static __be32
1da177e4
LT
1276nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner)
1277{
1278 DECODE_HEAD;
1279
e1a90ebd
AS
1280 if (argp->minorversion >= 1)
1281 return nfserr_notsupp;
1282
1da177e4
LT
1283 READ_BUF(12);
1284 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t));
06553991 1285 rlockowner->rl_owner.len = be32_to_cpup(p++);
1da177e4
LT
1286 READ_BUF(rlockowner->rl_owner.len);
1287 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len);
1288
60adfc50
AA
1289 if (argp->minorversion && !zero_clientid(&rlockowner->rl_clientid))
1290 return nfserr_inval;
1da177e4
LT
1291 DECODE_TAIL;
1292}
1293
2db134eb
AA
1294static __be32
1295nfsd4_decode_exchange_id(struct nfsd4_compoundargs *argp,
0733d213 1296 struct nfsd4_exchange_id *exid)
2db134eb 1297{
5afa040b 1298 int dummy, tmp;
0733d213
AA
1299 DECODE_HEAD;
1300
1301 READ_BUF(NFS4_VERIFIER_SIZE);
1302 COPYMEM(exid->verifier.data, NFS4_VERIFIER_SIZE);
1303
a084daf5
BF
1304 status = nfsd4_decode_opaque(argp, &exid->clname);
1305 if (status)
1306 return nfserr_bad_xdr;
0733d213
AA
1307
1308 READ_BUF(4);
06553991 1309 exid->flags = be32_to_cpup(p++);
0733d213
AA
1310
1311 /* Ignore state_protect4_a */
1312 READ_BUF(4);
06553991 1313 exid->spa_how = be32_to_cpup(p++);
0733d213
AA
1314 switch (exid->spa_how) {
1315 case SP4_NONE:
1316 break;
1317 case SP4_MACH_CRED:
1318 /* spo_must_enforce */
ed941643
AE
1319 status = nfsd4_decode_bitmap(argp,
1320 exid->spo_must_enforce);
1321 if (status)
1322 goto out;
0733d213 1323 /* spo_must_allow */
ed941643
AE
1324 status = nfsd4_decode_bitmap(argp, exid->spo_must_allow);
1325 if (status)
1326 goto out;
0733d213
AA
1327 break;
1328 case SP4_SSV:
1329 /* ssp_ops */
1330 READ_BUF(4);
06553991 1331 dummy = be32_to_cpup(p++);
0733d213
AA
1332 READ_BUF(dummy * 4);
1333 p += dummy;
1334
1335 READ_BUF(4);
06553991 1336 dummy = be32_to_cpup(p++);
0733d213
AA
1337 READ_BUF(dummy * 4);
1338 p += dummy;
1339
1340 /* ssp_hash_algs<> */
1341 READ_BUF(4);
06553991 1342 tmp = be32_to_cpup(p++);
5afa040b
MJ
1343 while (tmp--) {
1344 READ_BUF(4);
06553991 1345 dummy = be32_to_cpup(p++);
5afa040b
MJ
1346 READ_BUF(dummy);
1347 p += XDR_QUADLEN(dummy);
1348 }
0733d213
AA
1349
1350 /* ssp_encr_algs<> */
1351 READ_BUF(4);
06553991 1352 tmp = be32_to_cpup(p++);
5afa040b
MJ
1353 while (tmp--) {
1354 READ_BUF(4);
06553991 1355 dummy = be32_to_cpup(p++);
5afa040b
MJ
1356 READ_BUF(dummy);
1357 p += XDR_QUADLEN(dummy);
1358 }
0733d213
AA
1359
1360 /* ssp_window and ssp_num_gss_handles */
1361 READ_BUF(8);
06553991
BF
1362 dummy = be32_to_cpup(p++);
1363 dummy = be32_to_cpup(p++);
0733d213
AA
1364 break;
1365 default:
1366 goto xdr_error;
1367 }
1368
1369 /* Ignore Implementation ID */
1370 READ_BUF(4); /* nfs_impl_id4 array length */
06553991 1371 dummy = be32_to_cpup(p++);
0733d213
AA
1372
1373 if (dummy > 1)
1374 goto xdr_error;
1375
1376 if (dummy == 1) {
1377 /* nii_domain */
1378 READ_BUF(4);
06553991 1379 dummy = be32_to_cpup(p++);
0733d213
AA
1380 READ_BUF(dummy);
1381 p += XDR_QUADLEN(dummy);
1382
1383 /* nii_name */
1384 READ_BUF(4);
06553991 1385 dummy = be32_to_cpup(p++);
0733d213
AA
1386 READ_BUF(dummy);
1387 p += XDR_QUADLEN(dummy);
1388
1389 /* nii_date */
1390 READ_BUF(12);
1391 p += 3;
1392 }
1393 DECODE_TAIL;
2db134eb
AA
1394}
1395
1396static __be32
1397nfsd4_decode_create_session(struct nfsd4_compoundargs *argp,
1398 struct nfsd4_create_session *sess)
1399{
ec6b5d7b 1400 DECODE_HEAD;
ec6b5d7b 1401 u32 dummy;
ec6b5d7b
AA
1402
1403 READ_BUF(16);
1404 COPYMEM(&sess->clientid, 8);
06553991
BF
1405 sess->seqid = be32_to_cpup(p++);
1406 sess->flags = be32_to_cpup(p++);
ec6b5d7b
AA
1407
1408 /* Fore channel attrs */
1409 READ_BUF(28);
06553991
BF
1410 dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */
1411 sess->fore_channel.maxreq_sz = be32_to_cpup(p++);
1412 sess->fore_channel.maxresp_sz = be32_to_cpup(p++);
1413 sess->fore_channel.maxresp_cached = be32_to_cpup(p++);
1414 sess->fore_channel.maxops = be32_to_cpup(p++);
1415 sess->fore_channel.maxreqs = be32_to_cpup(p++);
1416 sess->fore_channel.nr_rdma_attrs = be32_to_cpup(p++);
ec6b5d7b
AA
1417 if (sess->fore_channel.nr_rdma_attrs == 1) {
1418 READ_BUF(4);
06553991 1419 sess->fore_channel.rdma_attrs = be32_to_cpup(p++);
ec6b5d7b
AA
1420 } else if (sess->fore_channel.nr_rdma_attrs > 1) {
1421 dprintk("Too many fore channel attr bitmaps!\n");
1422 goto xdr_error;
1423 }
1424
1425 /* Back channel attrs */
1426 READ_BUF(28);
06553991
BF
1427 dummy = be32_to_cpup(p++); /* headerpadsz is always 0 */
1428 sess->back_channel.maxreq_sz = be32_to_cpup(p++);
1429 sess->back_channel.maxresp_sz = be32_to_cpup(p++);
1430 sess->back_channel.maxresp_cached = be32_to_cpup(p++);
1431 sess->back_channel.maxops = be32_to_cpup(p++);
1432 sess->back_channel.maxreqs = be32_to_cpup(p++);
1433 sess->back_channel.nr_rdma_attrs = be32_to_cpup(p++);
ec6b5d7b
AA
1434 if (sess->back_channel.nr_rdma_attrs == 1) {
1435 READ_BUF(4);
06553991 1436 sess->back_channel.rdma_attrs = be32_to_cpup(p++);
ec6b5d7b
AA
1437 } else if (sess->back_channel.nr_rdma_attrs > 1) {
1438 dprintk("Too many back channel attr bitmaps!\n");
1439 goto xdr_error;
1440 }
1441
acb2887e 1442 READ_BUF(4);
06553991 1443 sess->callback_prog = be32_to_cpup(p++);
acb2887e 1444 nfsd4_decode_cb_sec(argp, &sess->cb_sec);
ec6b5d7b 1445 DECODE_TAIL;
2db134eb
AA
1446}
1447
1448static __be32
1449nfsd4_decode_destroy_session(struct nfsd4_compoundargs *argp,
1450 struct nfsd4_destroy_session *destroy_session)
1451{
e10e0cfc
BH
1452 DECODE_HEAD;
1453 READ_BUF(NFS4_MAX_SESSIONID_LEN);
1454 COPYMEM(destroy_session->sessionid.data, NFS4_MAX_SESSIONID_LEN);
1455
1456 DECODE_TAIL;
2db134eb
AA
1457}
1458
e1ca12df
BS
1459static __be32
1460nfsd4_decode_free_stateid(struct nfsd4_compoundargs *argp,
1461 struct nfsd4_free_stateid *free_stateid)
1462{
1463 DECODE_HEAD;
1464
1465 READ_BUF(sizeof(stateid_t));
06553991 1466 free_stateid->fr_stateid.si_generation = be32_to_cpup(p++);
e1ca12df
BS
1467 COPYMEM(&free_stateid->fr_stateid.si_opaque, sizeof(stateid_opaque_t));
1468
1469 DECODE_TAIL;
1470}
1471
2db134eb
AA
1472static __be32
1473nfsd4_decode_sequence(struct nfsd4_compoundargs *argp,
1474 struct nfsd4_sequence *seq)
1475{
b85d4c01
BH
1476 DECODE_HEAD;
1477
1478 READ_BUF(NFS4_MAX_SESSIONID_LEN + 16);
1479 COPYMEM(seq->sessionid.data, NFS4_MAX_SESSIONID_LEN);
06553991
BF
1480 seq->seqid = be32_to_cpup(p++);
1481 seq->slotid = be32_to_cpup(p++);
1482 seq->maxslots = be32_to_cpup(p++);
1483 seq->cachethis = be32_to_cpup(p++);
b85d4c01
BH
1484
1485 DECODE_TAIL;
2db134eb
AA
1486}
1487
17456804
BS
1488static __be32
1489nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_stateid *test_stateid)
1490{
17456804 1491 int i;
03cfb420
BS
1492 __be32 *p, status;
1493 struct nfsd4_test_stateid_id *stateid;
17456804
BS
1494
1495 READ_BUF(4);
1496 test_stateid->ts_num_ids = ntohl(*p++);
1497
03cfb420 1498 INIT_LIST_HEAD(&test_stateid->ts_stateid_list);
17456804
BS
1499
1500 for (i = 0; i < test_stateid->ts_num_ids; i++) {
d5e23383 1501 stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));
03cfb420 1502 if (!stateid) {
afcf6792 1503 status = nfserrno(-ENOMEM);
03cfb420
BS
1504 goto out;
1505 }
1506
03cfb420
BS
1507 INIT_LIST_HEAD(&stateid->ts_id_list);
1508 list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);
1509
1510 status = nfsd4_decode_stateid(argp, &stateid->ts_id_stateid);
17456804 1511 if (status)
03cfb420 1512 goto out;
17456804
BS
1513 }
1514
1515 status = 0;
1516out:
1517 return status;
1518xdr_error:
1519 dprintk("NFSD: xdr error (%s:%d)\n", __FILE__, __LINE__);
1520 status = nfserr_bad_xdr;
1521 goto out;
1522}
1523
345c2842
MJ
1524static __be32 nfsd4_decode_destroy_clientid(struct nfsd4_compoundargs *argp, struct nfsd4_destroy_clientid *dc)
1525{
1526 DECODE_HEAD;
1527
1528 READ_BUF(8);
1529 COPYMEM(&dc->clientid, 8);
1530
1531 DECODE_TAIL;
1532}
1533
4dc6ec00
BF
1534static __be32 nfsd4_decode_reclaim_complete(struct nfsd4_compoundargs *argp, struct nfsd4_reclaim_complete *rc)
1535{
1536 DECODE_HEAD;
1537
1538 READ_BUF(4);
06553991 1539 rc->rca_one_fs = be32_to_cpup(p++);
4dc6ec00
BF
1540
1541 DECODE_TAIL;
1542}
1543
9cf514cc
CH
1544#ifdef CONFIG_NFSD_PNFS
1545static __be32
1546nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp,
1547 struct nfsd4_getdeviceinfo *gdev)
1548{
1549 DECODE_HEAD;
1550 u32 num, i;
1551
1552 READ_BUF(sizeof(struct nfsd4_deviceid) + 3 * 4);
1553 COPYMEM(&gdev->gd_devid, sizeof(struct nfsd4_deviceid));
1554 gdev->gd_layout_type = be32_to_cpup(p++);
1555 gdev->gd_maxcount = be32_to_cpup(p++);
1556 num = be32_to_cpup(p++);
1557 if (num) {
1558 READ_BUF(4 * num);
1559 gdev->gd_notify_types = be32_to_cpup(p++);
1560 for (i = 1; i < num; i++) {
1561 if (be32_to_cpup(p++)) {
1562 status = nfserr_inval;
1563 goto out;
1564 }
1565 }
1566 }
1567 DECODE_TAIL;
1568}
1569
1570static __be32
1571nfsd4_decode_layoutget(struct nfsd4_compoundargs *argp,
1572 struct nfsd4_layoutget *lgp)
1573{
1574 DECODE_HEAD;
1575
1576 READ_BUF(36);
1577 lgp->lg_signal = be32_to_cpup(p++);
1578 lgp->lg_layout_type = be32_to_cpup(p++);
1579 lgp->lg_seg.iomode = be32_to_cpup(p++);
1580 p = xdr_decode_hyper(p, &lgp->lg_seg.offset);
1581 p = xdr_decode_hyper(p, &lgp->lg_seg.length);
1582 p = xdr_decode_hyper(p, &lgp->lg_minlength);
db59c0ef
KM
1583
1584 status = nfsd4_decode_stateid(argp, &lgp->lg_sid);
1585 if (status)
1586 return status;
1587
9cf514cc
CH
1588 READ_BUF(4);
1589 lgp->lg_maxcount = be32_to_cpup(p++);
1590
1591 DECODE_TAIL;
1592}
1593
1594static __be32
1595nfsd4_decode_layoutcommit(struct nfsd4_compoundargs *argp,
1596 struct nfsd4_layoutcommit *lcp)
1597{
1598 DECODE_HEAD;
1599 u32 timechange;
1600
1601 READ_BUF(20);
1602 p = xdr_decode_hyper(p, &lcp->lc_seg.offset);
1603 p = xdr_decode_hyper(p, &lcp->lc_seg.length);
1604 lcp->lc_reclaim = be32_to_cpup(p++);
db59c0ef
KM
1605
1606 status = nfsd4_decode_stateid(argp, &lcp->lc_sid);
1607 if (status)
1608 return status;
1609
9cf514cc
CH
1610 READ_BUF(4);
1611 lcp->lc_newoffset = be32_to_cpup(p++);
1612 if (lcp->lc_newoffset) {
1613 READ_BUF(8);
1614 p = xdr_decode_hyper(p, &lcp->lc_last_wr);
1615 } else
1616 lcp->lc_last_wr = 0;
1617 READ_BUF(4);
1618 timechange = be32_to_cpup(p++);
1619 if (timechange) {
1620 status = nfsd4_decode_time(argp, &lcp->lc_mtime);
1621 if (status)
1622 return status;
1623 } else {
1624 lcp->lc_mtime.tv_nsec = UTIME_NOW;
1625 }
1626 READ_BUF(8);
1627 lcp->lc_layout_type = be32_to_cpup(p++);
1628
1629 /*
1630 * Save the layout update in XDR format and let the layout driver deal
1631 * with it later.
1632 */
1633 lcp->lc_up_len = be32_to_cpup(p++);
1634 if (lcp->lc_up_len > 0) {
1635 READ_BUF(lcp->lc_up_len);
1636 READMEM(lcp->lc_up_layout, lcp->lc_up_len);
1637 }
1638
1639 DECODE_TAIL;
1640}
1641
1642static __be32
1643nfsd4_decode_layoutreturn(struct nfsd4_compoundargs *argp,
1644 struct nfsd4_layoutreturn *lrp)
1645{
1646 DECODE_HEAD;
1647
1648 READ_BUF(16);
1649 lrp->lr_reclaim = be32_to_cpup(p++);
1650 lrp->lr_layout_type = be32_to_cpup(p++);
1651 lrp->lr_seg.iomode = be32_to_cpup(p++);
1652 lrp->lr_return_type = be32_to_cpup(p++);
1653 if (lrp->lr_return_type == RETURN_FILE) {
1654 READ_BUF(16);
1655 p = xdr_decode_hyper(p, &lrp->lr_seg.offset);
1656 p = xdr_decode_hyper(p, &lrp->lr_seg.length);
db59c0ef
KM
1657
1658 status = nfsd4_decode_stateid(argp, &lrp->lr_sid);
1659 if (status)
1660 return status;
1661
9cf514cc
CH
1662 READ_BUF(4);
1663 lrp->lrf_body_len = be32_to_cpup(p++);
1664 if (lrp->lrf_body_len > 0) {
1665 READ_BUF(lrp->lrf_body_len);
1666 READMEM(lrp->lrf_body, lrp->lrf_body_len);
1667 }
1668 } else {
1669 lrp->lr_seg.offset = 0;
1670 lrp->lr_seg.length = NFS4_MAX_UINT64;
1671 }
1672
1673 DECODE_TAIL;
1674}
1675#endif /* CONFIG_NFSD_PNFS */
1676
95d871f0
AS
1677static __be32
1678nfsd4_decode_fallocate(struct nfsd4_compoundargs *argp,
1679 struct nfsd4_fallocate *fallocate)
1680{
1681 DECODE_HEAD;
1682
1683 status = nfsd4_decode_stateid(argp, &fallocate->falloc_stateid);
1684 if (status)
1685 return status;
1686
1687 READ_BUF(16);
1688 p = xdr_decode_hyper(p, &fallocate->falloc_offset);
1689 xdr_decode_hyper(p, &fallocate->falloc_length);
1690
1691 DECODE_TAIL;
1692}
1693
ffa0160a
CH
1694static __be32
1695nfsd4_decode_clone(struct nfsd4_compoundargs *argp, struct nfsd4_clone *clone)
1696{
1697 DECODE_HEAD;
1698
1699 status = nfsd4_decode_stateid(argp, &clone->cl_src_stateid);
1700 if (status)
1701 return status;
1702 status = nfsd4_decode_stateid(argp, &clone->cl_dst_stateid);
1703 if (status)
1704 return status;
1705
1706 READ_BUF(8 + 8 + 8);
1707 p = xdr_decode_hyper(p, &clone->cl_src_pos);
1708 p = xdr_decode_hyper(p, &clone->cl_dst_pos);
1709 p = xdr_decode_hyper(p, &clone->cl_count);
1710 DECODE_TAIL;
1711}
1712
29ae7f9d
AS
1713static __be32
1714nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)
1715{
1716 DECODE_HEAD;
1717 unsigned int tmp;
1718
1719 status = nfsd4_decode_stateid(argp, &copy->cp_src_stateid);
1720 if (status)
1721 return status;
1722 status = nfsd4_decode_stateid(argp, &copy->cp_dst_stateid);
1723 if (status)
1724 return status;
1725
1726 READ_BUF(8 + 8 + 8 + 4 + 4 + 4);
1727 p = xdr_decode_hyper(p, &copy->cp_src_pos);
1728 p = xdr_decode_hyper(p, &copy->cp_dst_pos);
1729 p = xdr_decode_hyper(p, &copy->cp_count);
1730 copy->cp_consecutive = be32_to_cpup(p++);
1731 copy->cp_synchronous = be32_to_cpup(p++);
1732 tmp = be32_to_cpup(p); /* Source server list not supported */
1733
1734 DECODE_TAIL;
1735}
1736
24bab491
AS
1737static __be32
1738nfsd4_decode_seek(struct nfsd4_compoundargs *argp, struct nfsd4_seek *seek)
1739{
1740 DECODE_HEAD;
1741
1742 status = nfsd4_decode_stateid(argp, &seek->seek_stateid);
1743 if (status)
1744 return status;
1745
1746 READ_BUF(8 + 4);
1747 p = xdr_decode_hyper(p, &seek->seek_offset);
1748 seek->seek_whence = be32_to_cpup(p);
1749
1750 DECODE_TAIL;
1751}
1752
347e0ad9
BH
1753static __be32
1754nfsd4_decode_noop(struct nfsd4_compoundargs *argp, void *p)
1755{
1756 return nfs_ok;
1757}
1758
3c375c6f
BH
1759static __be32
1760nfsd4_decode_notsupp(struct nfsd4_compoundargs *argp, void *p)
1761{
1e685ec2 1762 return nfserr_notsupp;
3c375c6f
BH
1763}
1764
347e0ad9
BH
1765typedef __be32(*nfsd4_dec)(struct nfsd4_compoundargs *argp, void *);
1766
1767static nfsd4_dec nfsd4_dec_ops[] = {
ad1060c8
BF
1768 [OP_ACCESS] = (nfsd4_dec)nfsd4_decode_access,
1769 [OP_CLOSE] = (nfsd4_dec)nfsd4_decode_close,
1770 [OP_COMMIT] = (nfsd4_dec)nfsd4_decode_commit,
1771 [OP_CREATE] = (nfsd4_dec)nfsd4_decode_create,
1772 [OP_DELEGPURGE] = (nfsd4_dec)nfsd4_decode_notsupp,
1773 [OP_DELEGRETURN] = (nfsd4_dec)nfsd4_decode_delegreturn,
1774 [OP_GETATTR] = (nfsd4_dec)nfsd4_decode_getattr,
1775 [OP_GETFH] = (nfsd4_dec)nfsd4_decode_noop,
1776 [OP_LINK] = (nfsd4_dec)nfsd4_decode_link,
1777 [OP_LOCK] = (nfsd4_dec)nfsd4_decode_lock,
1778 [OP_LOCKT] = (nfsd4_dec)nfsd4_decode_lockt,
1779 [OP_LOCKU] = (nfsd4_dec)nfsd4_decode_locku,
1780 [OP_LOOKUP] = (nfsd4_dec)nfsd4_decode_lookup,
1781 [OP_LOOKUPP] = (nfsd4_dec)nfsd4_decode_noop,
1782 [OP_NVERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1783 [OP_OPEN] = (nfsd4_dec)nfsd4_decode_open,
1784 [OP_OPENATTR] = (nfsd4_dec)nfsd4_decode_notsupp,
1785 [OP_OPEN_CONFIRM] = (nfsd4_dec)nfsd4_decode_open_confirm,
1786 [OP_OPEN_DOWNGRADE] = (nfsd4_dec)nfsd4_decode_open_downgrade,
1787 [OP_PUTFH] = (nfsd4_dec)nfsd4_decode_putfh,
e1a90ebd 1788 [OP_PUTPUBFH] = (nfsd4_dec)nfsd4_decode_putpubfh,
ad1060c8
BF
1789 [OP_PUTROOTFH] = (nfsd4_dec)nfsd4_decode_noop,
1790 [OP_READ] = (nfsd4_dec)nfsd4_decode_read,
1791 [OP_READDIR] = (nfsd4_dec)nfsd4_decode_readdir,
1792 [OP_READLINK] = (nfsd4_dec)nfsd4_decode_noop,
1793 [OP_REMOVE] = (nfsd4_dec)nfsd4_decode_remove,
1794 [OP_RENAME] = (nfsd4_dec)nfsd4_decode_rename,
1795 [OP_RENEW] = (nfsd4_dec)nfsd4_decode_renew,
1796 [OP_RESTOREFH] = (nfsd4_dec)nfsd4_decode_noop,
1797 [OP_SAVEFH] = (nfsd4_dec)nfsd4_decode_noop,
1798 [OP_SECINFO] = (nfsd4_dec)nfsd4_decode_secinfo,
1799 [OP_SETATTR] = (nfsd4_dec)nfsd4_decode_setattr,
1800 [OP_SETCLIENTID] = (nfsd4_dec)nfsd4_decode_setclientid,
1801 [OP_SETCLIENTID_CONFIRM] = (nfsd4_dec)nfsd4_decode_setclientid_confirm,
1802 [OP_VERIFY] = (nfsd4_dec)nfsd4_decode_verify,
1803 [OP_WRITE] = (nfsd4_dec)nfsd4_decode_write,
1804 [OP_RELEASE_LOCKOWNER] = (nfsd4_dec)nfsd4_decode_release_lockowner,
2db134eb
AA
1805
1806 /* new operations for NFSv4.1 */
cb73a9f4 1807 [OP_BACKCHANNEL_CTL] = (nfsd4_dec)nfsd4_decode_backchannel_ctl,
1d1bc8f2 1808 [OP_BIND_CONN_TO_SESSION]= (nfsd4_dec)nfsd4_decode_bind_conn_to_session,
9064caae
RD
1809 [OP_EXCHANGE_ID] = (nfsd4_dec)nfsd4_decode_exchange_id,
1810 [OP_CREATE_SESSION] = (nfsd4_dec)nfsd4_decode_create_session,
1811 [OP_DESTROY_SESSION] = (nfsd4_dec)nfsd4_decode_destroy_session,
e1ca12df 1812 [OP_FREE_STATEID] = (nfsd4_dec)nfsd4_decode_free_stateid,
9064caae 1813 [OP_GET_DIR_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
9cf514cc
CH
1814#ifdef CONFIG_NFSD_PNFS
1815 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_getdeviceinfo,
1816 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1817 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_layoutcommit,
1818 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_layoutget,
1819 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_layoutreturn,
1820#else
9064caae
RD
1821 [OP_GETDEVICEINFO] = (nfsd4_dec)nfsd4_decode_notsupp,
1822 [OP_GETDEVICELIST] = (nfsd4_dec)nfsd4_decode_notsupp,
1823 [OP_LAYOUTCOMMIT] = (nfsd4_dec)nfsd4_decode_notsupp,
1824 [OP_LAYOUTGET] = (nfsd4_dec)nfsd4_decode_notsupp,
1825 [OP_LAYOUTRETURN] = (nfsd4_dec)nfsd4_decode_notsupp,
9cf514cc 1826#endif
04f4ad16 1827 [OP_SECINFO_NO_NAME] = (nfsd4_dec)nfsd4_decode_secinfo_no_name,
9064caae
RD
1828 [OP_SEQUENCE] = (nfsd4_dec)nfsd4_decode_sequence,
1829 [OP_SET_SSV] = (nfsd4_dec)nfsd4_decode_notsupp,
17456804 1830 [OP_TEST_STATEID] = (nfsd4_dec)nfsd4_decode_test_stateid,
9064caae 1831 [OP_WANT_DELEGATION] = (nfsd4_dec)nfsd4_decode_notsupp,
345c2842 1832 [OP_DESTROY_CLIENTID] = (nfsd4_dec)nfsd4_decode_destroy_clientid,
4dc6ec00 1833 [OP_RECLAIM_COMPLETE] = (nfsd4_dec)nfsd4_decode_reclaim_complete,
87a15a80
AS
1834
1835 /* new operations for NFSv4.2 */
95d871f0 1836 [OP_ALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
29ae7f9d 1837 [OP_COPY] = (nfsd4_dec)nfsd4_decode_copy,
87a15a80 1838 [OP_COPY_NOTIFY] = (nfsd4_dec)nfsd4_decode_notsupp,
b0cb9085 1839 [OP_DEALLOCATE] = (nfsd4_dec)nfsd4_decode_fallocate,
87a15a80
AS
1840 [OP_IO_ADVISE] = (nfsd4_dec)nfsd4_decode_notsupp,
1841 [OP_LAYOUTERROR] = (nfsd4_dec)nfsd4_decode_notsupp,
1842 [OP_LAYOUTSTATS] = (nfsd4_dec)nfsd4_decode_notsupp,
1843 [OP_OFFLOAD_CANCEL] = (nfsd4_dec)nfsd4_decode_notsupp,
1844 [OP_OFFLOAD_STATUS] = (nfsd4_dec)nfsd4_decode_notsupp,
1845 [OP_READ_PLUS] = (nfsd4_dec)nfsd4_decode_notsupp,
24bab491 1846 [OP_SEEK] = (nfsd4_dec)nfsd4_decode_seek,
87a15a80 1847 [OP_WRITE_SAME] = (nfsd4_dec)nfsd4_decode_notsupp,
ffa0160a 1848 [OP_CLONE] = (nfsd4_dec)nfsd4_decode_clone,
2db134eb
AA
1849};
1850
e1a90ebd
AS
1851static inline bool
1852nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
1853{
8217d146 1854 if (op->opnum < FIRST_NFS4_OP)
e1a90ebd 1855 return false;
8217d146 1856 else if (argp->minorversion == 0 && op->opnum > LAST_NFS40_OP)
e1a90ebd 1857 return false;
8217d146
AS
1858 else if (argp->minorversion == 1 && op->opnum > LAST_NFS41_OP)
1859 return false;
1860 else if (argp->minorversion == 2 && op->opnum > LAST_NFS42_OP)
e1a90ebd
AS
1861 return false;
1862 return true;
1863}
f2feb96b 1864
b37ad28b 1865static __be32
1da177e4
LT
1866nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1867{
1868 DECODE_HEAD;
1869 struct nfsd4_op *op;
1091006c 1870 bool cachethis = false;
a5cddc88
BF
1871 int auth_slack= argp->rqstp->rq_auth_slack;
1872 int max_reply = auth_slack + 8; /* opcnt, status */
b0e35fda
BF
1873 int readcount = 0;
1874 int readbytes = 0;
1da177e4
LT
1875 int i;
1876
1da177e4 1877 READ_BUF(4);
06553991 1878 argp->taglen = be32_to_cpup(p++);
4aed9c46 1879 READ_BUF(argp->taglen);
1da177e4 1880 SAVEMEM(argp->tag, argp->taglen);
4aed9c46 1881 READ_BUF(8);
06553991
BF
1882 argp->minorversion = be32_to_cpup(p++);
1883 argp->opcnt = be32_to_cpup(p++);
4f0cefbf 1884 max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2);
1da177e4
LT
1885
1886 if (argp->taglen > NFSD4_MAX_TAGLEN)
1887 goto xdr_error;
1888 if (argp->opcnt > 100)
1889 goto xdr_error;
1890
e8c96f8c 1891 if (argp->opcnt > ARRAY_SIZE(argp->iops)) {
5d6031ca 1892 argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL);
1da177e4
LT
1893 if (!argp->ops) {
1894 argp->ops = argp->iops;
817cb9d4 1895 dprintk("nfsd: couldn't allocate room for COMPOUND\n");
1da177e4
LT
1896 goto xdr_error;
1897 }
1898 }
1899
e1a90ebd 1900 if (argp->minorversion > NFSD_SUPPORTED_MINOR_VERSION)
30cff1ff
BH
1901 argp->opcnt = 0;
1902
1da177e4
LT
1903 for (i = 0; i < argp->opcnt; i++) {
1904 op = &argp->ops[i];
1905 op->replay = NULL;
1906
8a61b18c 1907 READ_BUF(4);
06553991 1908 op->opnum = be32_to_cpup(p++);
1da177e4 1909
e1a90ebd
AS
1910 if (nfsd4_opnum_in_range(argp, op))
1911 op->status = nfsd4_dec_ops[op->opnum](argp, &op->u);
347e0ad9 1912 else {
1da177e4
LT
1913 op->opnum = OP_ILLEGAL;
1914 op->status = nfserr_op_illegal;
1da177e4 1915 }
1091006c
BF
1916 /*
1917 * We'll try to cache the result in the DRC if any one
1918 * op in the compound wants to be cached:
1919 */
1920 cachethis |= nfsd4_cache_this_op(op);
6ff40dec 1921
b0e35fda
BF
1922 if (op->opnum == OP_READ) {
1923 readcount++;
1924 readbytes += nfsd4_max_reply(argp->rqstp, op);
1925 } else
1926 max_reply += nfsd4_max_reply(argp->rqstp, op);
f7b43d0c
BF
1927 /*
1928 * OP_LOCK may return a conflicting lock. (Special case
1929 * because it will just skip encoding this if it runs
1930 * out of xdr buffer space, and it is the only operation
1931 * that behaves this way.)
1932 */
1933 if (op->opnum == OP_LOCK)
1934 max_reply += NFS4_OPAQUE_LIMIT;
e372ba60
BF
1935
1936 if (op->status) {
1937 argp->opcnt = i+1;
1938 break;
1939 }
1da177e4 1940 }
1091006c
BF
1941 /* Sessions make the DRC unnecessary: */
1942 if (argp->minorversion)
1943 cachethis = false;
b0e35fda 1944 svc_reserve(argp->rqstp, max_reply + readbytes);
1091006c 1945 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1da177e4 1946
a5cddc88 1947 if (readcount > 1 || max_reply > PAGE_SIZE - auth_slack)
779fb0f3 1948 clear_bit(RQ_SPLICE_OK, &argp->rqstp->rq_flags);
b0e35fda 1949
1da177e4
LT
1950 DECODE_TAIL;
1951}
1da177e4 1952
d05d5744 1953static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode)
c654b8a9
BF
1954{
1955 if (IS_I_VERSION(inode)) {
d05d5744 1956 p = xdr_encode_hyper(p, inode->i_version);
c654b8a9 1957 } else {
d05d5744
BF
1958 *p++ = cpu_to_be32(stat->ctime.tv_sec);
1959 *p++ = cpu_to_be32(stat->ctime.tv_nsec);
c654b8a9 1960 }
d05d5744 1961 return p;
c654b8a9
BF
1962}
1963
d05d5744 1964static __be32 *encode_cinfo(__be32 *p, struct nfsd4_change_info *c)
c654b8a9 1965{
d05d5744 1966 *p++ = cpu_to_be32(c->atomic);
c654b8a9 1967 if (c->change_supported) {
d05d5744
BF
1968 p = xdr_encode_hyper(p, c->before_change);
1969 p = xdr_encode_hyper(p, c->after_change);
c654b8a9 1970 } else {
d05d5744
BF
1971 *p++ = cpu_to_be32(c->before_ctime_sec);
1972 *p++ = cpu_to_be32(c->before_ctime_nsec);
1973 *p++ = cpu_to_be32(c->after_ctime_sec);
1974 *p++ = cpu_to_be32(c->after_ctime_nsec);
c654b8a9 1975 }
d05d5744 1976 return p;
c654b8a9 1977}
1da177e4 1978
81c3f413 1979/* Encode as an array of strings the string given with components
e7a0444a 1980 * separated @sep, escaped with esc_enter and esc_exit.
81c3f413 1981 */
ddd1ea56
BF
1982static __be32 nfsd4_encode_components_esc(struct xdr_stream *xdr, char sep,
1983 char *components, char esc_enter,
1984 char esc_exit)
81c3f413 1985{
ddd1ea56 1986 __be32 *p;
082d4bd7
BF
1987 __be32 pathlen;
1988 int pathlen_offset;
81c3f413 1989 int strlen, count=0;
e7a0444a 1990 char *str, *end, *next;
81c3f413
BF
1991
1992 dprintk("nfsd4_encode_components(%s)\n", components);
082d4bd7
BF
1993
1994 pathlen_offset = xdr->buf->len;
ddd1ea56
BF
1995 p = xdr_reserve_space(xdr, 4);
1996 if (!p)
81c3f413 1997 return nfserr_resource;
082d4bd7
BF
1998 p++; /* We will fill this in with @count later */
1999
81c3f413
BF
2000 end = str = components;
2001 while (*end) {
e7a0444a
WAA
2002 bool found_esc = false;
2003
2004 /* try to parse as esc_start, ..., esc_end, sep */
2005 if (*str == esc_enter) {
2006 for (; *end && (*end != esc_exit); end++)
2007 /* find esc_exit or end of string */;
2008 next = end + 1;
2009 if (*end && (!*next || *next == sep)) {
2010 str++;
2011 found_esc = true;
2012 }
2013 }
2014
2015 if (!found_esc)
2016 for (; *end && (*end != sep); end++)
2017 /* find sep or end of string */;
2018
81c3f413
BF
2019 strlen = end - str;
2020 if (strlen) {
ddd1ea56
BF
2021 p = xdr_reserve_space(xdr, strlen + 4);
2022 if (!p)
81c3f413 2023 return nfserr_resource;
0c0c267b 2024 p = xdr_encode_opaque(p, str, strlen);
81c3f413
BF
2025 count++;
2026 }
2027 else
2028 end++;
5a64e569
BC
2029 if (found_esc)
2030 end = next;
2031
81c3f413
BF
2032 str = end;
2033 }
bf7491f1 2034 pathlen = htonl(count);
082d4bd7 2035 write_bytes_to_xdr_buf(xdr->buf, pathlen_offset, &pathlen, 4);
81c3f413
BF
2036 return 0;
2037}
2038
e7a0444a
WAA
2039/* Encode as an array of strings the string given with components
2040 * separated @sep.
2041 */
ddd1ea56
BF
2042static __be32 nfsd4_encode_components(struct xdr_stream *xdr, char sep,
2043 char *components)
e7a0444a 2044{
ddd1ea56 2045 return nfsd4_encode_components_esc(xdr, sep, components, 0, 0);
e7a0444a
WAA
2046}
2047
81c3f413
BF
2048/*
2049 * encode a location element of a fs_locations structure
2050 */
ddd1ea56
BF
2051static __be32 nfsd4_encode_fs_location4(struct xdr_stream *xdr,
2052 struct nfsd4_fs_location *location)
81c3f413 2053{
b37ad28b 2054 __be32 status;
81c3f413 2055
ddd1ea56 2056 status = nfsd4_encode_components_esc(xdr, ':', location->hosts,
e7a0444a 2057 '[', ']');
81c3f413
BF
2058 if (status)
2059 return status;
ddd1ea56 2060 status = nfsd4_encode_components(xdr, '/', location->path);
81c3f413
BF
2061 if (status)
2062 return status;
81c3f413
BF
2063 return 0;
2064}
2065
2066/*
ed748aac 2067 * Encode a path in RFC3530 'pathname4' format
81c3f413 2068 */
ddd1ea56
BF
2069static __be32 nfsd4_encode_path(struct xdr_stream *xdr,
2070 const struct path *root,
2071 const struct path *path)
81c3f413 2072{
301f0268 2073 struct path cur = *path;
ddd1ea56 2074 __be32 *p;
ed748aac
TM
2075 struct dentry **components = NULL;
2076 unsigned int ncomponents = 0;
2077 __be32 err = nfserr_jukebox;
81c3f413 2078
ed748aac 2079 dprintk("nfsd4_encode_components(");
81c3f413 2080
ed748aac
TM
2081 path_get(&cur);
2082 /* First walk the path up to the nfsd root, and store the
2083 * dentries/path components in an array.
2084 */
2085 for (;;) {
b77a4b2e 2086 if (path_equal(&cur, root))
ed748aac
TM
2087 break;
2088 if (cur.dentry == cur.mnt->mnt_root) {
2089 if (follow_up(&cur))
2090 continue;
2091 goto out_free;
2092 }
2093 if ((ncomponents & 15) == 0) {
2094 struct dentry **new;
2095 new = krealloc(components,
2096 sizeof(*new) * (ncomponents + 16),
2097 GFP_KERNEL);
2098 if (!new)
2099 goto out_free;
2100 components = new;
2101 }
2102 components[ncomponents++] = cur.dentry;
2103 cur.dentry = dget_parent(cur.dentry);
2104 }
ddd1ea56
BF
2105 err = nfserr_resource;
2106 p = xdr_reserve_space(xdr, 4);
2107 if (!p)
ed748aac 2108 goto out_free;
c373b0a4 2109 *p++ = cpu_to_be32(ncomponents);
ed748aac
TM
2110
2111 while (ncomponents) {
2112 struct dentry *dentry = components[ncomponents - 1];
301f0268 2113 unsigned int len;
ed748aac 2114
301f0268
AV
2115 spin_lock(&dentry->d_lock);
2116 len = dentry->d_name.len;
ddd1ea56
BF
2117 p = xdr_reserve_space(xdr, len + 4);
2118 if (!p) {
301f0268 2119 spin_unlock(&dentry->d_lock);
ed748aac 2120 goto out_free;
301f0268 2121 }
0c0c267b 2122 p = xdr_encode_opaque(p, dentry->d_name.name, len);
a455589f 2123 dprintk("/%pd", dentry);
301f0268 2124 spin_unlock(&dentry->d_lock);
ed748aac
TM
2125 dput(dentry);
2126 ncomponents--;
81c3f413 2127 }
ed748aac 2128
ed748aac
TM
2129 err = 0;
2130out_free:
2131 dprintk(")\n");
2132 while (ncomponents)
2133 dput(components[--ncomponents]);
2134 kfree(components);
2135 path_put(&cur);
2136 return err;
2137}
2138
ddd1ea56
BF
2139static __be32 nfsd4_encode_fsloc_fsroot(struct xdr_stream *xdr,
2140 struct svc_rqst *rqstp, const struct path *path)
ed748aac
TM
2141{
2142 struct svc_export *exp_ps;
2143 __be32 res;
2144
2145 exp_ps = rqst_find_fsidzero_export(rqstp);
2146 if (IS_ERR(exp_ps))
2147 return nfserrno(PTR_ERR(exp_ps));
ddd1ea56 2148 res = nfsd4_encode_path(xdr, &exp_ps->ex_path, path);
ed748aac
TM
2149 exp_put(exp_ps);
2150 return res;
81c3f413
BF
2151}
2152
2153/*
2154 * encode a fs_locations structure
2155 */
ddd1ea56
BF
2156static __be32 nfsd4_encode_fs_locations(struct xdr_stream *xdr,
2157 struct svc_rqst *rqstp, struct svc_export *exp)
81c3f413 2158{
b37ad28b 2159 __be32 status;
cc45f017 2160 int i;
ddd1ea56 2161 __be32 *p;
81c3f413 2162 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs;
81c3f413 2163
ddd1ea56 2164 status = nfsd4_encode_fsloc_fsroot(xdr, rqstp, &exp->ex_path);
81c3f413
BF
2165 if (status)
2166 return status;
ddd1ea56
BF
2167 p = xdr_reserve_space(xdr, 4);
2168 if (!p)
81c3f413 2169 return nfserr_resource;
c373b0a4 2170 *p++ = cpu_to_be32(fslocs->locations_count);
81c3f413 2171 for (i=0; i<fslocs->locations_count; i++) {
ddd1ea56 2172 status = nfsd4_encode_fs_location4(xdr, &fslocs->locations[i]);
81c3f413
BF
2173 if (status)
2174 return status;
2175 }
81c3f413
BF
2176 return 0;
2177}
1da177e4 2178
3d2544b1
BF
2179static u32 nfs4_file_type(umode_t mode)
2180{
2181 switch (mode & S_IFMT) {
2182 case S_IFIFO: return NF4FIFO;
2183 case S_IFCHR: return NF4CHR;
2184 case S_IFDIR: return NF4DIR;
2185 case S_IFBLK: return NF4BLK;
2186 case S_IFLNK: return NF4LNK;
2187 case S_IFREG: return NF4REG;
2188 case S_IFSOCK: return NF4SOCK;
2189 default: return NF4BAD;
2190 };
2191}
1da177e4 2192
b37ad28b 2193static inline __be32
ddd1ea56
BF
2194nfsd4_encode_aclname(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2195 struct nfs4_ace *ace)
1da177e4 2196{
3554116d 2197 if (ace->whotype != NFS4_ACL_WHO_NAMED)
ddd1ea56 2198 return nfs4_acl_write_who(xdr, ace->whotype);
3554116d 2199 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
ddd1ea56 2200 return nfsd4_encode_group(xdr, rqstp, ace->who_gid);
3554116d 2201 else
ddd1ea56 2202 return nfsd4_encode_user(xdr, rqstp, ace->who_uid);
1da177e4
LT
2203}
2204
6896f15a 2205static inline __be32
8a4c3926 2206nfsd4_encode_layout_types(struct xdr_stream *xdr, u32 layout_types)
6896f15a 2207{
8a4c3926
JL
2208 __be32 *p;
2209 unsigned long i = hweight_long(layout_types);
6896f15a 2210
8a4c3926
JL
2211 p = xdr_reserve_space(xdr, 4 + 4 * i);
2212 if (!p)
2213 return nfserr_resource;
2214
2215 *p++ = cpu_to_be32(i);
2216
2217 for (i = LAYOUT_NFSV4_1_FILES; i < LAYOUT_TYPE_MAX; ++i)
2218 if (layout_types & (1 << i))
2219 *p++ = cpu_to_be32(i);
6896f15a
KM
2220
2221 return 0;
2222}
2223
42ca0993
BF
2224#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
2225 FATTR4_WORD0_RDATTR_ERROR)
2226#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID
c2227a39 2227#define WORD2_ABSENT_FS_ATTRS 0
42ca0993 2228
18032ca0
DQ
2229#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
2230static inline __be32
ddd1ea56
BF
2231nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2232 void *context, int len)
18032ca0 2233{
ddd1ea56 2234 __be32 *p;
18032ca0 2235
ddd1ea56
BF
2236 p = xdr_reserve_space(xdr, len + 4 + 4 + 4);
2237 if (!p)
18032ca0
DQ
2238 return nfserr_resource;
2239
2240 /*
2241 * For now we use a 0 here to indicate the null translation; in
2242 * the future we may place a call to translation code here.
2243 */
c373b0a4
BF
2244 *p++ = cpu_to_be32(0); /* lfs */
2245 *p++ = cpu_to_be32(0); /* pi */
18032ca0 2246 p = xdr_encode_opaque(p, context, len);
18032ca0
DQ
2247 return 0;
2248}
2249#else
2250static inline __be32
ddd1ea56
BF
2251nfsd4_encode_security_label(struct xdr_stream *xdr, struct svc_rqst *rqstp,
2252 void *context, int len)
18032ca0
DQ
2253{ return 0; }
2254#endif
2255
c2227a39 2256static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *bmval2, u32 *rdattr_err)
42ca0993
BF
2257{
2258 /* As per referral draft: */
2259 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS ||
2260 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) {
2261 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR ||
2262 *bmval0 & FATTR4_WORD0_FS_LOCATIONS)
2263 *rdattr_err = NFSERR_MOVED;
2264 else
2265 return nfserr_moved;
2266 }
2267 *bmval0 &= WORD0_ABSENT_FS_ATTRS;
2268 *bmval1 &= WORD1_ABSENT_FS_ATTRS;
c2227a39 2269 *bmval2 &= WORD2_ABSENT_FS_ATTRS;
42ca0993
BF
2270 return 0;
2271}
1da177e4 2272
ae7095a7
BF
2273
2274static int get_parent_attributes(struct svc_export *exp, struct kstat *stat)
2275{
2276 struct path path = exp->ex_path;
2277 int err;
2278
2279 path_get(&path);
2280 while (follow_up(&path)) {
2281 if (path.dentry != path.mnt->mnt_root)
2282 break;
2283 }
3dadecce 2284 err = vfs_getattr(&path, stat);
ae7095a7
BF
2285 path_put(&path);
2286 return err;
2287}
2288
75976de6
KM
2289static __be32
2290nfsd4_encode_bitmap(struct xdr_stream *xdr, u32 bmval0, u32 bmval1, u32 bmval2)
2291{
2292 __be32 *p;
2293
2294 if (bmval2) {
2295 p = xdr_reserve_space(xdr, 16);
2296 if (!p)
2297 goto out_resource;
2298 *p++ = cpu_to_be32(3);
2299 *p++ = cpu_to_be32(bmval0);
2300 *p++ = cpu_to_be32(bmval1);
2301 *p++ = cpu_to_be32(bmval2);
2302 } else if (bmval1) {
2303 p = xdr_reserve_space(xdr, 12);
2304 if (!p)
2305 goto out_resource;
2306 *p++ = cpu_to_be32(2);
2307 *p++ = cpu_to_be32(bmval0);
2308 *p++ = cpu_to_be32(bmval1);
2309 } else {
2310 p = xdr_reserve_space(xdr, 8);
2311 if (!p)
2312 goto out_resource;
2313 *p++ = cpu_to_be32(1);
2314 *p++ = cpu_to_be32(bmval0);
2315 }
2316
2317 return 0;
2318out_resource:
2319 return nfserr_resource;
2320}
2321
1da177e4
LT
2322/*
2323 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle
2324 * ourselves.
1da177e4 2325 */
da2ebce6 2326static __be32
d5184658
BF
2327nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,
2328 struct svc_export *exp,
2329 struct dentry *dentry, u32 *bmval,
406a7ea9 2330 struct svc_rqst *rqstp, int ignore_crossmnt)
1da177e4
LT
2331{
2332 u32 bmval0 = bmval[0];
2333 u32 bmval1 = bmval[1];
7e705706 2334 u32 bmval2 = bmval[2];
1da177e4 2335 struct kstat stat;
d50e6136 2336 struct svc_fh *tempfh = NULL;
1da177e4 2337 struct kstatfs statfs;
ddd1ea56 2338 __be32 *p;
1fcea5b2 2339 int starting_len = xdr->buf->len;
082d4bd7
BF
2340 int attrlen_offset;
2341 __be32 attrlen;
1da177e4
LT
2342 u32 dummy;
2343 u64 dummy64;
42ca0993 2344 u32 rdattr_err = 0;
b37ad28b 2345 __be32 status;
b8dd7b9a 2346 int err;
1da177e4 2347 struct nfs4_acl *acl = NULL;
18032ca0
DQ
2348 void *context = NULL;
2349 int contextlen;
2350 bool contextsupport = false;
7e705706
AA
2351 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2352 u32 minorversion = resp->cstate.minorversion;
ebabe9a9
CH
2353 struct path path = {
2354 .mnt = exp->ex_path.mnt,
2355 .dentry = dentry,
2356 };
3d733711 2357 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
1da177e4
LT
2358
2359 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1);
916d2d84 2360 BUG_ON(!nfsd_attrs_supported(minorversion, bmval));
1da177e4 2361
42ca0993 2362 if (exp->ex_fslocs.migrated) {
c2227a39 2363 status = fattr_handle_absent_fs(&bmval0, &bmval1, &bmval2, &rdattr_err);
42ca0993
BF
2364 if (status)
2365 goto out;
2366 }
2367
3dadecce 2368 err = vfs_getattr(&path, &stat);
b8dd7b9a 2369 if (err)
1da177e4 2370 goto out_nfserr;
12337901
CH
2371 if ((bmval0 & (FATTR4_WORD0_FILES_AVAIL | FATTR4_WORD0_FILES_FREE |
2372 FATTR4_WORD0_FILES_TOTAL | FATTR4_WORD0_MAXNAME)) ||
1da177e4
LT
2373 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE |
2374 FATTR4_WORD1_SPACE_TOTAL))) {
ebabe9a9 2375 err = vfs_statfs(&path, &statfs);
b8dd7b9a 2376 if (err)
1da177e4
LT
2377 goto out_nfserr;
2378 }
2379 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) {
d50e6136
BF
2380 tempfh = kmalloc(sizeof(struct svc_fh), GFP_KERNEL);
2381 status = nfserr_jukebox;
2382 if (!tempfh)
2383 goto out;
2384 fh_init(tempfh, NFS4_FHSIZE);
2385 status = fh_compose(tempfh, exp, dentry, NULL);
1da177e4
LT
2386 if (status)
2387 goto out;
d50e6136 2388 fhp = tempfh;
1da177e4 2389 }
0c9d65e7 2390 if (bmval0 & FATTR4_WORD0_ACL) {
b8dd7b9a 2391 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl);
0c9d65e7
AG
2392 if (err == -EOPNOTSUPP)
2393 bmval0 &= ~FATTR4_WORD0_ACL;
2394 else if (err == -EINVAL) {
2395 status = nfserr_attrnotsupp;
2396 goto out;
2397 } else if (err != 0)
2398 goto out_nfserr;
1da177e4 2399 }
1da177e4 2400
18032ca0 2401#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
c2227a39
KM
2402 if ((bmval2 & FATTR4_WORD2_SECURITY_LABEL) ||
2403 bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
2b0143b5 2404 err = security_inode_getsecctx(d_inode(dentry),
18032ca0
DQ
2405 &context, &contextlen);
2406 contextsupport = (err == 0);
2407 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2408 if (err == -EOPNOTSUPP)
2409 bmval2 &= ~FATTR4_WORD2_SECURITY_LABEL;
2410 else if (err)
2411 goto out_nfserr;
2412 }
2413 }
2414#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
2415
75976de6
KM
2416 status = nfsd4_encode_bitmap(xdr, bmval0, bmval1, bmval2);
2417 if (status)
2418 goto out;
082d4bd7
BF
2419
2420 attrlen_offset = xdr->buf->len;
ddd1ea56
BF
2421 p = xdr_reserve_space(xdr, 4);
2422 if (!p)
2423 goto out_resource;
082d4bd7 2424 p++; /* to be backfilled later */
1da177e4
LT
2425
2426 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {
916d2d84 2427 u32 *supp = nfsd_suppattrs[minorversion];
7e705706 2428
0c9d65e7 2429 if (!IS_POSIXACL(dentry->d_inode))
916d2d84 2430 supp[0] &= ~FATTR4_WORD0_ACL;
18032ca0 2431 if (!contextsupport)
916d2d84
BF
2432 supp[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
2433 if (!supp[2]) {
ddd1ea56
BF
2434 p = xdr_reserve_space(xdr, 12);
2435 if (!p)
2b44f1ba 2436 goto out_resource;
c373b0a4 2437 *p++ = cpu_to_be32(2);
916d2d84
BF
2438 *p++ = cpu_to_be32(supp[0]);
2439 *p++ = cpu_to_be32(supp[1]);
7e705706 2440 } else {
ddd1ea56
BF
2441 p = xdr_reserve_space(xdr, 16);
2442 if (!p)
2b44f1ba 2443 goto out_resource;
c373b0a4 2444 *p++ = cpu_to_be32(3);
916d2d84
BF
2445 *p++ = cpu_to_be32(supp[0]);
2446 *p++ = cpu_to_be32(supp[1]);
2447 *p++ = cpu_to_be32(supp[2]);
7e705706 2448 }
1da177e4
LT
2449 }
2450 if (bmval0 & FATTR4_WORD0_TYPE) {
ddd1ea56
BF
2451 p = xdr_reserve_space(xdr, 4);
2452 if (!p)
1da177e4 2453 goto out_resource;
3d2544b1 2454 dummy = nfs4_file_type(stat.mode);
6b6d8137
BF
2455 if (dummy == NF4BAD) {
2456 status = nfserr_serverfault;
2457 goto out;
2458 }
c373b0a4 2459 *p++ = cpu_to_be32(dummy);
1da177e4
LT
2460 }
2461 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) {
ddd1ea56
BF
2462 p = xdr_reserve_space(xdr, 4);
2463 if (!p)
1da177e4 2464 goto out_resource;
49640001 2465 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK)
c373b0a4 2466 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT);
49640001 2467 else
c373b0a4
BF
2468 *p++ = cpu_to_be32(NFS4_FH_PERSISTENT|
2469 NFS4_FH_VOL_RENAME);
1da177e4
LT
2470 }
2471 if (bmval0 & FATTR4_WORD0_CHANGE) {
ddd1ea56
BF
2472 p = xdr_reserve_space(xdr, 8);
2473 if (!p)
1da177e4 2474 goto out_resource;
2b0143b5 2475 p = encode_change(p, &stat, d_inode(dentry));
1da177e4
LT
2476 }
2477 if (bmval0 & FATTR4_WORD0_SIZE) {
ddd1ea56
BF
2478 p = xdr_reserve_space(xdr, 8);
2479 if (!p)
1da177e4 2480 goto out_resource;
b64c7f3b 2481 p = xdr_encode_hyper(p, stat.size);
1da177e4
LT
2482 }
2483 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) {
ddd1ea56
BF
2484 p = xdr_reserve_space(xdr, 4);
2485 if (!p)
1da177e4 2486 goto out_resource;
c373b0a4 2487 *p++ = cpu_to_be32(1);
1da177e4
LT
2488 }
2489 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) {
ddd1ea56
BF
2490 p = xdr_reserve_space(xdr, 4);
2491 if (!p)
1da177e4 2492 goto out_resource;
c373b0a4 2493 *p++ = cpu_to_be32(1);
1da177e4
LT
2494 }
2495 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) {
ddd1ea56
BF
2496 p = xdr_reserve_space(xdr, 4);
2497 if (!p)
1da177e4 2498 goto out_resource;
c373b0a4 2499 *p++ = cpu_to_be32(0);
1da177e4
LT
2500 }
2501 if (bmval0 & FATTR4_WORD0_FSID) {
ddd1ea56
BF
2502 p = xdr_reserve_space(xdr, 16);
2503 if (!p)
1da177e4 2504 goto out_resource;
42ca0993 2505 if (exp->ex_fslocs.migrated) {
b64c7f3b
BF
2506 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MAJOR);
2507 p = xdr_encode_hyper(p, NFS4_REFERRAL_FSID_MINOR);
af6a4e28
N
2508 } else switch(fsid_source(fhp)) {
2509 case FSIDSOURCE_FSID:
b64c7f3b
BF
2510 p = xdr_encode_hyper(p, (u64)exp->ex_fsid);
2511 p = xdr_encode_hyper(p, (u64)0);
af6a4e28
N
2512 break;
2513 case FSIDSOURCE_DEV:
c373b0a4
BF
2514 *p++ = cpu_to_be32(0);
2515 *p++ = cpu_to_be32(MAJOR(stat.dev));
2516 *p++ = cpu_to_be32(0);
2517 *p++ = cpu_to_be32(MINOR(stat.dev));
af6a4e28
N
2518 break;
2519 case FSIDSOURCE_UUID:
94eb3689
KM
2520 p = xdr_encode_opaque_fixed(p, exp->ex_uuid,
2521 EX_UUID_LEN);
af6a4e28 2522 break;
1da177e4
LT
2523 }
2524 }
2525 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) {
ddd1ea56
BF
2526 p = xdr_reserve_space(xdr, 4);
2527 if (!p)
1da177e4 2528 goto out_resource;
c373b0a4 2529 *p++ = cpu_to_be32(0);
1da177e4
LT
2530 }
2531 if (bmval0 & FATTR4_WORD0_LEASE_TIME) {
ddd1ea56
BF
2532 p = xdr_reserve_space(xdr, 4);
2533 if (!p)
1da177e4 2534 goto out_resource;
c373b0a4 2535 *p++ = cpu_to_be32(nn->nfsd4_lease);
1da177e4
LT
2536 }
2537 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) {
ddd1ea56
BF
2538 p = xdr_reserve_space(xdr, 4);
2539 if (!p)
1da177e4 2540 goto out_resource;
c373b0a4 2541 *p++ = cpu_to_be32(rdattr_err);
1da177e4
LT
2542 }
2543 if (bmval0 & FATTR4_WORD0_ACL) {
2544 struct nfs4_ace *ace;
1da177e4
LT
2545
2546 if (acl == NULL) {
ddd1ea56
BF
2547 p = xdr_reserve_space(xdr, 4);
2548 if (!p)
1da177e4
LT
2549 goto out_resource;
2550
c373b0a4 2551 *p++ = cpu_to_be32(0);
1da177e4
LT
2552 goto out_acl;
2553 }
ddd1ea56
BF
2554 p = xdr_reserve_space(xdr, 4);
2555 if (!p)
1da177e4 2556 goto out_resource;
c373b0a4 2557 *p++ = cpu_to_be32(acl->naces);
1da177e4 2558
28e05dd8 2559 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
ddd1ea56
BF
2560 p = xdr_reserve_space(xdr, 4*3);
2561 if (!p)
1da177e4 2562 goto out_resource;
c373b0a4
BF
2563 *p++ = cpu_to_be32(ace->type);
2564 *p++ = cpu_to_be32(ace->flag);
2565 *p++ = cpu_to_be32(ace->access_mask &
2566 NFS4_ACE_MASK_ALL);
ddd1ea56 2567 status = nfsd4_encode_aclname(xdr, rqstp, ace);
1da177e4
LT
2568 if (status)
2569 goto out;
2570 }
2571 }
2572out_acl:
2573 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) {
ddd1ea56
BF
2574 p = xdr_reserve_space(xdr, 4);
2575 if (!p)
1da177e4 2576 goto out_resource;
0c9d65e7 2577 *p++ = cpu_to_be32(IS_POSIXACL(dentry->d_inode) ?
1da177e4
LT
2578 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0);
2579 }
2580 if (bmval0 & FATTR4_WORD0_CANSETTIME) {
ddd1ea56
BF
2581 p = xdr_reserve_space(xdr, 4);
2582 if (!p)
1da177e4 2583 goto out_resource;
c373b0a4 2584 *p++ = cpu_to_be32(1);
1da177e4
LT
2585 }
2586 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) {
ddd1ea56
BF
2587 p = xdr_reserve_space(xdr, 4);
2588 if (!p)
1da177e4 2589 goto out_resource;
c373b0a4 2590 *p++ = cpu_to_be32(0);
1da177e4
LT
2591 }
2592 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) {
ddd1ea56
BF
2593 p = xdr_reserve_space(xdr, 4);
2594 if (!p)
1da177e4 2595 goto out_resource;
c373b0a4 2596 *p++ = cpu_to_be32(1);
1da177e4
LT
2597 }
2598 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) {
ddd1ea56
BF
2599 p = xdr_reserve_space(xdr, 4);
2600 if (!p)
1da177e4 2601 goto out_resource;
c373b0a4 2602 *p++ = cpu_to_be32(1);
1da177e4
LT
2603 }
2604 if (bmval0 & FATTR4_WORD0_FILEHANDLE) {
ddd1ea56
BF
2605 p = xdr_reserve_space(xdr, fhp->fh_handle.fh_size + 4);
2606 if (!p)
1da177e4 2607 goto out_resource;
0c0c267b
BF
2608 p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base,
2609 fhp->fh_handle.fh_size);
1da177e4
LT
2610 }
2611 if (bmval0 & FATTR4_WORD0_FILEID) {
ddd1ea56
BF
2612 p = xdr_reserve_space(xdr, 8);
2613 if (!p)
1da177e4 2614 goto out_resource;
b64c7f3b 2615 p = xdr_encode_hyper(p, stat.ino);
1da177e4
LT
2616 }
2617 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) {
ddd1ea56
BF
2618 p = xdr_reserve_space(xdr, 8);
2619 if (!p)
1da177e4 2620 goto out_resource;
b64c7f3b 2621 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
1da177e4
LT
2622 }
2623 if (bmval0 & FATTR4_WORD0_FILES_FREE) {
ddd1ea56
BF
2624 p = xdr_reserve_space(xdr, 8);
2625 if (!p)
1da177e4 2626 goto out_resource;
b64c7f3b 2627 p = xdr_encode_hyper(p, (u64) statfs.f_ffree);
1da177e4
LT
2628 }
2629 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) {
ddd1ea56
BF
2630 p = xdr_reserve_space(xdr, 8);
2631 if (!p)
1da177e4 2632 goto out_resource;
b64c7f3b 2633 p = xdr_encode_hyper(p, (u64) statfs.f_files);
1da177e4 2634 }
81c3f413 2635 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) {
ddd1ea56 2636 status = nfsd4_encode_fs_locations(xdr, rqstp, exp);
81c3f413
BF
2637 if (status)
2638 goto out;
2639 }
1da177e4 2640 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) {
ddd1ea56
BF
2641 p = xdr_reserve_space(xdr, 4);
2642 if (!p)
1da177e4 2643 goto out_resource;
c373b0a4 2644 *p++ = cpu_to_be32(1);
1da177e4
LT
2645 }
2646 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) {
ddd1ea56
BF
2647 p = xdr_reserve_space(xdr, 8);
2648 if (!p)
1da177e4 2649 goto out_resource;
b64c7f3b 2650 p = xdr_encode_hyper(p, exp->ex_path.mnt->mnt_sb->s_maxbytes);
1da177e4
LT
2651 }
2652 if (bmval0 & FATTR4_WORD0_MAXLINK) {
ddd1ea56
BF
2653 p = xdr_reserve_space(xdr, 4);
2654 if (!p)
1da177e4 2655 goto out_resource;
c373b0a4 2656 *p++ = cpu_to_be32(255);
1da177e4
LT
2657 }
2658 if (bmval0 & FATTR4_WORD0_MAXNAME) {
ddd1ea56
BF
2659 p = xdr_reserve_space(xdr, 4);
2660 if (!p)
1da177e4 2661 goto out_resource;
c373b0a4 2662 *p++ = cpu_to_be32(statfs.f_namelen);
1da177e4
LT
2663 }
2664 if (bmval0 & FATTR4_WORD0_MAXREAD) {
ddd1ea56
BF
2665 p = xdr_reserve_space(xdr, 8);
2666 if (!p)
1da177e4 2667 goto out_resource;
b64c7f3b 2668 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
1da177e4
LT
2669 }
2670 if (bmval0 & FATTR4_WORD0_MAXWRITE) {
ddd1ea56
BF
2671 p = xdr_reserve_space(xdr, 8);
2672 if (!p)
1da177e4 2673 goto out_resource;
b64c7f3b 2674 p = xdr_encode_hyper(p, (u64) svc_max_payload(rqstp));
1da177e4
LT
2675 }
2676 if (bmval1 & FATTR4_WORD1_MODE) {
ddd1ea56
BF
2677 p = xdr_reserve_space(xdr, 4);
2678 if (!p)
1da177e4 2679 goto out_resource;
c373b0a4 2680 *p++ = cpu_to_be32(stat.mode & S_IALLUGO);
1da177e4
LT
2681 }
2682 if (bmval1 & FATTR4_WORD1_NO_TRUNC) {
ddd1ea56
BF
2683 p = xdr_reserve_space(xdr, 4);
2684 if (!p)
1da177e4 2685 goto out_resource;
c373b0a4 2686 *p++ = cpu_to_be32(1);
1da177e4
LT
2687 }
2688 if (bmval1 & FATTR4_WORD1_NUMLINKS) {
ddd1ea56
BF
2689 p = xdr_reserve_space(xdr, 4);
2690 if (!p)
1da177e4 2691 goto out_resource;
c373b0a4 2692 *p++ = cpu_to_be32(stat.nlink);
1da177e4
LT
2693 }
2694 if (bmval1 & FATTR4_WORD1_OWNER) {
ddd1ea56 2695 status = nfsd4_encode_user(xdr, rqstp, stat.uid);
1da177e4
LT
2696 if (status)
2697 goto out;
2698 }
2699 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) {
ddd1ea56 2700 status = nfsd4_encode_group(xdr, rqstp, stat.gid);
1da177e4
LT
2701 if (status)
2702 goto out;
2703 }
2704 if (bmval1 & FATTR4_WORD1_RAWDEV) {
ddd1ea56
BF
2705 p = xdr_reserve_space(xdr, 8);
2706 if (!p)
1da177e4 2707 goto out_resource;
c373b0a4
BF
2708 *p++ = cpu_to_be32((u32) MAJOR(stat.rdev));
2709 *p++ = cpu_to_be32((u32) MINOR(stat.rdev));
1da177e4
LT
2710 }
2711 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) {
ddd1ea56
BF
2712 p = xdr_reserve_space(xdr, 8);
2713 if (!p)
1da177e4
LT
2714 goto out_resource;
2715 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize;
b64c7f3b 2716 p = xdr_encode_hyper(p, dummy64);
1da177e4
LT
2717 }
2718 if (bmval1 & FATTR4_WORD1_SPACE_FREE) {
ddd1ea56
BF
2719 p = xdr_reserve_space(xdr, 8);
2720 if (!p)
1da177e4
LT
2721 goto out_resource;
2722 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize;
b64c7f3b 2723 p = xdr_encode_hyper(p, dummy64);
1da177e4
LT
2724 }
2725 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) {
ddd1ea56
BF
2726 p = xdr_reserve_space(xdr, 8);
2727 if (!p)
1da177e4
LT
2728 goto out_resource;
2729 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize;
b64c7f3b 2730 p = xdr_encode_hyper(p, dummy64);
1da177e4
LT
2731 }
2732 if (bmval1 & FATTR4_WORD1_SPACE_USED) {
ddd1ea56
BF
2733 p = xdr_reserve_space(xdr, 8);
2734 if (!p)
1da177e4
LT
2735 goto out_resource;
2736 dummy64 = (u64)stat.blocks << 9;
b64c7f3b 2737 p = xdr_encode_hyper(p, dummy64);
1da177e4
LT
2738 }
2739 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) {
ddd1ea56
BF
2740 p = xdr_reserve_space(xdr, 12);
2741 if (!p)
1da177e4 2742 goto out_resource;
b64c7f3b 2743 p = xdr_encode_hyper(p, (s64)stat.atime.tv_sec);
c373b0a4 2744 *p++ = cpu_to_be32(stat.atime.tv_nsec);
1da177e4
LT
2745 }
2746 if (bmval1 & FATTR4_WORD1_TIME_DELTA) {
ddd1ea56
BF
2747 p = xdr_reserve_space(xdr, 12);
2748 if (!p)
1da177e4 2749 goto out_resource;
c373b0a4
BF
2750 *p++ = cpu_to_be32(0);
2751 *p++ = cpu_to_be32(1);
2752 *p++ = cpu_to_be32(0);
1da177e4
LT
2753 }
2754 if (bmval1 & FATTR4_WORD1_TIME_METADATA) {
ddd1ea56
BF
2755 p = xdr_reserve_space(xdr, 12);
2756 if (!p)
1da177e4 2757 goto out_resource;
b64c7f3b 2758 p = xdr_encode_hyper(p, (s64)stat.ctime.tv_sec);
c373b0a4 2759 *p++ = cpu_to_be32(stat.ctime.tv_nsec);
1da177e4
LT
2760 }
2761 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) {
ddd1ea56
BF
2762 p = xdr_reserve_space(xdr, 12);
2763 if (!p)
1da177e4 2764 goto out_resource;
b64c7f3b 2765 p = xdr_encode_hyper(p, (s64)stat.mtime.tv_sec);
c373b0a4 2766 *p++ = cpu_to_be32(stat.mtime.tv_nsec);
1da177e4
LT
2767 }
2768 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) {
0a2050d7
KM
2769 struct kstat parent_stat;
2770 u64 ino = stat.ino;
2771
ddd1ea56
BF
2772 p = xdr_reserve_space(xdr, 8);
2773 if (!p)
1da177e4 2774 goto out_resource;
406a7ea9
FF
2775 /*
2776 * Get parent's attributes if not ignoring crossmount
2777 * and this is the root of a cross-mounted filesystem.
2778 */
2779 if (ignore_crossmnt == 0 &&
0a2050d7
KM
2780 dentry == exp->ex_path.mnt->mnt_root) {
2781 err = get_parent_attributes(exp, &parent_stat);
2782 if (err)
2783 goto out_nfserr;
2784 ino = parent_stat.ino;
2785 }
2786 p = xdr_encode_hyper(p, ino);
1da177e4 2787 }
9cf514cc 2788#ifdef CONFIG_NFSD_PNFS
6896f15a 2789 if (bmval1 & FATTR4_WORD1_FS_LAYOUT_TYPES) {
8a4c3926 2790 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
6896f15a
KM
2791 if (status)
2792 goto out;
2793 }
2794
2795 if (bmval2 & FATTR4_WORD2_LAYOUT_TYPES) {
8a4c3926 2796 status = nfsd4_encode_layout_types(xdr, exp->ex_layout_types);
6896f15a
KM
2797 if (status)
2798 goto out;
9cf514cc
CH
2799 }
2800
2801 if (bmval2 & FATTR4_WORD2_LAYOUT_BLKSIZE) {
2802 p = xdr_reserve_space(xdr, 4);
2803 if (!p)
2804 goto out_resource;
2805 *p++ = cpu_to_be32(stat.blksize);
2806 }
2807#endif /* CONFIG_NFSD_PNFS */
8c18f205 2808 if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
75976de6
KM
2809 status = nfsd4_encode_bitmap(xdr, NFSD_SUPPATTR_EXCLCREAT_WORD0,
2810 NFSD_SUPPATTR_EXCLCREAT_WORD1,
2811 NFSD_SUPPATTR_EXCLCREAT_WORD2);
2812 if (status)
2813 goto out;
8c18f205 2814 }
7e705706 2815
7d580722
KM
2816 if (bmval2 & FATTR4_WORD2_SECURITY_LABEL) {
2817 status = nfsd4_encode_security_label(xdr, rqstp, context,
2818 contextlen);
2819 if (status)
2820 goto out;
2821 }
2822
082d4bd7
BF
2823 attrlen = htonl(xdr->buf->len - attrlen_offset - 4);
2824 write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4);
1da177e4
LT
2825 status = nfs_ok;
2826
2827out:
ba4e55bb 2828#ifdef CONFIG_NFSD_V4_SECURITY_LABEL
18032ca0
DQ
2829 if (context)
2830 security_release_secctx(context, contextlen);
ba4e55bb 2831#endif /* CONFIG_NFSD_V4_SECURITY_LABEL */
28e05dd8 2832 kfree(acl);
18df11d0 2833 if (tempfh) {
d50e6136 2834 fh_put(tempfh);
18df11d0
YZ
2835 kfree(tempfh);
2836 }
1fcea5b2
BF
2837 if (status)
2838 xdr_truncate_encode(xdr, starting_len);
1da177e4
LT
2839 return status;
2840out_nfserr:
b8dd7b9a 2841 status = nfserrno(err);
1da177e4
LT
2842 goto out;
2843out_resource:
1da177e4
LT
2844 status = nfserr_resource;
2845 goto out;
1da177e4
LT
2846}
2847
2825a7f9
BF
2848static void svcxdr_init_encode_from_buffer(struct xdr_stream *xdr,
2849 struct xdr_buf *buf, __be32 *p, int bytes)
2850{
2851 xdr->scratch.iov_len = 0;
2852 memset(buf, 0, sizeof(struct xdr_buf));
2853 buf->head[0].iov_base = p;
2854 buf->head[0].iov_len = 0;
2855 buf->len = 0;
2856 xdr->buf = buf;
2857 xdr->iov = buf->head;
2858 xdr->p = p;
2859 xdr->end = (void *)p + bytes;
2860 buf->buflen = bytes;
2861}
2862
d5184658
BF
2863__be32 nfsd4_encode_fattr_to_buf(__be32 **p, int words,
2864 struct svc_fh *fhp, struct svc_export *exp,
2865 struct dentry *dentry, u32 *bmval,
2866 struct svc_rqst *rqstp, int ignore_crossmnt)
2867{
2825a7f9 2868 struct xdr_buf dummy;
d5184658
BF
2869 struct xdr_stream xdr;
2870 __be32 ret;
2871
2825a7f9 2872 svcxdr_init_encode_from_buffer(&xdr, &dummy, *p, words << 2);
d5184658
BF
2873 ret = nfsd4_encode_fattr(&xdr, fhp, exp, dentry, bmval, rqstp,
2874 ignore_crossmnt);
2875 *p = xdr.p;
2876 return ret;
2877}
2878
c0ce6ec8
BF
2879static inline int attributes_need_mount(u32 *bmval)
2880{
2881 if (bmval[0] & ~(FATTR4_WORD0_RDATTR_ERROR | FATTR4_WORD0_LEASE_TIME))
2882 return 1;
2883 if (bmval[1] & ~FATTR4_WORD1_MOUNTED_ON_FILEID)
2884 return 1;
2885 return 0;
2886}
2887
b37ad28b 2888static __be32
561f0ed4
BF
2889nfsd4_encode_dirent_fattr(struct xdr_stream *xdr, struct nfsd4_readdir *cd,
2890 const char *name, int namlen)
1da177e4
LT
2891{
2892 struct svc_export *exp = cd->rd_fhp->fh_export;
2893 struct dentry *dentry;
b37ad28b 2894 __be32 nfserr;
406a7ea9 2895 int ignore_crossmnt = 0;
1da177e4 2896
bbddca8e 2897 dentry = lookup_one_len_unlocked(name, cd->rd_fhp->fh_dentry, namlen);
1da177e4
LT
2898 if (IS_ERR(dentry))
2899 return nfserrno(PTR_ERR(dentry));
2b0143b5 2900 if (d_really_is_negative(dentry)) {
b2c0cea6 2901 /*
bbddca8e
N
2902 * we're not holding the i_mutex here, so there's
2903 * a window where this directory entry could have gone
2904 * away.
b2c0cea6
BF
2905 */
2906 dput(dentry);
2907 return nfserr_noent;
2908 }
1da177e4
LT
2909
2910 exp_get(exp);
406a7ea9
FF
2911 /*
2912 * In the case of a mountpoint, the client may be asking for
2913 * attributes that are only properties of the underlying filesystem
2914 * as opposed to the cross-mounted file system. In such a case,
2915 * we will not follow the cross mount and will fill the attribtutes
2916 * directly from the mountpoint dentry.
2917 */
3227fa41 2918 if (nfsd_mountpoint(dentry, exp)) {
021d3a72
BF
2919 int err;
2920
3227fa41
BF
2921 if (!(exp->ex_flags & NFSEXP_V4ROOT)
2922 && !attributes_need_mount(cd->rd_bmval)) {
2923 ignore_crossmnt = 1;
2924 goto out_encode;
2925 }
dcb488a3
AA
2926 /*
2927 * Why the heck aren't we just using nfsd_lookup??
2928 * Different "."/".." handling? Something else?
2929 * At least, add a comment here to explain....
2930 */
021d3a72
BF
2931 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
2932 if (err) {
2933 nfserr = nfserrno(err);
1da177e4
LT
2934 goto out_put;
2935 }
dcb488a3
AA
2936 nfserr = check_nfsd_access(exp, cd->rd_rqstp);
2937 if (nfserr)
2938 goto out_put;
1da177e4
LT
2939
2940 }
3227fa41 2941out_encode:
561f0ed4 2942 nfserr = nfsd4_encode_fattr(xdr, NULL, exp, dentry, cd->rd_bmval,
406a7ea9 2943 cd->rd_rqstp, ignore_crossmnt);
1da177e4
LT
2944out_put:
2945 dput(dentry);
2946 exp_put(exp);
2947 return nfserr;
2948}
2949
2ebbc012 2950static __be32 *
561f0ed4 2951nfsd4_encode_rdattr_error(struct xdr_stream *xdr, __be32 nfserr)
1da177e4 2952{
561f0ed4
BF
2953 __be32 *p;
2954
c3a45617 2955 p = xdr_reserve_space(xdr, 20);
561f0ed4 2956 if (!p)
1da177e4
LT
2957 return NULL;
2958 *p++ = htonl(2);
2959 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */
2960 *p++ = htonl(0); /* bmval1 */
2961
87915c64 2962 *p++ = htonl(4); /* attribute length */
1da177e4 2963 *p++ = nfserr; /* no htonl */
1da177e4
LT
2964 return p;
2965}
2966
2967static int
a0ad13ef
N
2968nfsd4_encode_dirent(void *ccdv, const char *name, int namlen,
2969 loff_t offset, u64 ino, unsigned int d_type)
1da177e4 2970{
a0ad13ef 2971 struct readdir_cd *ccd = ccdv;
1da177e4 2972 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common);
561f0ed4
BF
2973 struct xdr_stream *xdr = cd->xdr;
2974 int start_offset = xdr->buf->len;
2975 int cookie_offset;
aee37764 2976 u32 name_and_cookie;
561f0ed4 2977 int entry_bytes;
b37ad28b 2978 __be32 nfserr = nfserr_toosmall;
561f0ed4
BF
2979 __be64 wire_offset;
2980 __be32 *p;
1da177e4
LT
2981
2982 /* In nfsv4, "." and ".." never make it onto the wire.. */
2983 if (name && isdotent(name, namlen)) {
2984 cd->common.err = nfs_ok;
2985 return 0;
2986 }
2987
561f0ed4
BF
2988 if (cd->cookie_offset) {
2989 wire_offset = cpu_to_be64(offset);
2990 write_bytes_to_xdr_buf(xdr->buf, cd->cookie_offset,
2991 &wire_offset, 8);
2992 }
1da177e4 2993
561f0ed4
BF
2994 p = xdr_reserve_space(xdr, 4);
2995 if (!p)
1da177e4 2996 goto fail;
1da177e4 2997 *p++ = xdr_one; /* mark entry present */
561f0ed4
BF
2998 cookie_offset = xdr->buf->len;
2999 p = xdr_reserve_space(xdr, 3*4 + namlen);
3000 if (!p)
3001 goto fail;
1da177e4
LT
3002 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */
3003 p = xdr_encode_array(p, name, namlen); /* name length & name */
3004
561f0ed4 3005 nfserr = nfsd4_encode_dirent_fattr(xdr, cd, name, namlen);
1da177e4
LT
3006 switch (nfserr) {
3007 case nfs_ok:
1da177e4
LT
3008 break;
3009 case nfserr_resource:
3010 nfserr = nfserr_toosmall;
3011 goto fail;
b2c0cea6 3012 case nfserr_noent:
f41c5ad2 3013 xdr_truncate_encode(xdr, start_offset);
b2c0cea6 3014 goto skip_entry;
1da177e4
LT
3015 default:
3016 /*
3017 * If the client requested the RDATTR_ERROR attribute,
3018 * we stuff the error code into this attribute
3019 * and continue. If this attribute was not requested,
3020 * then in accordance with the spec, we fail the
3021 * entire READDIR operation(!)
3022 */
3023 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR))
3024 goto fail;
561f0ed4 3025 p = nfsd4_encode_rdattr_error(xdr, nfserr);
34081efc
FI
3026 if (p == NULL) {
3027 nfserr = nfserr_toosmall;
1da177e4 3028 goto fail;
34081efc 3029 }
1da177e4 3030 }
561f0ed4
BF
3031 nfserr = nfserr_toosmall;
3032 entry_bytes = xdr->buf->len - start_offset;
3033 if (entry_bytes > cd->rd_maxcount)
3034 goto fail;
3035 cd->rd_maxcount -= entry_bytes;
aee37764
BF
3036 /*
3037 * RFC 3530 14.2.24 describes rd_dircount as only a "hint", so
3038 * let's always let through the first entry, at least:
3039 */
0ec016e3
BF
3040 if (!cd->rd_dircount)
3041 goto fail;
3042 name_and_cookie = 4 + 4 * XDR_QUADLEN(namlen) + 8;
aee37764
BF
3043 if (name_and_cookie > cd->rd_dircount && cd->cookie_offset)
3044 goto fail;
3045 cd->rd_dircount -= min(cd->rd_dircount, name_and_cookie);
0ec016e3 3046
561f0ed4 3047 cd->cookie_offset = cookie_offset;
b2c0cea6 3048skip_entry:
1da177e4
LT
3049 cd->common.err = nfs_ok;
3050 return 0;
3051fail:
561f0ed4 3052 xdr_truncate_encode(xdr, start_offset);
1da177e4
LT
3053 cd->common.err = nfserr;
3054 return -EINVAL;
3055}
3056
d0a381dd
BF
3057static __be32
3058nfsd4_encode_stateid(struct xdr_stream *xdr, stateid_t *sid)
e2f282b9 3059{
bc749ca4 3060 __be32 *p;
e2f282b9 3061
d0a381dd
BF
3062 p = xdr_reserve_space(xdr, sizeof(stateid_t));
3063 if (!p)
3064 return nfserr_resource;
c373b0a4 3065 *p++ = cpu_to_be32(sid->si_generation);
0c0c267b
BF
3066 p = xdr_encode_opaque_fixed(p, &sid->si_opaque,
3067 sizeof(stateid_opaque_t));
d0a381dd 3068 return 0;
e2f282b9
BH
3069}
3070
695e12f8 3071static __be32
b37ad28b 3072nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access)
1da177e4 3073{
d0a381dd 3074 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3075 __be32 *p;
1da177e4
LT
3076
3077 if (!nfserr) {
d0a381dd
BF
3078 p = xdr_reserve_space(xdr, 8);
3079 if (!p)
3080 return nfserr_resource;
c373b0a4
BF
3081 *p++ = cpu_to_be32(access->ac_supported);
3082 *p++ = cpu_to_be32(access->ac_resp_access);
1da177e4 3083 }
695e12f8 3084 return nfserr;
1da177e4
LT
3085}
3086
1d1bc8f2
BF
3087static __be32 nfsd4_encode_bind_conn_to_session(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_bind_conn_to_session *bcts)
3088{
d0a381dd 3089 struct xdr_stream *xdr = &resp->xdr;
1d1bc8f2
BF
3090 __be32 *p;
3091
3092 if (!nfserr) {
d0a381dd
BF
3093 p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 8);
3094 if (!p)
3095 return nfserr_resource;
0c0c267b
BF
3096 p = xdr_encode_opaque_fixed(p, bcts->sessionid.data,
3097 NFS4_MAX_SESSIONID_LEN);
c373b0a4 3098 *p++ = cpu_to_be32(bcts->dir);
4ce85c8c 3099 /* Upshifting from TCP to RDMA is not supported */
c373b0a4 3100 *p++ = cpu_to_be32(0);
1d1bc8f2
BF
3101 }
3102 return nfserr;
3103}
3104
695e12f8 3105static __be32
b37ad28b 3106nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close)
1da177e4 3107{
d0a381dd
BF
3108 struct xdr_stream *xdr = &resp->xdr;
3109
e2f282b9 3110 if (!nfserr)
d0a381dd 3111 nfserr = nfsd4_encode_stateid(xdr, &close->cl_stateid);
e2f282b9 3112
695e12f8 3113 return nfserr;
1da177e4
LT
3114}
3115
3116
695e12f8 3117static __be32
b37ad28b 3118nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit)
1da177e4 3119{
d0a381dd 3120 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3121 __be32 *p;
1da177e4
LT
3122
3123 if (!nfserr) {
d0a381dd
BF
3124 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
3125 if (!p)
3126 return nfserr_resource;
0c0c267b
BF
3127 p = xdr_encode_opaque_fixed(p, commit->co_verf.data,
3128 NFS4_VERIFIER_SIZE);
1da177e4 3129 }
695e12f8 3130 return nfserr;
1da177e4
LT
3131}
3132
695e12f8 3133static __be32
b37ad28b 3134nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create)
1da177e4 3135{
d0a381dd 3136 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3137 __be32 *p;
1da177e4
LT
3138
3139 if (!nfserr) {
75976de6 3140 p = xdr_reserve_space(xdr, 20);
d0a381dd
BF
3141 if (!p)
3142 return nfserr_resource;
75976de6
KM
3143 encode_cinfo(p, &create->cr_cinfo);
3144 nfserr = nfsd4_encode_bitmap(xdr, create->cr_bmval[0],
3145 create->cr_bmval[1], create->cr_bmval[2]);
1da177e4 3146 }
695e12f8 3147 return nfserr;
1da177e4
LT
3148}
3149
b37ad28b
AV
3150static __be32
3151nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr)
1da177e4
LT
3152{
3153 struct svc_fh *fhp = getattr->ga_fhp;
d5184658 3154 struct xdr_stream *xdr = &resp->xdr;
1da177e4
LT
3155
3156 if (nfserr)
3157 return nfserr;
3158
d5184658
BF
3159 nfserr = nfsd4_encode_fattr(xdr, fhp, fhp->fh_export, fhp->fh_dentry,
3160 getattr->ga_bmval,
406a7ea9 3161 resp->rqstp, 0);
1da177e4
LT
3162 return nfserr;
3163}
3164
695e12f8
BH
3165static __be32
3166nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh **fhpp)
1da177e4 3167{
d0a381dd 3168 struct xdr_stream *xdr = &resp->xdr;
695e12f8 3169 struct svc_fh *fhp = *fhpp;
1da177e4 3170 unsigned int len;
bc749ca4 3171 __be32 *p;
1da177e4
LT
3172
3173 if (!nfserr) {
3174 len = fhp->fh_handle.fh_size;
d0a381dd
BF
3175 p = xdr_reserve_space(xdr, len + 4);
3176 if (!p)
3177 return nfserr_resource;
0c0c267b 3178 p = xdr_encode_opaque(p, &fhp->fh_handle.fh_base, len);
1da177e4 3179 }
695e12f8 3180 return nfserr;
1da177e4
LT
3181}
3182
3183/*
3184* Including all fields other than the name, a LOCK4denied structure requires
3185* 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes.
3186*/
d0a381dd
BF
3187static __be32
3188nfsd4_encode_lock_denied(struct xdr_stream *xdr, struct nfsd4_lock_denied *ld)
1da177e4 3189{
7c13f344 3190 struct xdr_netobj *conf = &ld->ld_owner;
bc749ca4 3191 __be32 *p;
1da177e4 3192
8c7424cf 3193again:
d0a381dd 3194 p = xdr_reserve_space(xdr, 32 + XDR_LEN(conf->len));
8c7424cf
BF
3195 if (!p) {
3196 /*
3197 * Don't fail to return the result just because we can't
3198 * return the conflicting open:
3199 */
3200 if (conf->len) {
f98bac5a 3201 kfree(conf->data);
8c7424cf
BF
3202 conf->len = 0;
3203 conf->data = NULL;
3204 goto again;
3205 }
d0a381dd 3206 return nfserr_resource;
8c7424cf 3207 }
b64c7f3b
BF
3208 p = xdr_encode_hyper(p, ld->ld_start);
3209 p = xdr_encode_hyper(p, ld->ld_length);
c373b0a4 3210 *p++ = cpu_to_be32(ld->ld_type);
7c13f344 3211 if (conf->len) {
0c0c267b
BF
3212 p = xdr_encode_opaque_fixed(p, &ld->ld_clientid, 8);
3213 p = xdr_encode_opaque(p, conf->data, conf->len);
f98bac5a 3214 kfree(conf->data);
1da177e4 3215 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */
b64c7f3b 3216 p = xdr_encode_hyper(p, (u64)0); /* clientid */
c373b0a4 3217 *p++ = cpu_to_be32(0); /* length of owner name */
1da177e4 3218 }
d0a381dd 3219 return nfserr_denied;
1da177e4
LT
3220}
3221
695e12f8 3222static __be32
b37ad28b 3223nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock)
1da177e4 3224{
d0a381dd
BF
3225 struct xdr_stream *xdr = &resp->xdr;
3226
e2f282b9 3227 if (!nfserr)
d0a381dd 3228 nfserr = nfsd4_encode_stateid(xdr, &lock->lk_resp_stateid);
e2f282b9 3229 else if (nfserr == nfserr_denied)
d0a381dd 3230 nfserr = nfsd4_encode_lock_denied(xdr, &lock->lk_denied);
f98bac5a 3231
695e12f8 3232 return nfserr;
1da177e4
LT
3233}
3234
695e12f8 3235static __be32
b37ad28b 3236nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt)
1da177e4 3237{
d0a381dd
BF
3238 struct xdr_stream *xdr = &resp->xdr;
3239
1da177e4 3240 if (nfserr == nfserr_denied)
d0a381dd 3241 nfsd4_encode_lock_denied(xdr, &lockt->lt_denied);
695e12f8 3242 return nfserr;
1da177e4
LT
3243}
3244
695e12f8 3245static __be32
b37ad28b 3246nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku)
1da177e4 3247{
d0a381dd
BF
3248 struct xdr_stream *xdr = &resp->xdr;
3249
e2f282b9 3250 if (!nfserr)
d0a381dd 3251 nfserr = nfsd4_encode_stateid(xdr, &locku->lu_stateid);
e2f282b9 3252
695e12f8 3253 return nfserr;
1da177e4
LT
3254}
3255
3256
695e12f8 3257static __be32
b37ad28b 3258nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link)
1da177e4 3259{
d0a381dd 3260 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3261 __be32 *p;
1da177e4
LT
3262
3263 if (!nfserr) {
d0a381dd
BF
3264 p = xdr_reserve_space(xdr, 20);
3265 if (!p)
3266 return nfserr_resource;
d05d5744 3267 p = encode_cinfo(p, &link->li_cinfo);
1da177e4 3268 }
695e12f8 3269 return nfserr;
1da177e4
LT
3270}
3271
3272
695e12f8 3273static __be32
b37ad28b 3274nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open)
1da177e4 3275{
d0a381dd 3276 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3277 __be32 *p;
1da177e4
LT
3278
3279 if (nfserr)
3280 goto out;
3281
d0a381dd
BF
3282 nfserr = nfsd4_encode_stateid(xdr, &open->op_stateid);
3283 if (nfserr)
3284 goto out;
75976de6 3285 p = xdr_reserve_space(xdr, 24);
d0a381dd
BF
3286 if (!p)
3287 return nfserr_resource;
d05d5744 3288 p = encode_cinfo(p, &open->op_cinfo);
c373b0a4 3289 *p++ = cpu_to_be32(open->op_rflags);
1da177e4 3290
75976de6
KM
3291 nfserr = nfsd4_encode_bitmap(xdr, open->op_bmval[0], open->op_bmval[1],
3292 open->op_bmval[2]);
3293 if (nfserr)
3294 goto out;
3295
3296 p = xdr_reserve_space(xdr, 4);
3297 if (!p)
3298 return nfserr_resource;
3299
3300 *p++ = cpu_to_be32(open->op_delegate_type);
1da177e4
LT
3301 switch (open->op_delegate_type) {
3302 case NFS4_OPEN_DELEGATE_NONE:
3303 break;
3304 case NFS4_OPEN_DELEGATE_READ:
d0a381dd
BF
3305 nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid);
3306 if (nfserr)
3307 return nfserr;
3308 p = xdr_reserve_space(xdr, 20);
3309 if (!p)
3310 return nfserr_resource;
c373b0a4 3311 *p++ = cpu_to_be32(open->op_recall);
1da177e4
LT
3312
3313 /*
3314 * TODO: ACE's in delegations
3315 */
c373b0a4
BF
3316 *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
3317 *p++ = cpu_to_be32(0);
3318 *p++ = cpu_to_be32(0);
3319 *p++ = cpu_to_be32(0); /* XXX: is NULL principal ok? */
1da177e4
LT
3320 break;
3321 case NFS4_OPEN_DELEGATE_WRITE:
d0a381dd
BF
3322 nfserr = nfsd4_encode_stateid(xdr, &open->op_delegate_stateid);
3323 if (nfserr)
3324 return nfserr;
3325 p = xdr_reserve_space(xdr, 32);
3326 if (!p)
3327 return nfserr_resource;
c373b0a4 3328 *p++ = cpu_to_be32(0);
1da177e4
LT
3329
3330 /*
3331 * TODO: space_limit's in delegations
3332 */
c373b0a4
BF
3333 *p++ = cpu_to_be32(NFS4_LIMIT_SIZE);
3334 *p++ = cpu_to_be32(~(u32)0);
3335 *p++ = cpu_to_be32(~(u32)0);
1da177e4
LT
3336
3337 /*
3338 * TODO: ACE's in delegations
3339 */
c373b0a4
BF
3340 *p++ = cpu_to_be32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE);
3341 *p++ = cpu_to_be32(0);
3342 *p++ = cpu_to_be32(0);
3343 *p++ = cpu_to_be32(0); /* XXX: is NULL principal ok? */
1da177e4 3344 break;
d24433cd
BH
3345 case NFS4_OPEN_DELEGATE_NONE_EXT: /* 4.1 */
3346 switch (open->op_why_no_deleg) {
3347 case WND4_CONTENTION:
3348 case WND4_RESOURCE:
d0a381dd
BF
3349 p = xdr_reserve_space(xdr, 8);
3350 if (!p)
3351 return nfserr_resource;
c373b0a4
BF
3352 *p++ = cpu_to_be32(open->op_why_no_deleg);
3353 /* deleg signaling not supported yet: */
3354 *p++ = cpu_to_be32(0);
d24433cd
BH
3355 break;
3356 default:
d0a381dd
BF
3357 p = xdr_reserve_space(xdr, 4);
3358 if (!p)
3359 return nfserr_resource;
c373b0a4 3360 *p++ = cpu_to_be32(open->op_why_no_deleg);
d24433cd 3361 }
d24433cd 3362 break;
1da177e4
LT
3363 default:
3364 BUG();
3365 }
3366 /* XXX save filehandle here */
3367out:
695e12f8 3368 return nfserr;
1da177e4
LT
3369}
3370
695e12f8 3371static __be32
b37ad28b 3372nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc)
1da177e4 3373{
d0a381dd
BF
3374 struct xdr_stream *xdr = &resp->xdr;
3375
e2f282b9 3376 if (!nfserr)
d0a381dd 3377 nfserr = nfsd4_encode_stateid(xdr, &oc->oc_resp_stateid);
1da177e4 3378
695e12f8 3379 return nfserr;
1da177e4
LT
3380}
3381
695e12f8 3382static __be32
b37ad28b 3383nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od)
1da177e4 3384{
d0a381dd
BF
3385 struct xdr_stream *xdr = &resp->xdr;
3386
e2f282b9 3387 if (!nfserr)
d0a381dd 3388 nfserr = nfsd4_encode_stateid(xdr, &od->od_stateid);
1da177e4 3389
695e12f8 3390 return nfserr;
1da177e4
LT
3391}
3392
dc97618d
BF
3393static __be32 nfsd4_encode_splice_read(
3394 struct nfsd4_compoundres *resp,
3395 struct nfsd4_read *read,
3396 struct file *file, unsigned long maxcount)
1da177e4 3397{
ddd1ea56 3398 struct xdr_stream *xdr = &resp->xdr;
34a78b48 3399 struct xdr_buf *buf = xdr->buf;
dc97618d 3400 u32 eof;
ac503e4a 3401 long len;
30596768 3402 int space_left;
dc97618d 3403 __be32 nfserr;
fec25fa4 3404 __be32 *p = xdr->p - 2;
1da177e4 3405
d5d5c304
KM
3406 /* Make sure there will be room for padding if needed */
3407 if (xdr->end - xdr->p < 1)
d0a381dd 3408 return nfserr_resource;
dc97618d 3409
ac503e4a 3410 len = maxcount;
dc97618d
BF
3411 nfserr = nfsd_splice_read(read->rd_rqstp, file,
3412 read->rd_offset, &maxcount);
3413 if (nfserr) {
3414 /*
3415 * nfsd_splice_actor may have already messed with the
3416 * page length; reset it so as not to confuse
3417 * xdr_truncate_encode:
3418 */
34a78b48 3419 buf->page_len = 0;
dc97618d 3420 return nfserr;
b0e35fda 3421 }
1da177e4 3422
ac503e4a
BC
3423 eof = nfsd_eof_on_read(len, maxcount, read->rd_offset,
3424 d_inode(read->rd_fhp->fh_dentry)->i_size);
4e21ac4b 3425
fec25fa4
BF
3426 *(p++) = htonl(eof);
3427 *(p++) = htonl(maxcount);
dc97618d 3428
34a78b48
BF
3429 buf->page_len = maxcount;
3430 buf->len += maxcount;
15b23ef5
BF
3431 xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1)
3432 / PAGE_SIZE;
dc97618d
BF
3433
3434 /* Use rest of head for padding and remaining ops: */
34a78b48
BF
3435 buf->tail[0].iov_base = xdr->p;
3436 buf->tail[0].iov_len = 0;
fec25fa4 3437 xdr->iov = buf->tail;
dc97618d 3438 if (maxcount&3) {
fec25fa4
BF
3439 int pad = 4 - (maxcount&3);
3440
3441 *(xdr->p++) = 0;
3442
34a78b48 3443 buf->tail[0].iov_base += maxcount&3;
fec25fa4
BF
3444 buf->tail[0].iov_len = pad;
3445 buf->len += pad;
b0e35fda 3446 }
2825a7f9 3447
dc97618d 3448 space_left = min_t(int, (void *)xdr->end - (void *)xdr->p,
34a78b48
BF
3449 buf->buflen - buf->len);
3450 buf->buflen = buf->len + space_left;
dc97618d
BF
3451 xdr->end = (__be32 *)((void *)xdr->end + space_left);
3452
3453 return 0;
3454}
3455
3456static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
3457 struct nfsd4_read *read,
3458 struct file *file, unsigned long maxcount)
3459{
3460 struct xdr_stream *xdr = &resp->xdr;
3461 u32 eof;
3462 int v;
dc97618d 3463 int starting_len = xdr->buf->len - 8;
dc97618d 3464 long len;
b0420980 3465 int thislen;
dc97618d
BF
3466 __be32 nfserr;
3467 __be32 tmp;
3468 __be32 *p;
b0420980
BF
3469 u32 zzz = 0;
3470 int pad;
1da177e4
LT
3471
3472 len = maxcount;
3473 v = 0;
6ff9897d 3474
1055414f 3475 thislen = min_t(long, len, ((void *)xdr->end - (void *)xdr->p));
b0420980
BF
3476 p = xdr_reserve_space(xdr, (thislen+3)&~3);
3477 WARN_ON_ONCE(!p);
3478 resp->rqstp->rq_vec[v].iov_base = p;
3479 resp->rqstp->rq_vec[v].iov_len = thislen;
3480 v++;
3481 len -= thislen;
3482
3483 while (len) {
6ff9897d 3484 thislen = min_t(long, len, PAGE_SIZE);
b0420980
BF
3485 p = xdr_reserve_space(xdr, (thislen+3)&~3);
3486 WARN_ON_ONCE(!p);
3487 resp->rqstp->rq_vec[v].iov_base = p;
6ff9897d 3488 resp->rqstp->rq_vec[v].iov_len = thislen;
1da177e4 3489 v++;
6ff9897d 3490 len -= thislen;
1da177e4
LT
3491 }
3492 read->rd_vlen = v;
3493
ac503e4a 3494 len = maxcount;
dc97618d
BF
3495 nfserr = nfsd_readv(file, read->rd_offset, resp->rqstp->rq_vec,
3496 read->rd_vlen, &maxcount);
3497 if (nfserr)
1da177e4 3498 return nfserr;
b0420980 3499 xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
dc97618d 3500
ac503e4a
BC
3501 eof = nfsd_eof_on_read(len, maxcount, read->rd_offset,
3502 d_inode(read->rd_fhp->fh_dentry)->i_size);
1da177e4 3503
dc97618d
BF
3504 tmp = htonl(eof);
3505 write_bytes_to_xdr_buf(xdr->buf, starting_len , &tmp, 4);
3506 tmp = htonl(maxcount);
3507 write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4);
3508
b0420980
BF
3509 pad = (maxcount&3) ? 4 - (maxcount&3) : 0;
3510 write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount,
3511 &zzz, pad);
1da177e4 3512 return 0;
dc97618d
BF
3513
3514}
3515
3516static __be32
3517nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3518 struct nfsd4_read *read)
3519{
3520 unsigned long maxcount;
3521 struct xdr_stream *xdr = &resp->xdr;
3522 struct file *file = read->rd_filp;
3523 int starting_len = xdr->buf->len;
e749a462 3524 struct raparms *ra = NULL;
dc97618d 3525 __be32 *p;
dc97618d
BF
3526
3527 if (nfserr)
96bcad50 3528 goto out;
dc97618d
BF
3529
3530 p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */
3531 if (!p) {
779fb0f3 3532 WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags));
96bcad50
CH
3533 nfserr = nfserr_resource;
3534 goto out;
dc97618d 3535 }
68e8bb03
CH
3536 if (resp->xdr.buf->page_len &&
3537 test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) {
b0420980 3538 WARN_ON_ONCE(1);
96bcad50
CH
3539 nfserr = nfserr_resource;
3540 goto out;
dc97618d 3541 }
dc97618d
BF
3542 xdr_commit_encode(xdr);
3543
3544 maxcount = svc_max_payload(resp->rqstp);
68e8bb03
CH
3545 maxcount = min_t(unsigned long, maxcount,
3546 (xdr->buf->buflen - xdr->buf->len));
3c7aa15d 3547 maxcount = min_t(unsigned long, maxcount, read->rd_length);
dc97618d 3548
af90f707 3549 if (read->rd_tmp_file)
e749a462 3550 ra = nfsd_init_raparms(file);
dc97618d 3551
68e8bb03
CH
3552 if (file->f_op->splice_read &&
3553 test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags))
96bcad50 3554 nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);
dc97618d 3555 else
96bcad50 3556 nfserr = nfsd4_encode_readv(resp, read, file, maxcount);
dc97618d 3557
e749a462
CH
3558 if (ra)
3559 nfsd_put_raparams(file, ra);
dc97618d 3560
96bcad50 3561 if (nfserr)
dc97618d 3562 xdr_truncate_encode(xdr, starting_len);
96bcad50
CH
3563
3564out:
3565 if (file)
3566 fput(file);
3567 return nfserr;
1da177e4
LT
3568}
3569
b37ad28b
AV
3570static __be32
3571nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)
1da177e4
LT
3572{
3573 int maxcount;
476a7b1f
BF
3574 __be32 wire_count;
3575 int zero = 0;
ddd1ea56 3576 struct xdr_stream *xdr = &resp->xdr;
1fcea5b2 3577 int length_offset = xdr->buf->len;
bc749ca4 3578 __be32 *p;
1da177e4
LT
3579
3580 if (nfserr)
3581 return nfserr;
2825a7f9
BF
3582
3583 p = xdr_reserve_space(xdr, 4);
3584 if (!p)
3585 return nfserr_resource;
1da177e4 3586 maxcount = PAGE_SIZE;
d0a381dd 3587
476a7b1f
BF
3588 p = xdr_reserve_space(xdr, maxcount);
3589 if (!p)
4e21ac4b 3590 return nfserr_resource;
1da177e4
LT
3591 /*
3592 * XXX: By default, the ->readlink() VFS op will truncate symlinks
3593 * if they would overflow the buffer. Is this kosher in NFSv4? If
3594 * not, one easy fix is: if ->readlink() precisely fills the buffer,
3595 * assume that truncation occurred, and return NFS4ERR_RESOURCE.
3596 */
476a7b1f
BF
3597 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp,
3598 (char *)p, &maxcount);
1da177e4 3599 if (nfserr == nfserr_isdir)
d3f627c8
BF
3600 nfserr = nfserr_inval;
3601 if (nfserr) {
1fcea5b2 3602 xdr_truncate_encode(xdr, length_offset);
1da177e4 3603 return nfserr;
d3f627c8 3604 }
1da177e4 3605
476a7b1f
BF
3606 wire_count = htonl(maxcount);
3607 write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, 4);
69bbd9c7 3608 xdr_truncate_encode(xdr, length_offset + 4 + ALIGN(maxcount, 4));
476a7b1f
BF
3609 if (maxcount & 3)
3610 write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount,
3611 &zero, 4 - (maxcount&3));
1da177e4
LT
3612 return 0;
3613}
3614
b37ad28b
AV
3615static __be32
3616nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir)
1da177e4
LT
3617{
3618 int maxcount;
561f0ed4 3619 int bytes_left;
1da177e4 3620 loff_t offset;
561f0ed4 3621 __be64 wire_offset;
ddd1ea56 3622 struct xdr_stream *xdr = &resp->xdr;
1fcea5b2 3623 int starting_len = xdr->buf->len;
bc749ca4 3624 __be32 *p;
1da177e4
LT
3625
3626 if (nfserr)
3627 return nfserr;
1da177e4 3628
d0a381dd
BF
3629 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
3630 if (!p)
3631 return nfserr_resource;
1da177e4
LT
3632
3633 /* XXX: Following NFSv3, we ignore the READDIR verifier for now. */
c373b0a4
BF
3634 *p++ = cpu_to_be32(0);
3635 *p++ = cpu_to_be32(0);
4aea24b2
BF
3636 resp->xdr.buf->head[0].iov_len = ((char *)resp->xdr.p)
3637 - (char *)resp->xdr.buf->head[0].iov_base;
1da177e4
LT
3638
3639 /*
561f0ed4
BF
3640 * Number of bytes left for directory entries allowing for the
3641 * final 8 bytes of the readdir and a following failed op:
3642 */
3643 bytes_left = xdr->buf->buflen - xdr->buf->len
3644 - COMPOUND_ERR_SLACK_SPACE - 8;
3645 if (bytes_left < 0) {
3646 nfserr = nfserr_resource;
3647 goto err_no_verf;
3648 }
3649 maxcount = min_t(u32, readdir->rd_maxcount, INT_MAX);
3650 /*
3651 * Note the rfc defines rd_maxcount as the size of the
3652 * READDIR4resok structure, which includes the verifier above
3653 * and the 8 bytes encoded at the end of this function:
1da177e4 3654 */
561f0ed4
BF
3655 if (maxcount < 16) {
3656 nfserr = nfserr_toosmall;
1da177e4
LT
3657 goto err_no_verf;
3658 }
561f0ed4 3659 maxcount = min_t(int, maxcount-16, bytes_left);
1da177e4 3660
aee37764
BF
3661 /* RFC 3530 14.2.24 allows us to ignore dircount when it's 0: */
3662 if (!readdir->rd_dircount)
3663 readdir->rd_dircount = INT_MAX;
3664
561f0ed4
BF
3665 readdir->xdr = xdr;
3666 readdir->rd_maxcount = maxcount;
1da177e4 3667 readdir->common.err = 0;
561f0ed4 3668 readdir->cookie_offset = 0;
1da177e4
LT
3669
3670 offset = readdir->rd_cookie;
3671 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp,
3672 &offset,
3673 &readdir->common, nfsd4_encode_dirent);
3674 if (nfserr == nfs_ok &&
3675 readdir->common.err == nfserr_toosmall &&
561f0ed4
BF
3676 xdr->buf->len == starting_len + 8) {
3677 /* nothing encoded; which limit did we hit?: */
3678 if (maxcount - 16 < bytes_left)
3679 /* It was the fault of rd_maxcount: */
3680 nfserr = nfserr_toosmall;
3681 else
3682 /* We ran out of buffer space: */
3683 nfserr = nfserr_resource;
3684 }
1da177e4
LT
3685 if (nfserr)
3686 goto err_no_verf;
3687
561f0ed4
BF
3688 if (readdir->cookie_offset) {
3689 wire_offset = cpu_to_be64(offset);
3690 write_bytes_to_xdr_buf(xdr->buf, readdir->cookie_offset,
3691 &wire_offset, 8);
3692 }
1da177e4 3693
561f0ed4
BF
3694 p = xdr_reserve_space(xdr, 8);
3695 if (!p) {
3696 WARN_ON_ONCE(1);
3697 goto err_no_verf;
3698 }
1da177e4
LT
3699 *p++ = 0; /* no more entries */
3700 *p++ = htonl(readdir->common.err == nfserr_eof);
1da177e4
LT
3701
3702 return 0;
3703err_no_verf:
1fcea5b2 3704 xdr_truncate_encode(xdr, starting_len);
1da177e4
LT
3705 return nfserr;
3706}
3707
695e12f8 3708static __be32
b37ad28b 3709nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove)
1da177e4 3710{
d0a381dd 3711 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3712 __be32 *p;
1da177e4
LT
3713
3714 if (!nfserr) {
d0a381dd
BF
3715 p = xdr_reserve_space(xdr, 20);
3716 if (!p)
3717 return nfserr_resource;
d05d5744 3718 p = encode_cinfo(p, &remove->rm_cinfo);
1da177e4 3719 }
695e12f8 3720 return nfserr;
1da177e4
LT
3721}
3722
695e12f8 3723static __be32
b37ad28b 3724nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename)
1da177e4 3725{
d0a381dd 3726 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3727 __be32 *p;
1da177e4
LT
3728
3729 if (!nfserr) {
d0a381dd
BF
3730 p = xdr_reserve_space(xdr, 40);
3731 if (!p)
3732 return nfserr_resource;
d05d5744
BF
3733 p = encode_cinfo(p, &rename->rn_sinfo);
3734 p = encode_cinfo(p, &rename->rn_tinfo);
1da177e4 3735 }
695e12f8 3736 return nfserr;
1da177e4
LT
3737}
3738
695e12f8 3739static __be32
d0a381dd 3740nfsd4_do_encode_secinfo(struct xdr_stream *xdr,
a77c806f 3741 __be32 nfserr, struct svc_export *exp)
dcb488a3 3742{
676e4ebd 3743 u32 i, nflavs, supported;
4796f457
BF
3744 struct exp_flavor_info *flavs;
3745 struct exp_flavor_info def_flavs[2];
676e4ebd
CL
3746 __be32 *p, *flavorsp;
3747 static bool report = true;
dcb488a3
AA
3748
3749 if (nfserr)
3750 goto out;
d0a381dd 3751 nfserr = nfserr_resource;
4796f457
BF
3752 if (exp->ex_nflavors) {
3753 flavs = exp->ex_flavors;
3754 nflavs = exp->ex_nflavors;
3755 } else { /* Handling of some defaults in absence of real secinfo: */
3756 flavs = def_flavs;
3757 if (exp->ex_client->flavour->flavour == RPC_AUTH_UNIX) {
3758 nflavs = 2;
3759 flavs[0].pseudoflavor = RPC_AUTH_UNIX;
3760 flavs[1].pseudoflavor = RPC_AUTH_NULL;
3761 } else if (exp->ex_client->flavour->flavour == RPC_AUTH_GSS) {
3762 nflavs = 1;
3763 flavs[0].pseudoflavor
3764 = svcauth_gss_flavor(exp->ex_client);
3765 } else {
3766 nflavs = 1;
3767 flavs[0].pseudoflavor
3768 = exp->ex_client->flavour->flavour;
3769 }
3770 }
3771
676e4ebd 3772 supported = 0;
d0a381dd
BF
3773 p = xdr_reserve_space(xdr, 4);
3774 if (!p)
3775 goto out;
676e4ebd 3776 flavorsp = p++; /* to be backfilled later */
676e4ebd 3777
4796f457 3778 for (i = 0; i < nflavs; i++) {
676e4ebd 3779 rpc_authflavor_t pf = flavs[i].pseudoflavor;
a77c806f 3780 struct rpcsec_gss_info info;
dcb488a3 3781
676e4ebd
CL
3782 if (rpcauth_get_gssinfo(pf, &info) == 0) {
3783 supported++;
d0a381dd
BF
3784 p = xdr_reserve_space(xdr, 4 + 4 +
3785 XDR_LEN(info.oid.len) + 4 + 4);
3786 if (!p)
3787 goto out;
c373b0a4 3788 *p++ = cpu_to_be32(RPC_AUTH_GSS);
0c0c267b 3789 p = xdr_encode_opaque(p, info.oid.data, info.oid.len);
c373b0a4
BF
3790 *p++ = cpu_to_be32(info.qop);
3791 *p++ = cpu_to_be32(info.service);
676e4ebd
CL
3792 } else if (pf < RPC_AUTH_MAXFLAVOR) {
3793 supported++;
d0a381dd
BF
3794 p = xdr_reserve_space(xdr, 4);
3795 if (!p)
3796 goto out;
c373b0a4 3797 *p++ = cpu_to_be32(pf);
676e4ebd
CL
3798 } else {
3799 if (report)
3800 pr_warn("NFS: SECINFO: security flavor %u "
3801 "is not supported\n", pf);
dcb488a3
AA
3802 }
3803 }
a77c806f 3804
676e4ebd
CL
3805 if (nflavs != supported)
3806 report = false;
3807 *flavorsp = htonl(supported);
d0a381dd 3808 nfserr = 0;
dcb488a3
AA
3809out:
3810 if (exp)
3811 exp_put(exp);
695e12f8 3812 return nfserr;
dcb488a3
AA
3813}
3814
22b6dee8
MJ
3815static __be32
3816nfsd4_encode_secinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
3817 struct nfsd4_secinfo *secinfo)
3818{
d0a381dd
BF
3819 struct xdr_stream *xdr = &resp->xdr;
3820
3821 return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->si_exp);
22b6dee8
MJ
3822}
3823
3824static __be32
3825nfsd4_encode_secinfo_no_name(struct nfsd4_compoundres *resp, __be32 nfserr,
3826 struct nfsd4_secinfo_no_name *secinfo)
3827{
d0a381dd
BF
3828 struct xdr_stream *xdr = &resp->xdr;
3829
3830 return nfsd4_do_encode_secinfo(xdr, nfserr, secinfo->sin_exp);
22b6dee8
MJ
3831}
3832
1da177e4
LT
3833/*
3834 * The SETATTR encode routine is special -- it always encodes a bitmap,
3835 * regardless of the error status.
3836 */
695e12f8 3837static __be32
b37ad28b 3838nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr)
1da177e4 3839{
d0a381dd 3840 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3841 __be32 *p;
1da177e4 3842
d0a381dd
BF
3843 p = xdr_reserve_space(xdr, 16);
3844 if (!p)
3845 return nfserr_resource;
1da177e4 3846 if (nfserr) {
c373b0a4
BF
3847 *p++ = cpu_to_be32(3);
3848 *p++ = cpu_to_be32(0);
3849 *p++ = cpu_to_be32(0);
3850 *p++ = cpu_to_be32(0);
1da177e4
LT
3851 }
3852 else {
c373b0a4
BF
3853 *p++ = cpu_to_be32(3);
3854 *p++ = cpu_to_be32(setattr->sa_bmval[0]);
3855 *p++ = cpu_to_be32(setattr->sa_bmval[1]);
3856 *p++ = cpu_to_be32(setattr->sa_bmval[2]);
1da177e4 3857 }
695e12f8 3858 return nfserr;
1da177e4
LT
3859}
3860
695e12f8 3861static __be32
b37ad28b 3862nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd)
1da177e4 3863{
d0a381dd 3864 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3865 __be32 *p;
1da177e4
LT
3866
3867 if (!nfserr) {
d0a381dd
BF
3868 p = xdr_reserve_space(xdr, 8 + NFS4_VERIFIER_SIZE);
3869 if (!p)
3870 return nfserr_resource;
0c0c267b
BF
3871 p = xdr_encode_opaque_fixed(p, &scd->se_clientid, 8);
3872 p = xdr_encode_opaque_fixed(p, &scd->se_confirm,
3873 NFS4_VERIFIER_SIZE);
1da177e4
LT
3874 }
3875 else if (nfserr == nfserr_clid_inuse) {
d0a381dd
BF
3876 p = xdr_reserve_space(xdr, 8);
3877 if (!p)
3878 return nfserr_resource;
c373b0a4
BF
3879 *p++ = cpu_to_be32(0);
3880 *p++ = cpu_to_be32(0);
1da177e4 3881 }
695e12f8 3882 return nfserr;
1da177e4
LT
3883}
3884
695e12f8 3885static __be32
b37ad28b 3886nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write)
1da177e4 3887{
d0a381dd 3888 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3889 __be32 *p;
1da177e4
LT
3890
3891 if (!nfserr) {
d0a381dd
BF
3892 p = xdr_reserve_space(xdr, 16);
3893 if (!p)
3894 return nfserr_resource;
c373b0a4
BF
3895 *p++ = cpu_to_be32(write->wr_bytes_written);
3896 *p++ = cpu_to_be32(write->wr_how_written);
0c0c267b
BF
3897 p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
3898 NFS4_VERIFIER_SIZE);
1da177e4 3899 }
695e12f8 3900 return nfserr;
1da177e4
LT
3901}
3902
2db134eb 3903static __be32
57b7b43b 3904nfsd4_encode_exchange_id(struct nfsd4_compoundres *resp, __be32 nfserr,
2db134eb
AA
3905 struct nfsd4_exchange_id *exid)
3906{
d0a381dd 3907 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3908 __be32 *p;
0733d213
AA
3909 char *major_id;
3910 char *server_scope;
3911 int major_id_sz;
3912 int server_scope_sz;
ed941643 3913 int status = 0;
0733d213
AA
3914 uint64_t minor_id = 0;
3915
3916 if (nfserr)
3917 return nfserr;
3918
3919 major_id = utsname()->nodename;
3920 major_id_sz = strlen(major_id);
3921 server_scope = utsname()->nodename;
3922 server_scope_sz = strlen(server_scope);
3923
d0a381dd 3924 p = xdr_reserve_space(xdr,
0733d213
AA
3925 8 /* eir_clientid */ +
3926 4 /* eir_sequenceid */ +
3927 4 /* eir_flags */ +
a8bb84bc 3928 4 /* spr_how */);
d0a381dd
BF
3929 if (!p)
3930 return nfserr_resource;
0733d213 3931
0c0c267b 3932 p = xdr_encode_opaque_fixed(p, &exid->clientid, 8);
c373b0a4
BF
3933 *p++ = cpu_to_be32(exid->seqid);
3934 *p++ = cpu_to_be32(exid->flags);
0733d213 3935
c373b0a4 3936 *p++ = cpu_to_be32(exid->spa_how);
a8bb84bc 3937
57266a6e
BF
3938 switch (exid->spa_how) {
3939 case SP4_NONE:
3940 break;
3941 case SP4_MACH_CRED:
3942 /* spo_must_enforce bitmap: */
ed941643
AE
3943 status = nfsd4_encode_bitmap(xdr,
3944 exid->spo_must_enforce[0],
3945 exid->spo_must_enforce[1],
3946 exid->spo_must_enforce[2]);
3947 if (status)
3948 goto out;
3949 /* spo_must_allow bitmap: */
3950 status = nfsd4_encode_bitmap(xdr,
3951 exid->spo_must_allow[0],
3952 exid->spo_must_allow[1],
3953 exid->spo_must_allow[2]);
3954 if (status)
3955 goto out;
57266a6e
BF
3956 break;
3957 default:
3958 WARN_ON_ONCE(1);
3959 }
0733d213 3960
d0a381dd 3961 p = xdr_reserve_space(xdr,
a8bb84bc
KM
3962 8 /* so_minor_id */ +
3963 4 /* so_major_id.len */ +
3964 (XDR_QUADLEN(major_id_sz) * 4) +
3965 4 /* eir_server_scope.len */ +
3966 (XDR_QUADLEN(server_scope_sz) * 4) +
3967 4 /* eir_server_impl_id.count (0) */);
d0a381dd
BF
3968 if (!p)
3969 return nfserr_resource;
a8bb84bc 3970
0733d213 3971 /* The server_owner struct */
b64c7f3b 3972 p = xdr_encode_hyper(p, minor_id); /* Minor id */
0733d213 3973 /* major id */
0c0c267b 3974 p = xdr_encode_opaque(p, major_id, major_id_sz);
0733d213
AA
3975
3976 /* Server scope */
0c0c267b 3977 p = xdr_encode_opaque(p, server_scope, server_scope_sz);
0733d213
AA
3978
3979 /* Implementation id */
c373b0a4 3980 *p++ = cpu_to_be32(0); /* zero length nfs_impl_id4 array */
0733d213 3981 return 0;
ed941643
AE
3982out:
3983 return status;
2db134eb
AA
3984}
3985
3986static __be32
57b7b43b 3987nfsd4_encode_create_session(struct nfsd4_compoundres *resp, __be32 nfserr,
2db134eb
AA
3988 struct nfsd4_create_session *sess)
3989{
d0a381dd 3990 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 3991 __be32 *p;
ec6b5d7b
AA
3992
3993 if (nfserr)
3994 return nfserr;
3995
d0a381dd
BF
3996 p = xdr_reserve_space(xdr, 24);
3997 if (!p)
3998 return nfserr_resource;
0c0c267b
BF
3999 p = xdr_encode_opaque_fixed(p, sess->sessionid.data,
4000 NFS4_MAX_SESSIONID_LEN);
c373b0a4
BF
4001 *p++ = cpu_to_be32(sess->seqid);
4002 *p++ = cpu_to_be32(sess->flags);
ec6b5d7b 4003
d0a381dd
BF
4004 p = xdr_reserve_space(xdr, 28);
4005 if (!p)
4006 return nfserr_resource;
c373b0a4
BF
4007 *p++ = cpu_to_be32(0); /* headerpadsz */
4008 *p++ = cpu_to_be32(sess->fore_channel.maxreq_sz);
4009 *p++ = cpu_to_be32(sess->fore_channel.maxresp_sz);
4010 *p++ = cpu_to_be32(sess->fore_channel.maxresp_cached);
4011 *p++ = cpu_to_be32(sess->fore_channel.maxops);
4012 *p++ = cpu_to_be32(sess->fore_channel.maxreqs);
4013 *p++ = cpu_to_be32(sess->fore_channel.nr_rdma_attrs);
ec6b5d7b
AA
4014
4015 if (sess->fore_channel.nr_rdma_attrs) {
d0a381dd
BF
4016 p = xdr_reserve_space(xdr, 4);
4017 if (!p)
4018 return nfserr_resource;
c373b0a4 4019 *p++ = cpu_to_be32(sess->fore_channel.rdma_attrs);
ec6b5d7b
AA
4020 }
4021
d0a381dd
BF
4022 p = xdr_reserve_space(xdr, 28);
4023 if (!p)
4024 return nfserr_resource;
c373b0a4
BF
4025 *p++ = cpu_to_be32(0); /* headerpadsz */
4026 *p++ = cpu_to_be32(sess->back_channel.maxreq_sz);
4027 *p++ = cpu_to_be32(sess->back_channel.maxresp_sz);
4028 *p++ = cpu_to_be32(sess->back_channel.maxresp_cached);
4029 *p++ = cpu_to_be32(sess->back_channel.maxops);
4030 *p++ = cpu_to_be32(sess->back_channel.maxreqs);
4031 *p++ = cpu_to_be32(sess->back_channel.nr_rdma_attrs);
ec6b5d7b
AA
4032
4033 if (sess->back_channel.nr_rdma_attrs) {
d0a381dd
BF
4034 p = xdr_reserve_space(xdr, 4);
4035 if (!p)
4036 return nfserr_resource;
c373b0a4 4037 *p++ = cpu_to_be32(sess->back_channel.rdma_attrs);
ec6b5d7b
AA
4038 }
4039 return 0;
2db134eb
AA
4040}
4041
c47d832b 4042static __be32
57b7b43b 4043nfsd4_encode_sequence(struct nfsd4_compoundres *resp, __be32 nfserr,
2db134eb
AA
4044 struct nfsd4_sequence *seq)
4045{
d0a381dd 4046 struct xdr_stream *xdr = &resp->xdr;
bc749ca4 4047 __be32 *p;
b85d4c01
BH
4048
4049 if (nfserr)
4050 return nfserr;
4051
d0a381dd
BF
4052 p = xdr_reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 20);
4053 if (!p)
4054 return nfserr_resource;
0c0c267b
BF
4055 p = xdr_encode_opaque_fixed(p, seq->sessionid.data,
4056 NFS4_MAX_SESSIONID_LEN);
c373b0a4
BF
4057 *p++ = cpu_to_be32(seq->seqid);
4058 *p++ = cpu_to_be32(seq->slotid);
b7d7ca35 4059 /* Note slotid's are numbered from zero: */
c373b0a4
BF
4060 *p++ = cpu_to_be32(seq->maxslots - 1); /* sr_highest_slotid */
4061 *p++ = cpu_to_be32(seq->maxslots - 1); /* sr_target_highest_slotid */
4062 *p++ = cpu_to_be32(seq->status_flags);
b85d4c01 4063
f5236013 4064 resp->cstate.data_offset = xdr->buf->len; /* DRC cache data pointer */
b85d4c01 4065 return 0;
2db134eb
AA
4066}
4067
2355c596 4068static __be32
57b7b43b 4069nfsd4_encode_test_stateid(struct nfsd4_compoundres *resp, __be32 nfserr,
17456804
BS
4070 struct nfsd4_test_stateid *test_stateid)
4071{
d0a381dd 4072 struct xdr_stream *xdr = &resp->xdr;
03cfb420 4073 struct nfsd4_test_stateid_id *stateid, *next;
17456804 4074 __be32 *p;
17456804 4075
a11fcce1
BF
4076 if (nfserr)
4077 return nfserr;
4078
d0a381dd
BF
4079 p = xdr_reserve_space(xdr, 4 + (4 * test_stateid->ts_num_ids));
4080 if (!p)
4081 return nfserr_resource;
17456804 4082 *p++ = htonl(test_stateid->ts_num_ids);
17456804 4083
03cfb420 4084 list_for_each_entry_safe(stateid, next, &test_stateid->ts_stateid_list, ts_id_list) {
02f5fde5 4085 *p++ = stateid->ts_id_status;
17456804 4086 }
17456804
BS
4087
4088 return nfserr;
4089}
4090
9cf514cc
CH
4091#ifdef CONFIG_NFSD_PNFS
4092static __be32
4093nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
4094 struct nfsd4_getdeviceinfo *gdev)
4095{
4096 struct xdr_stream *xdr = &resp->xdr;
4097 const struct nfsd4_layout_ops *ops =
4098 nfsd4_layout_ops[gdev->gd_layout_type];
4099 u32 starting_len = xdr->buf->len, needed_len;
4100 __be32 *p;
4101
bec782b4 4102 dprintk("%s: err %d\n", __func__, be32_to_cpu(nfserr));
9cf514cc
CH
4103 if (nfserr)
4104 goto out;
4105
4106 nfserr = nfserr_resource;
4107 p = xdr_reserve_space(xdr, 4);
4108 if (!p)
4109 goto out;
4110
4111 *p++ = cpu_to_be32(gdev->gd_layout_type);
4112
4113 /* If maxcount is 0 then just update notifications */
4114 if (gdev->gd_maxcount != 0) {
4115 nfserr = ops->encode_getdeviceinfo(xdr, gdev);
4116 if (nfserr) {
4117 /*
4118 * We don't bother to burden the layout drivers with
4119 * enforcing gd_maxcount, just tell the client to
4120 * come back with a bigger buffer if it's not enough.
4121 */
4122 if (xdr->buf->len + 4 > gdev->gd_maxcount)
4123 goto toosmall;
4124 goto out;
4125 }
4126 }
4127
4128 nfserr = nfserr_resource;
4129 if (gdev->gd_notify_types) {
4130 p = xdr_reserve_space(xdr, 4 + 4);
4131 if (!p)
4132 goto out;
4133 *p++ = cpu_to_be32(1); /* bitmap length */
4134 *p++ = cpu_to_be32(gdev->gd_notify_types);
4135 } else {
4136 p = xdr_reserve_space(xdr, 4);
4137 if (!p)
4138 goto out;
4139 *p++ = 0;
4140 }
4141
4142 nfserr = 0;
4143out:
4144 kfree(gdev->gd_device);
4145 dprintk("%s: done: %d\n", __func__, be32_to_cpu(nfserr));
4146 return nfserr;
4147
4148toosmall:
4149 dprintk("%s: maxcount too small\n", __func__);
4150 needed_len = xdr->buf->len + 4 /* notifications */;
4151 xdr_truncate_encode(xdr, starting_len);
4152 p = xdr_reserve_space(xdr, 4);
4153 if (!p) {
4154 nfserr = nfserr_resource;
4155 } else {
4156 *p++ = cpu_to_be32(needed_len);
4157 nfserr = nfserr_toosmall;
4158 }
4159 goto out;
4160}
4161
4162static __be32
4163nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
4164 struct nfsd4_layoutget *lgp)
4165{
4166 struct xdr_stream *xdr = &resp->xdr;
4167 const struct nfsd4_layout_ops *ops =
4168 nfsd4_layout_ops[lgp->lg_layout_type];
4169 __be32 *p;
4170
4171 dprintk("%s: err %d\n", __func__, nfserr);
4172 if (nfserr)
4173 goto out;
4174
4175 nfserr = nfserr_resource;
4176 p = xdr_reserve_space(xdr, 36 + sizeof(stateid_opaque_t));
4177 if (!p)
4178 goto out;
4179
4180 *p++ = cpu_to_be32(1); /* we always set return-on-close */
4181 *p++ = cpu_to_be32(lgp->lg_sid.si_generation);
4182 p = xdr_encode_opaque_fixed(p, &lgp->lg_sid.si_opaque,
4183 sizeof(stateid_opaque_t));
4184
4185 *p++ = cpu_to_be32(1); /* we always return a single layout */
4186 p = xdr_encode_hyper(p, lgp->lg_seg.offset);
4187 p = xdr_encode_hyper(p, lgp->lg_seg.length);
4188 *p++ = cpu_to_be32(lgp->lg_seg.iomode);
4189 *p++ = cpu_to_be32(lgp->lg_layout_type);
4190
4191 nfserr = ops->encode_layoutget(xdr, lgp);
4192out:
4193 kfree(lgp->lg_content);
4194 return nfserr;
4195}
4196
4197static __be32
4198nfsd4_encode_layoutcommit(struct nfsd4_compoundres *resp, __be32 nfserr,
4199 struct nfsd4_layoutcommit *lcp)
4200{
4201 struct xdr_stream *xdr = &resp->xdr;
4202 __be32 *p;
4203
4204 if (nfserr)
4205 return nfserr;
4206
4207 p = xdr_reserve_space(xdr, 4);
4208 if (!p)
4209 return nfserr_resource;
4210 *p++ = cpu_to_be32(lcp->lc_size_chg);
4211 if (lcp->lc_size_chg) {
4212 p = xdr_reserve_space(xdr, 8);
4213 if (!p)
4214 return nfserr_resource;
4215 p = xdr_encode_hyper(p, lcp->lc_newsize);
4216 }
4217
4218 return nfs_ok;
4219}
4220
4221static __be32
4222nfsd4_encode_layoutreturn(struct nfsd4_compoundres *resp, __be32 nfserr,
4223 struct nfsd4_layoutreturn *lrp)
4224{
4225 struct xdr_stream *xdr = &resp->xdr;
4226 __be32 *p;
4227
4228 if (nfserr)
4229 return nfserr;
4230
4231 p = xdr_reserve_space(xdr, 4);
4232 if (!p)
4233 return nfserr_resource;
4234 *p++ = cpu_to_be32(lrp->lrs_present);
4235 if (lrp->lrs_present)
376675da 4236 return nfsd4_encode_stateid(xdr, &lrp->lr_sid);
9cf514cc
CH
4237 return nfs_ok;
4238}
4239#endif /* CONFIG_NFSD_PNFS */
4240
29ae7f9d
AS
4241static __be32
4242nfsd42_encode_write_res(struct nfsd4_compoundres *resp, struct nfsd42_write_res *write)
4243{
4244 __be32 *p;
4245
4246 p = xdr_reserve_space(&resp->xdr, 4 + 8 + 4 + NFS4_VERIFIER_SIZE);
4247 if (!p)
4248 return nfserr_resource;
4249
4250 *p++ = cpu_to_be32(0);
4251 p = xdr_encode_hyper(p, write->wr_bytes_written);
4252 *p++ = cpu_to_be32(write->wr_stable_how);
4253 p = xdr_encode_opaque_fixed(p, write->wr_verifier.data,
4254 NFS4_VERIFIER_SIZE);
4255 return nfs_ok;
4256}
4257
4258static __be32
4259nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,
4260 struct nfsd4_copy *copy)
4261{
4262 __be32 *p;
4263
4264 if (!nfserr) {
4265 nfserr = nfsd42_encode_write_res(resp, &copy->cp_res);
4266 if (nfserr)
4267 return nfserr;
4268
4269 p = xdr_reserve_space(&resp->xdr, 4 + 4);
4270 *p++ = cpu_to_be32(copy->cp_consecutive);
4271 *p++ = cpu_to_be32(copy->cp_synchronous);
4272 }
4273 return nfserr;
4274}
4275
24bab491
AS
4276static __be32
4277nfsd4_encode_seek(struct nfsd4_compoundres *resp, __be32 nfserr,
4278 struct nfsd4_seek *seek)
4279{
4280 __be32 *p;
4281
4282 if (nfserr)
4283 return nfserr;
4284
4285 p = xdr_reserve_space(&resp->xdr, 4 + 8);
4286 *p++ = cpu_to_be32(seek->seek_eof);
4287 p = xdr_encode_hyper(p, seek->seek_pos);
4288
4289 return nfserr;
4290}
4291
695e12f8
BH
4292static __be32
4293nfsd4_encode_noop(struct nfsd4_compoundres *resp, __be32 nfserr, void *p)
4294{
4295 return nfserr;
4296}
4297
4298typedef __be32(* nfsd4_enc)(struct nfsd4_compoundres *, __be32, void *);
4299
2db134eb
AA
4300/*
4301 * Note: nfsd4_enc_ops vector is shared for v4.0 and v4.1
4302 * since we don't need to filter out obsolete ops as this is
4303 * done in the decoding phase.
4304 */
695e12f8 4305static nfsd4_enc nfsd4_enc_ops[] = {
ad1060c8
BF
4306 [OP_ACCESS] = (nfsd4_enc)nfsd4_encode_access,
4307 [OP_CLOSE] = (nfsd4_enc)nfsd4_encode_close,
4308 [OP_COMMIT] = (nfsd4_enc)nfsd4_encode_commit,
4309 [OP_CREATE] = (nfsd4_enc)nfsd4_encode_create,
4310 [OP_DELEGPURGE] = (nfsd4_enc)nfsd4_encode_noop,
4311 [OP_DELEGRETURN] = (nfsd4_enc)nfsd4_encode_noop,
4312 [OP_GETATTR] = (nfsd4_enc)nfsd4_encode_getattr,
4313 [OP_GETFH] = (nfsd4_enc)nfsd4_encode_getfh,
4314 [OP_LINK] = (nfsd4_enc)nfsd4_encode_link,
4315 [OP_LOCK] = (nfsd4_enc)nfsd4_encode_lock,
4316 [OP_LOCKT] = (nfsd4_enc)nfsd4_encode_lockt,
4317 [OP_LOCKU] = (nfsd4_enc)nfsd4_encode_locku,
4318 [OP_LOOKUP] = (nfsd4_enc)nfsd4_encode_noop,
4319 [OP_LOOKUPP] = (nfsd4_enc)nfsd4_encode_noop,
4320 [OP_NVERIFY] = (nfsd4_enc)nfsd4_encode_noop,
4321 [OP_OPEN] = (nfsd4_enc)nfsd4_encode_open,
84f09f46 4322 [OP_OPENATTR] = (nfsd4_enc)nfsd4_encode_noop,
ad1060c8
BF
4323 [OP_OPEN_CONFIRM] = (nfsd4_enc)nfsd4_encode_open_confirm,
4324 [OP_OPEN_DOWNGRADE] = (nfsd4_enc)nfsd4_encode_open_downgrade,
4325 [OP_PUTFH] = (nfsd4_enc)nfsd4_encode_noop,
4326 [OP_PUTPUBFH] = (nfsd4_enc)nfsd4_encode_noop,
4327 [OP_PUTROOTFH] = (nfsd4_enc)nfsd4_encode_noop,
4328 [OP_READ] = (nfsd4_enc)nfsd4_encode_read,
4329 [OP_READDIR] = (nfsd4_enc)nfsd4_encode_readdir,
4330 [OP_READLINK] = (nfsd4_enc)nfsd4_encode_readlink,
4331 [OP_REMOVE] = (nfsd4_enc)nfsd4_encode_remove,
4332 [OP_RENAME] = (nfsd4_enc)nfsd4_encode_rename,
4333 [OP_RENEW] = (nfsd4_enc)nfsd4_encode_noop,
4334 [OP_RESTOREFH] = (nfsd4_enc)nfsd4_encode_noop,
4335 [OP_SAVEFH] = (nfsd4_enc)nfsd4_encode_noop,
4336 [OP_SECINFO] = (nfsd4_enc)nfsd4_encode_secinfo,
4337 [OP_SETATTR] = (nfsd4_enc)nfsd4_encode_setattr,
4338 [OP_SETCLIENTID] = (nfsd4_enc)nfsd4_encode_setclientid,
4339 [OP_SETCLIENTID_CONFIRM] = (nfsd4_enc)nfsd4_encode_noop,
4340 [OP_VERIFY] = (nfsd4_enc)nfsd4_encode_noop,
4341 [OP_WRITE] = (nfsd4_enc)nfsd4_encode_write,
4342 [OP_RELEASE_LOCKOWNER] = (nfsd4_enc)nfsd4_encode_noop,
2db134eb
AA
4343
4344 /* NFSv4.1 operations */
4345 [OP_BACKCHANNEL_CTL] = (nfsd4_enc)nfsd4_encode_noop,
1d1bc8f2 4346 [OP_BIND_CONN_TO_SESSION] = (nfsd4_enc)nfsd4_encode_bind_conn_to_session,
2db134eb
AA
4347 [OP_EXCHANGE_ID] = (nfsd4_enc)nfsd4_encode_exchange_id,
4348 [OP_CREATE_SESSION] = (nfsd4_enc)nfsd4_encode_create_session,
43212cc7
KM
4349 [OP_DESTROY_SESSION] = (nfsd4_enc)nfsd4_encode_noop,
4350 [OP_FREE_STATEID] = (nfsd4_enc)nfsd4_encode_noop,
2db134eb 4351 [OP_GET_DIR_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
9cf514cc
CH
4352#ifdef CONFIG_NFSD_PNFS
4353 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_getdeviceinfo,
4354 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
4355 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_layoutcommit,
4356 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_layoutget,
4357 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_layoutreturn,
4358#else
2db134eb
AA
4359 [OP_GETDEVICEINFO] = (nfsd4_enc)nfsd4_encode_noop,
4360 [OP_GETDEVICELIST] = (nfsd4_enc)nfsd4_encode_noop,
4361 [OP_LAYOUTCOMMIT] = (nfsd4_enc)nfsd4_encode_noop,
4362 [OP_LAYOUTGET] = (nfsd4_enc)nfsd4_encode_noop,
4363 [OP_LAYOUTRETURN] = (nfsd4_enc)nfsd4_encode_noop,
9cf514cc 4364#endif
22b6dee8 4365 [OP_SECINFO_NO_NAME] = (nfsd4_enc)nfsd4_encode_secinfo_no_name,
2db134eb
AA
4366 [OP_SEQUENCE] = (nfsd4_enc)nfsd4_encode_sequence,
4367 [OP_SET_SSV] = (nfsd4_enc)nfsd4_encode_noop,
17456804 4368 [OP_TEST_STATEID] = (nfsd4_enc)nfsd4_encode_test_stateid,
2db134eb
AA
4369 [OP_WANT_DELEGATION] = (nfsd4_enc)nfsd4_encode_noop,
4370 [OP_DESTROY_CLIENTID] = (nfsd4_enc)nfsd4_encode_noop,
4371 [OP_RECLAIM_COMPLETE] = (nfsd4_enc)nfsd4_encode_noop,
87a15a80
AS
4372
4373 /* NFSv4.2 operations */
4374 [OP_ALLOCATE] = (nfsd4_enc)nfsd4_encode_noop,
29ae7f9d 4375 [OP_COPY] = (nfsd4_enc)nfsd4_encode_copy,
87a15a80
AS
4376 [OP_COPY_NOTIFY] = (nfsd4_enc)nfsd4_encode_noop,
4377 [OP_DEALLOCATE] = (nfsd4_enc)nfsd4_encode_noop,
4378 [OP_IO_ADVISE] = (nfsd4_enc)nfsd4_encode_noop,
4379 [OP_LAYOUTERROR] = (nfsd4_enc)nfsd4_encode_noop,
4380 [OP_LAYOUTSTATS] = (nfsd4_enc)nfsd4_encode_noop,
4381 [OP_OFFLOAD_CANCEL] = (nfsd4_enc)nfsd4_encode_noop,
4382 [OP_OFFLOAD_STATUS] = (nfsd4_enc)nfsd4_encode_noop,
4383 [OP_READ_PLUS] = (nfsd4_enc)nfsd4_encode_noop,
24bab491 4384 [OP_SEEK] = (nfsd4_enc)nfsd4_encode_seek,
87a15a80 4385 [OP_WRITE_SAME] = (nfsd4_enc)nfsd4_encode_noop,
ffa0160a 4386 [OP_CLONE] = (nfsd4_enc)nfsd4_encode_noop,
695e12f8
BH
4387};
4388
496c262c 4389/*
a8095f7e
BF
4390 * Calculate whether we still have space to encode repsize bytes.
4391 * There are two considerations:
4392 * - For NFS versions >=4.1, the size of the reply must stay within
4393 * session limits
4394 * - For all NFS versions, we must stay within limited preallocated
4395 * buffer space.
496c262c 4396 *
a8095f7e
BF
4397 * This is called before the operation is processed, so can only provide
4398 * an upper estimate. For some nonidempotent operations (such as
4399 * getattr), it's not necessarily a problem if that estimate is wrong,
4400 * as we can fail it after processing without significant side effects.
496c262c 4401 */
a8095f7e 4402__be32 nfsd4_check_resp_size(struct nfsd4_compoundres *resp, u32 respsize)
496c262c 4403{
67492c99 4404 struct xdr_buf *buf = &resp->rqstp->rq_res;
47ee5298 4405 struct nfsd4_slot *slot = resp->cstate.slot;
496c262c 4406
47ee5298
BF
4407 if (buf->len + respsize <= buf->buflen)
4408 return nfs_ok;
4409 if (!nfsd4_has_session(&resp->cstate))
ea8d7720 4410 return nfserr_resource;
47ee5298
BF
4411 if (slot->sl_flags & NFSD4_SLOT_CACHETHIS) {
4412 WARN_ON_ONCE(1);
4413 return nfserr_rep_too_big_to_cache;
ea8d7720 4414 }
47ee5298 4415 return nfserr_rep_too_big;
496c262c
AA
4416}
4417
1da177e4
LT
4418void
4419nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)
4420{
082d4bd7 4421 struct xdr_stream *xdr = &resp->xdr;
9411b1d4 4422 struct nfs4_stateowner *so = resp->cstate.replay_owner;
5f4ab945 4423 struct svc_rqst *rqstp = resp->rqstp;
082d4bd7 4424 int post_err_offset;
07d1f802 4425 nfsd4_enc encoder;
bc749ca4 4426 __be32 *p;
1da177e4 4427
d0a381dd
BF
4428 p = xdr_reserve_space(xdr, 8);
4429 if (!p) {
4430 WARN_ON_ONCE(1);
4431 return;
4432 }
c373b0a4 4433 *p++ = cpu_to_be32(op->opnum);
082d4bd7 4434 post_err_offset = xdr->buf->len;
1da177e4 4435
695e12f8
BH
4436 if (op->opnum == OP_ILLEGAL)
4437 goto status;
4438 BUG_ON(op->opnum < 0 || op->opnum >= ARRAY_SIZE(nfsd4_enc_ops) ||
4439 !nfsd4_enc_ops[op->opnum]);
07d1f802
BF
4440 encoder = nfsd4_enc_ops[op->opnum];
4441 op->status = encoder(resp, op->status, &op->u);
2825a7f9
BF
4442 xdr_commit_encode(xdr);
4443
067e1ace 4444 /* nfsd4_check_resp_size guarantees enough room for error status */
5f4ab945
BF
4445 if (!op->status) {
4446 int space_needed = 0;
4447 if (!nfsd4_last_compound_op(rqstp))
4448 space_needed = COMPOUND_ERR_SLACK_SPACE;
4449 op->status = nfsd4_check_resp_size(resp, space_needed);
4450 }
c8f13d97
BF
4451 if (op->status == nfserr_resource && nfsd4_has_session(&resp->cstate)) {
4452 struct nfsd4_slot *slot = resp->cstate.slot;
4453
4454 if (slot->sl_flags & NFSD4_SLOT_CACHETHIS)
4455 op->status = nfserr_rep_too_big_to_cache;
4456 else
4457 op->status = nfserr_rep_too_big;
4458 }
07d1f802
BF
4459 if (op->status == nfserr_resource ||
4460 op->status == nfserr_rep_too_big ||
4461 op->status == nfserr_rep_too_big_to_cache) {
4462 /*
4463 * The operation may have already been encoded or
4464 * partially encoded. No op returns anything additional
4465 * in the case of one of these three errors, so we can
4466 * just truncate back to after the status. But it's a
4467 * bug if we had to do this on a non-idempotent op:
4468 */
4469 warn_on_nonidempotent_op(op);
082d4bd7 4470 xdr_truncate_encode(xdr, post_err_offset);
07d1f802 4471 }
9411b1d4 4472 if (so) {
082d4bd7
BF
4473 int len = xdr->buf->len - post_err_offset;
4474
9411b1d4 4475 so->so_replay.rp_status = op->status;
082d4bd7
BF
4476 so->so_replay.rp_buflen = len;
4477 read_bytes_from_xdr_buf(xdr->buf, post_err_offset,
4478 so->so_replay.rp_buf, len);
9411b1d4 4479 }
695e12f8 4480status:
082d4bd7
BF
4481 /* Note that op->status is already in network byte order: */
4482 write_bytes_to_xdr_buf(xdr->buf, post_err_offset - 4, &op->status, 4);
1da177e4
LT
4483}
4484
4485/*
4486 * Encode the reply stored in the stateowner reply cache
4487 *
4488 * XDR note: do not encode rp->rp_buflen: the buffer contains the
4489 * previously sent already encoded operation.
1da177e4
LT
4490 */
4491void
d0a381dd 4492nfsd4_encode_replay(struct xdr_stream *xdr, struct nfsd4_op *op)
1da177e4 4493{
bc749ca4 4494 __be32 *p;
1da177e4
LT
4495 struct nfs4_replay *rp = op->replay;
4496
4497 BUG_ON(!rp);
4498
d0a381dd
BF
4499 p = xdr_reserve_space(xdr, 8 + rp->rp_buflen);
4500 if (!p) {
4501 WARN_ON_ONCE(1);
4502 return;
4503 }
c373b0a4 4504 *p++ = cpu_to_be32(op->opnum);
1da177e4 4505 *p++ = rp->rp_status; /* already xdr'ed */
1da177e4 4506
0c0c267b 4507 p = xdr_encode_opaque_fixed(p, rp->rp_buf, rp->rp_buflen);
1da177e4
LT
4508}
4509
1da177e4 4510int
2ebbc012 4511nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
1da177e4
LT
4512{
4513 return xdr_ressize_check(rqstp, p);
4514}
4515
3e98abff 4516int nfsd4_release_compoundargs(void *rq, __be32 *p, void *resp)
1da177e4 4517{
3e98abff
BF
4518 struct svc_rqst *rqstp = rq;
4519 struct nfsd4_compoundargs *args = rqstp->rq_argp;
4520
1da177e4
LT
4521 if (args->ops != args->iops) {
4522 kfree(args->ops);
4523 args->ops = args->iops;
4524 }
f99d49ad
JJ
4525 kfree(args->tmpp);
4526 args->tmpp = NULL;
1da177e4 4527 while (args->to_free) {
d5e23383 4528 struct svcxdr_tmpbuf *tb = args->to_free;
1da177e4 4529 args->to_free = tb->next;
1da177e4
LT
4530 kfree(tb);
4531 }
3e98abff 4532 return 1;
1da177e4
LT
4533}
4534
4535int
2ebbc012 4536nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args)
1da177e4 4537{
e874f9f8
JL
4538 if (rqstp->rq_arg.head[0].iov_len % 4) {
4539 /* client is nuts */
4540 dprintk("%s: compound not properly padded! (peeraddr=%pISc xid=0x%x)",
4541 __func__, svc_addr(rqstp), be32_to_cpu(rqstp->rq_xid));
4542 return 0;
4543 }
1da177e4
LT
4544 args->p = p;
4545 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len;
4546 args->pagelist = rqstp->rq_arg.pages;
4547 args->pagelen = rqstp->rq_arg.page_len;
4548 args->tmpp = NULL;
4549 args->to_free = NULL;
4550 args->ops = args->iops;
4551 args->rqstp = rqstp;
4552
3e98abff 4553 return !nfsd4_decode_compound(args);
1da177e4
LT
4554}
4555
4556int
2ebbc012 4557nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp)
1da177e4
LT
4558{
4559 /*
4560 * All that remains is to write the tag and operation count...
4561 */
6ac90391
BF
4562 struct xdr_buf *buf = resp->xdr.buf;
4563
4564 WARN_ON_ONCE(buf->len != buf->head[0].iov_len + buf->page_len +
4565 buf->tail[0].iov_len);
dd97fdde 4566
2825a7f9
BF
4567 rqstp->rq_next_page = resp->xdr.page_ptr + 1;
4568
1da177e4
LT
4569 p = resp->tagp;
4570 *p++ = htonl(resp->taglen);
4571 memcpy(p, resp->tag, resp->taglen);
4572 p += XDR_QUADLEN(resp->taglen);
4573 *p++ = htonl(resp->opcnt);
4574
b607664e 4575 nfsd4_sequence_done(resp);
1da177e4
LT
4576 return 1;
4577}
4578
4579/*
4580 * Local variables:
4581 * c-basic-offset: 8
4582 * End:
4583 */