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