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