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