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