1 // SPDX-License-Identifier: GPL-2.0
3 * XDR support for nfsd/protocol version 3.
5 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
7 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
10 #include <linux/namei.h>
11 #include <linux/sunrpc/svc_xprt.h>
18 * Force construction of an empty post-op attr
20 static const struct svc_fh nfs3svc_null_fh
= {
25 * time_delta. {1, 0} means the server is accurate only
26 * to the nearest second.
28 static const struct timespec64 nfs3svc_time_delta
= {
34 * Mapping of S_IF* types to NFS file types
36 static const u32 nfs3_ftypes
[] = {
37 NF3NON
, NF3FIFO
, NF3CHR
, NF3BAD
,
38 NF3DIR
, NF3BAD
, NF3BLK
, NF3BAD
,
39 NF3REG
, NF3BAD
, NF3LNK
, NF3BAD
,
40 NF3SOCK
, NF3BAD
, NF3LNK
, NF3BAD
,
45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
49 encode_nfstime3(__be32
*p
, const struct timespec64
*time
)
51 *p
++ = cpu_to_be32((u32
)time
->tv_sec
);
52 *p
++ = cpu_to_be32(time
->tv_nsec
);
58 svcxdr_decode_nfstime3(struct xdr_stream
*xdr
, struct timespec64
*timep
)
62 p
= xdr_inline_decode(xdr
, XDR_UNIT
* 2);
65 timep
->tv_sec
= be32_to_cpup(p
++);
66 timep
->tv_nsec
= be32_to_cpup(p
);
72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH
74 * @fhp: OUT: filled-in server file handle
77 * %false: The encoded file handle was not valid
78 * %true: @fhp has been initialized
81 svcxdr_decode_nfs_fh3(struct xdr_stream
*xdr
, struct svc_fh
*fhp
)
86 if (xdr_stream_decode_u32(xdr
, &size
) < 0)
88 if (size
== 0 || size
> NFS3_FHSIZE
)
90 p
= xdr_inline_decode(xdr
, size
);
93 fh_init(fhp
, NFS3_FHSIZE
);
94 fhp
->fh_handle
.fh_size
= size
;
95 memcpy(&fhp
->fh_handle
.fh_base
, p
, size
);
101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code
103 * @status: status value to encode
106 * %false: Send buffer space was exhausted
110 svcxdr_encode_nfsstat3(struct xdr_stream
*xdr
, __be32 status
)
114 p
= xdr_reserve_space(xdr
, sizeof(status
));
123 svcxdr_encode_nfs_fh3(struct xdr_stream
*xdr
, const struct svc_fh
*fhp
)
125 u32 size
= fhp
->fh_handle
.fh_size
;
128 p
= xdr_reserve_space(xdr
, XDR_UNIT
+ size
);
131 *p
++ = cpu_to_be32(size
);
133 p
[XDR_QUADLEN(size
) - 1] = 0;
134 memcpy(p
, &fhp
->fh_handle
.fh_base
, size
);
140 svcxdr_encode_post_op_fh3(struct xdr_stream
*xdr
, const struct svc_fh
*fhp
)
142 if (xdr_stream_encode_item_present(xdr
) < 0)
144 if (!svcxdr_encode_nfs_fh3(xdr
, fhp
))
151 svcxdr_encode_cookieverf3(struct xdr_stream
*xdr
, const __be32
*verf
)
155 p
= xdr_reserve_space(xdr
, NFS3_COOKIEVERFSIZE
);
158 memcpy(p
, verf
, NFS3_COOKIEVERFSIZE
);
164 svcxdr_encode_writeverf3(struct xdr_stream
*xdr
, const __be32
*verf
)
168 p
= xdr_reserve_space(xdr
, NFS3_WRITEVERFSIZE
);
171 memcpy(p
, verf
, NFS3_WRITEVERFSIZE
);
177 svcxdr_decode_filename3(struct xdr_stream
*xdr
, char **name
, unsigned int *len
)
183 if (xdr_stream_decode_u32(xdr
, &size
) < 0)
185 if (size
== 0 || size
> NFS3_MAXNAMLEN
)
187 p
= xdr_inline_decode(xdr
, size
);
193 for (i
= 0, c
= *name
; i
< size
; i
++, c
++) {
194 if (*c
== '\0' || *c
== '/')
202 svcxdr_decode_diropargs3(struct xdr_stream
*xdr
, struct svc_fh
*fhp
,
203 char **name
, unsigned int *len
)
205 return svcxdr_decode_nfs_fh3(xdr
, fhp
) &&
206 svcxdr_decode_filename3(xdr
, name
, len
);
210 svcxdr_decode_sattr3(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
217 if (xdr_stream_decode_bool(xdr
, &set_it
) < 0)
222 if (xdr_stream_decode_u32(xdr
, &mode
) < 0)
224 iap
->ia_valid
|= ATTR_MODE
;
227 if (xdr_stream_decode_bool(xdr
, &set_it
) < 0)
232 if (xdr_stream_decode_u32(xdr
, &uid
) < 0)
234 iap
->ia_uid
= make_kuid(nfsd_user_namespace(rqstp
), uid
);
235 if (uid_valid(iap
->ia_uid
))
236 iap
->ia_valid
|= ATTR_UID
;
238 if (xdr_stream_decode_bool(xdr
, &set_it
) < 0)
243 if (xdr_stream_decode_u32(xdr
, &gid
) < 0)
245 iap
->ia_gid
= make_kgid(nfsd_user_namespace(rqstp
), gid
);
246 if (gid_valid(iap
->ia_gid
))
247 iap
->ia_valid
|= ATTR_GID
;
249 if (xdr_stream_decode_bool(xdr
, &set_it
) < 0)
254 if (xdr_stream_decode_u64(xdr
, &newsize
) < 0)
256 iap
->ia_valid
|= ATTR_SIZE
;
257 iap
->ia_size
= newsize
;
259 if (xdr_stream_decode_u32(xdr
, &set_it
) < 0)
264 case SET_TO_SERVER_TIME
:
265 iap
->ia_valid
|= ATTR_ATIME
;
267 case SET_TO_CLIENT_TIME
:
268 if (!svcxdr_decode_nfstime3(xdr
, &iap
->ia_atime
))
270 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
275 if (xdr_stream_decode_u32(xdr
, &set_it
) < 0)
280 case SET_TO_SERVER_TIME
:
281 iap
->ia_valid
|= ATTR_MTIME
;
283 case SET_TO_CLIENT_TIME
:
284 if (!svcxdr_decode_nfstime3(xdr
, &iap
->ia_mtime
))
286 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
296 svcxdr_decode_sattrguard3(struct xdr_stream
*xdr
, struct nfsd3_sattrargs
*args
)
301 if (xdr_stream_decode_bool(xdr
, &check
) < 0)
304 p
= xdr_inline_decode(xdr
, XDR_UNIT
* 2);
307 args
->check_guard
= 1;
308 args
->guardtime
= be32_to_cpup(p
);
310 args
->check_guard
= 0;
316 svcxdr_decode_specdata3(struct xdr_stream
*xdr
, struct nfsd3_mknodargs
*args
)
320 p
= xdr_inline_decode(xdr
, XDR_UNIT
* 2);
323 args
->major
= be32_to_cpup(p
++);
324 args
->minor
= be32_to_cpup(p
);
330 svcxdr_decode_devicedata3(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
331 struct nfsd3_mknodargs
*args
)
333 return svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
) &&
334 svcxdr_decode_specdata3(xdr
, args
);
338 svcxdr_encode_fattr3(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
339 const struct svc_fh
*fhp
, const struct kstat
*stat
)
341 struct user_namespace
*userns
= nfsd_user_namespace(rqstp
);
345 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 21);
349 *p
++ = cpu_to_be32(nfs3_ftypes
[(stat
->mode
& S_IFMT
) >> 12]);
350 *p
++ = cpu_to_be32((u32
)(stat
->mode
& S_IALLUGO
));
351 *p
++ = cpu_to_be32((u32
)stat
->nlink
);
352 *p
++ = cpu_to_be32((u32
)from_kuid_munged(userns
, stat
->uid
));
353 *p
++ = cpu_to_be32((u32
)from_kgid_munged(userns
, stat
->gid
));
354 if (S_ISLNK(stat
->mode
) && stat
->size
> NFS3_MAXPATHLEN
)
355 p
= xdr_encode_hyper(p
, (u64
)NFS3_MAXPATHLEN
);
357 p
= xdr_encode_hyper(p
, (u64
)stat
->size
);
360 p
= xdr_encode_hyper(p
, ((u64
)stat
->blocks
) << 9);
363 *p
++ = cpu_to_be32((u32
)MAJOR(stat
->rdev
));
364 *p
++ = cpu_to_be32((u32
)MINOR(stat
->rdev
));
366 switch(fsid_source(fhp
)) {
367 case FSIDSOURCE_FSID
:
368 fsid
= (u64
)fhp
->fh_export
->ex_fsid
;
370 case FSIDSOURCE_UUID
:
371 fsid
= ((u64
*)fhp
->fh_export
->ex_uuid
)[0];
372 fsid
^= ((u64
*)fhp
->fh_export
->ex_uuid
)[1];
375 fsid
= (u64
)huge_encode_dev(fhp
->fh_dentry
->d_sb
->s_dev
);
377 p
= xdr_encode_hyper(p
, fsid
);
380 p
= xdr_encode_hyper(p
, stat
->ino
);
382 p
= encode_nfstime3(p
, &stat
->atime
);
383 p
= encode_nfstime3(p
, &stat
->mtime
);
384 encode_nfstime3(p
, &stat
->ctime
);
390 svcxdr_encode_wcc_attr(struct xdr_stream
*xdr
, const struct svc_fh
*fhp
)
394 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 6);
397 p
= xdr_encode_hyper(p
, (u64
)fhp
->fh_pre_size
);
398 p
= encode_nfstime3(p
, &fhp
->fh_pre_mtime
);
399 encode_nfstime3(p
, &fhp
->fh_pre_ctime
);
405 svcxdr_encode_pre_op_attr(struct xdr_stream
*xdr
, const struct svc_fh
*fhp
)
407 if (!fhp
->fh_pre_saved
) {
408 if (xdr_stream_encode_item_absent(xdr
) < 0)
413 if (xdr_stream_encode_item_present(xdr
) < 0)
415 return svcxdr_encode_wcc_attr(xdr
, fhp
);
419 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
420 * @rqstp: Context of a completed RPC transaction
422 * @fhp: File handle to encode
425 * %false: Send buffer space was exhausted
429 svcxdr_encode_post_op_attr(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
430 const struct svc_fh
*fhp
)
432 struct dentry
*dentry
= fhp
->fh_dentry
;
436 * The inode may be NULL if the call failed because of a
437 * stale file handle. In this case, no attributes are
440 if (fhp
->fh_no_wcc
|| !dentry
|| !d_really_is_positive(dentry
))
441 goto no_post_op_attrs
;
442 if (fh_getattr(fhp
, &stat
) != nfs_ok
)
443 goto no_post_op_attrs
;
445 if (xdr_stream_encode_item_present(xdr
) < 0)
447 lease_get_mtime(d_inode(dentry
), &stat
.mtime
);
448 if (!svcxdr_encode_fattr3(rqstp
, xdr
, fhp
, &stat
))
454 return xdr_stream_encode_item_absent(xdr
) > 0;
458 * Encode weak cache consistency data
461 svcxdr_encode_wcc_data(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
462 const struct svc_fh
*fhp
)
464 struct dentry
*dentry
= fhp
->fh_dentry
;
466 if (!dentry
|| !d_really_is_positive(dentry
) || !fhp
->fh_post_saved
)
470 if (!svcxdr_encode_pre_op_attr(xdr
, fhp
))
474 if (xdr_stream_encode_item_present(xdr
) < 0)
476 if (!svcxdr_encode_fattr3(rqstp
, xdr
, fhp
, &fhp
->fh_post_attr
))
482 if (xdr_stream_encode_item_absent(xdr
) < 0)
484 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, fhp
))
491 * Fill in the pre_op attr for the wcc data
493 void fill_pre_wcc(struct svc_fh
*fhp
)
497 bool v4
= (fhp
->fh_maxsize
== NFS4_FHSIZE
);
500 if (fhp
->fh_no_wcc
|| fhp
->fh_pre_saved
)
502 inode
= d_inode(fhp
->fh_dentry
);
503 err
= fh_getattr(fhp
, &stat
);
505 /* Grab the times from inode anyway */
506 stat
.mtime
= inode
->i_mtime
;
507 stat
.ctime
= inode
->i_ctime
;
508 stat
.size
= inode
->i_size
;
511 fhp
->fh_pre_change
= nfsd4_change_attribute(&stat
, inode
);
513 fhp
->fh_pre_mtime
= stat
.mtime
;
514 fhp
->fh_pre_ctime
= stat
.ctime
;
515 fhp
->fh_pre_size
= stat
.size
;
516 fhp
->fh_pre_saved
= true;
520 * Fill in the post_op attr for the wcc data
522 void fill_post_wcc(struct svc_fh
*fhp
)
524 bool v4
= (fhp
->fh_maxsize
== NFS4_FHSIZE
);
525 struct inode
*inode
= d_inode(fhp
->fh_dentry
);
531 if (fhp
->fh_post_saved
)
532 printk("nfsd: inode locked twice during operation.\n");
534 err
= fh_getattr(fhp
, &fhp
->fh_post_attr
);
536 fhp
->fh_post_saved
= false;
537 fhp
->fh_post_attr
.ctime
= inode
->i_ctime
;
539 fhp
->fh_post_saved
= true;
541 fhp
->fh_post_change
=
542 nfsd4_change_attribute(&fhp
->fh_post_attr
, inode
);
546 * XDR decode functions
550 nfs3svc_decode_fhandleargs(struct svc_rqst
*rqstp
, __be32
*p
)
552 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
553 struct nfsd_fhandle
*args
= rqstp
->rq_argp
;
555 return svcxdr_decode_nfs_fh3(xdr
, &args
->fh
);
559 nfs3svc_decode_sattrargs(struct svc_rqst
*rqstp
, __be32
*p
)
561 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
562 struct nfsd3_sattrargs
*args
= rqstp
->rq_argp
;
564 return svcxdr_decode_nfs_fh3(xdr
, &args
->fh
) &&
565 svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
) &&
566 svcxdr_decode_sattrguard3(xdr
, args
);
570 nfs3svc_decode_diropargs(struct svc_rqst
*rqstp
, __be32
*p
)
572 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
573 struct nfsd3_diropargs
*args
= rqstp
->rq_argp
;
575 return svcxdr_decode_diropargs3(xdr
, &args
->fh
, &args
->name
, &args
->len
);
579 nfs3svc_decode_accessargs(struct svc_rqst
*rqstp
, __be32
*p
)
581 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
582 struct nfsd3_accessargs
*args
= rqstp
->rq_argp
;
584 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
586 if (xdr_stream_decode_u32(xdr
, &args
->access
) < 0)
593 nfs3svc_decode_readargs(struct svc_rqst
*rqstp
, __be32
*p
)
595 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
596 struct nfsd3_readargs
*args
= rqstp
->rq_argp
;
598 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
600 if (xdr_stream_decode_u64(xdr
, &args
->offset
) < 0)
602 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
609 nfs3svc_decode_writeargs(struct svc_rqst
*rqstp
, __be32
*p
)
611 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
612 struct nfsd3_writeargs
*args
= rqstp
->rq_argp
;
613 u32 max_blocksize
= svc_max_payload(rqstp
);
615 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
617 if (xdr_stream_decode_u64(xdr
, &args
->offset
) < 0)
619 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
621 if (xdr_stream_decode_u32(xdr
, &args
->stable
) < 0)
625 if (xdr_stream_decode_u32(xdr
, &args
->len
) < 0)
629 if (args
->count
!= args
->len
)
631 if (args
->count
> max_blocksize
) {
632 args
->count
= max_blocksize
;
633 args
->len
= max_blocksize
;
635 if (!xdr_stream_subsegment(xdr
, &args
->payload
, args
->count
))
642 nfs3svc_decode_createargs(struct svc_rqst
*rqstp
, __be32
*p
)
644 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
645 struct nfsd3_createargs
*args
= rqstp
->rq_argp
;
647 if (!svcxdr_decode_diropargs3(xdr
, &args
->fh
, &args
->name
, &args
->len
))
649 if (xdr_stream_decode_u32(xdr
, &args
->createmode
) < 0)
651 switch (args
->createmode
) {
652 case NFS3_CREATE_UNCHECKED
:
653 case NFS3_CREATE_GUARDED
:
654 return svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
);
655 case NFS3_CREATE_EXCLUSIVE
:
656 args
->verf
= xdr_inline_decode(xdr
, NFS3_CREATEVERFSIZE
);
667 nfs3svc_decode_mkdirargs(struct svc_rqst
*rqstp
, __be32
*p
)
669 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
670 struct nfsd3_createargs
*args
= rqstp
->rq_argp
;
672 return svcxdr_decode_diropargs3(xdr
, &args
->fh
,
673 &args
->name
, &args
->len
) &&
674 svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
);
678 nfs3svc_decode_symlinkargs(struct svc_rqst
*rqstp
, __be32
*p
)
680 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
681 struct nfsd3_symlinkargs
*args
= rqstp
->rq_argp
;
682 struct kvec
*head
= rqstp
->rq_arg
.head
;
683 struct kvec
*tail
= rqstp
->rq_arg
.tail
;
686 if (!svcxdr_decode_diropargs3(xdr
, &args
->ffh
, &args
->fname
, &args
->flen
))
688 if (!svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
))
690 if (xdr_stream_decode_u32(xdr
, &args
->tlen
) < 0)
694 remaining
= head
->iov_len
+ rqstp
->rq_arg
.page_len
+ tail
->iov_len
;
695 remaining
-= xdr_stream_pos(xdr
);
696 if (remaining
< xdr_align_size(args
->tlen
))
699 args
->first
.iov_base
= xdr
->p
;
700 args
->first
.iov_len
= head
->iov_len
- xdr_stream_pos(xdr
);
706 nfs3svc_decode_mknodargs(struct svc_rqst
*rqstp
, __be32
*p
)
708 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
709 struct nfsd3_mknodargs
*args
= rqstp
->rq_argp
;
711 if (!svcxdr_decode_diropargs3(xdr
, &args
->fh
, &args
->name
, &args
->len
))
713 if (xdr_stream_decode_u32(xdr
, &args
->ftype
) < 0)
715 switch (args
->ftype
) {
718 return svcxdr_decode_devicedata3(rqstp
, xdr
, args
);
721 return svcxdr_decode_sattr3(rqstp
, xdr
, &args
->attrs
);
725 /* Valid XDR but illegal file types */
735 nfs3svc_decode_renameargs(struct svc_rqst
*rqstp
, __be32
*p
)
737 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
738 struct nfsd3_renameargs
*args
= rqstp
->rq_argp
;
740 return svcxdr_decode_diropargs3(xdr
, &args
->ffh
,
741 &args
->fname
, &args
->flen
) &&
742 svcxdr_decode_diropargs3(xdr
, &args
->tfh
,
743 &args
->tname
, &args
->tlen
);
747 nfs3svc_decode_linkargs(struct svc_rqst
*rqstp
, __be32
*p
)
749 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
750 struct nfsd3_linkargs
*args
= rqstp
->rq_argp
;
752 return svcxdr_decode_nfs_fh3(xdr
, &args
->ffh
) &&
753 svcxdr_decode_diropargs3(xdr
, &args
->tfh
,
754 &args
->tname
, &args
->tlen
);
758 nfs3svc_decode_readdirargs(struct svc_rqst
*rqstp
, __be32
*p
)
760 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
761 struct nfsd3_readdirargs
*args
= rqstp
->rq_argp
;
763 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
765 if (xdr_stream_decode_u64(xdr
, &args
->cookie
) < 0)
767 args
->verf
= xdr_inline_decode(xdr
, NFS3_COOKIEVERFSIZE
);
770 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
777 nfs3svc_decode_readdirplusargs(struct svc_rqst
*rqstp
, __be32
*p
)
779 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
780 struct nfsd3_readdirargs
*args
= rqstp
->rq_argp
;
783 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
785 if (xdr_stream_decode_u64(xdr
, &args
->cookie
) < 0)
787 args
->verf
= xdr_inline_decode(xdr
, NFS3_COOKIEVERFSIZE
);
790 /* dircount is ignored */
791 if (xdr_stream_decode_u32(xdr
, &dircount
) < 0)
793 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
800 nfs3svc_decode_commitargs(struct svc_rqst
*rqstp
, __be32
*p
)
802 struct xdr_stream
*xdr
= &rqstp
->rq_arg_stream
;
803 struct nfsd3_commitargs
*args
= rqstp
->rq_argp
;
805 if (!svcxdr_decode_nfs_fh3(xdr
, &args
->fh
))
807 if (xdr_stream_decode_u64(xdr
, &args
->offset
) < 0)
809 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
816 * XDR encode functions
821 nfs3svc_encode_getattrres(struct svc_rqst
*rqstp
, __be32
*p
)
823 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
824 struct nfsd3_attrstat
*resp
= rqstp
->rq_resp
;
826 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
828 switch (resp
->status
) {
830 lease_get_mtime(d_inode(resp
->fh
.fh_dentry
), &resp
->stat
.mtime
);
831 if (!svcxdr_encode_fattr3(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
839 /* SETATTR, REMOVE, RMDIR */
841 nfs3svc_encode_wccstat(struct svc_rqst
*rqstp
, __be32
*p
)
843 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
844 struct nfsd3_attrstat
*resp
= rqstp
->rq_resp
;
846 return svcxdr_encode_nfsstat3(xdr
, resp
->status
) &&
847 svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->fh
);
851 int nfs3svc_encode_lookupres(struct svc_rqst
*rqstp
, __be32
*p
)
853 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
854 struct nfsd3_diropres
*resp
= rqstp
->rq_resp
;
856 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
858 switch (resp
->status
) {
860 if (!svcxdr_encode_nfs_fh3(xdr
, &resp
->fh
))
862 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
864 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->dirfh
))
868 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->dirfh
))
877 nfs3svc_encode_accessres(struct svc_rqst
*rqstp
, __be32
*p
)
879 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
880 struct nfsd3_accessres
*resp
= rqstp
->rq_resp
;
882 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
884 switch (resp
->status
) {
886 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
888 if (xdr_stream_encode_u32(xdr
, resp
->access
) < 0)
892 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
901 nfs3svc_encode_readlinkres(struct svc_rqst
*rqstp
, __be32
*p
)
903 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
904 struct nfsd3_readlinkres
*resp
= rqstp
->rq_resp
;
905 struct kvec
*head
= rqstp
->rq_res
.head
;
907 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
909 switch (resp
->status
) {
911 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
913 if (xdr_stream_encode_u32(xdr
, resp
->len
) < 0)
915 xdr_write_pages(xdr
, resp
->pages
, 0, resp
->len
);
916 if (svc_encode_result_payload(rqstp
, head
->iov_len
, resp
->len
) < 0)
920 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
929 nfs3svc_encode_readres(struct svc_rqst
*rqstp
, __be32
*p
)
931 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
932 struct nfsd3_readres
*resp
= rqstp
->rq_resp
;
933 struct kvec
*head
= rqstp
->rq_res
.head
;
935 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
937 switch (resp
->status
) {
939 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
941 if (xdr_stream_encode_u32(xdr
, resp
->count
) < 0)
943 if (xdr_stream_encode_bool(xdr
, resp
->eof
) < 0)
945 if (xdr_stream_encode_u32(xdr
, resp
->count
) < 0)
947 xdr_write_pages(xdr
, resp
->pages
, rqstp
->rq_res
.page_base
,
949 if (svc_encode_result_payload(rqstp
, head
->iov_len
, resp
->count
) < 0)
953 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
962 nfs3svc_encode_writeres(struct svc_rqst
*rqstp
, __be32
*p
)
964 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
965 struct nfsd3_writeres
*resp
= rqstp
->rq_resp
;
967 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
969 switch (resp
->status
) {
971 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->fh
))
973 if (xdr_stream_encode_u32(xdr
, resp
->count
) < 0)
975 if (xdr_stream_encode_u32(xdr
, resp
->committed
) < 0)
977 if (!svcxdr_encode_writeverf3(xdr
, resp
->verf
))
981 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->fh
))
988 /* CREATE, MKDIR, SYMLINK, MKNOD */
990 nfs3svc_encode_createres(struct svc_rqst
*rqstp
, __be32
*p
)
992 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
993 struct nfsd3_diropres
*resp
= rqstp
->rq_resp
;
995 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
997 switch (resp
->status
) {
999 if (!svcxdr_encode_post_op_fh3(xdr
, &resp
->fh
))
1001 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
1003 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->dirfh
))
1007 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->dirfh
))
1016 nfs3svc_encode_renameres(struct svc_rqst
*rqstp
, __be32
*p
)
1018 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1019 struct nfsd3_renameres
*resp
= rqstp
->rq_resp
;
1021 return svcxdr_encode_nfsstat3(xdr
, resp
->status
) &&
1022 svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->ffh
) &&
1023 svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->tfh
);
1028 nfs3svc_encode_linkres(struct svc_rqst
*rqstp
, __be32
*p
)
1030 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1031 struct nfsd3_linkres
*resp
= rqstp
->rq_resp
;
1033 return svcxdr_encode_nfsstat3(xdr
, resp
->status
) &&
1034 svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
) &&
1035 svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->tfh
);
1040 nfs3svc_encode_readdirres(struct svc_rqst
*rqstp
, __be32
*p
)
1042 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1043 struct nfsd3_readdirres
*resp
= rqstp
->rq_resp
;
1044 struct xdr_buf
*dirlist
= &resp
->dirlist
;
1046 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
1048 switch (resp
->status
) {
1050 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
1052 if (!svcxdr_encode_cookieverf3(xdr
, resp
->verf
))
1054 xdr_write_pages(xdr
, dirlist
->pages
, 0, dirlist
->len
);
1055 /* no more entries */
1056 if (xdr_stream_encode_item_absent(xdr
) < 0)
1058 if (xdr_stream_encode_bool(xdr
, resp
->common
.err
== nfserr_eof
) < 0)
1062 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &resp
->fh
))
1070 compose_entry_fh(struct nfsd3_readdirres
*cd
, struct svc_fh
*fhp
,
1071 const char *name
, int namlen
, u64 ino
)
1073 struct svc_export
*exp
;
1074 struct dentry
*dparent
, *dchild
;
1075 __be32 rv
= nfserr_noent
;
1077 dparent
= cd
->fh
.fh_dentry
;
1078 exp
= cd
->fh
.fh_export
;
1080 if (isdotent(name
, namlen
)) {
1082 dchild
= dget_parent(dparent
);
1084 * Don't return filehandle for ".." if we're at
1085 * the filesystem or export root:
1087 if (dchild
== dparent
)
1089 if (dparent
== exp
->ex_path
.dentry
)
1092 dchild
= dget(dparent
);
1094 dchild
= lookup_positive_unlocked(name
, dparent
, namlen
);
1097 if (d_mountpoint(dchild
))
1099 if (dchild
->d_inode
->i_ino
!= ino
)
1101 rv
= fh_compose(fhp
, exp
, dchild
, &cd
->fh
);
1108 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1109 * @resp: readdir result context
1110 * @offset: offset cookie to encode
1112 * The buffer space for the offset cookie has already been reserved
1113 * by svcxdr_encode_entry3_common().
1115 void nfs3svc_encode_cookie3(struct nfsd3_readdirres
*resp
, u64 offset
)
1117 __be64 cookie
= cpu_to_be64(offset
);
1119 if (!resp
->cookie_offset
)
1121 write_bytes_to_xdr_buf(&resp
->dirlist
, resp
->cookie_offset
, &cookie
,
1123 resp
->cookie_offset
= 0;
1127 svcxdr_encode_entry3_common(struct nfsd3_readdirres
*resp
, const char *name
,
1128 int namlen
, loff_t offset
, u64 ino
)
1130 struct xdr_buf
*dirlist
= &resp
->dirlist
;
1131 struct xdr_stream
*xdr
= &resp
->xdr
;
1133 if (xdr_stream_encode_item_present(xdr
) < 0)
1136 if (xdr_stream_encode_u64(xdr
, ino
) < 0)
1139 if (xdr_stream_encode_opaque(xdr
, name
, min(namlen
, NFS3_MAXNAMLEN
)) < 0)
1142 resp
->cookie_offset
= dirlist
->len
;
1143 if (xdr_stream_encode_u64(xdr
, NFS_OFFSET_MAX
) < 0)
1150 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1151 * @data: directory context
1152 * @name: name of the object to be encoded
1153 * @namlen: length of that name, in bytes
1154 * @offset: the offset of the previous entry
1155 * @ino: the fileid of this entry
1159 * %0: Entry was successfully encoded.
1160 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1162 * On exit, the following fields are updated:
1164 * - resp->common.err
1165 * - resp->cookie_offset
1167 int nfs3svc_encode_entry3(void *data
, const char *name
, int namlen
,
1168 loff_t offset
, u64 ino
, unsigned int d_type
)
1170 struct readdir_cd
*ccd
= data
;
1171 struct nfsd3_readdirres
*resp
= container_of(ccd
,
1172 struct nfsd3_readdirres
,
1174 unsigned int starting_length
= resp
->dirlist
.len
;
1176 /* The offset cookie for the previous entry */
1177 nfs3svc_encode_cookie3(resp
, offset
);
1179 if (!svcxdr_encode_entry3_common(resp
, name
, namlen
, offset
, ino
))
1182 xdr_commit_encode(&resp
->xdr
);
1183 resp
->common
.err
= nfs_ok
;
1187 resp
->cookie_offset
= 0;
1188 resp
->common
.err
= nfserr_toosmall
;
1189 resp
->dirlist
.len
= starting_length
;
1194 svcxdr_encode_entry3_plus(struct nfsd3_readdirres
*resp
, const char *name
,
1195 int namlen
, u64 ino
)
1197 struct xdr_stream
*xdr
= &resp
->xdr
;
1198 struct svc_fh
*fhp
= &resp
->scratch
;
1202 fh_init(fhp
, NFS3_FHSIZE
);
1203 if (compose_entry_fh(resp
, fhp
, name
, namlen
, ino
) != nfs_ok
)
1206 if (!svcxdr_encode_post_op_attr(resp
->rqstp
, xdr
, fhp
))
1208 if (!svcxdr_encode_post_op_fh3(xdr
, fhp
))
1217 if (xdr_stream_encode_item_absent(xdr
) < 0)
1219 if (xdr_stream_encode_item_absent(xdr
) < 0)
1225 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1226 * @data: directory context
1227 * @name: name of the object to be encoded
1228 * @namlen: length of that name, in bytes
1229 * @offset: the offset of the previous entry
1230 * @ino: the fileid of this entry
1234 * %0: Entry was successfully encoded.
1235 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1237 * On exit, the following fields are updated:
1239 * - resp->common.err
1240 * - resp->cookie_offset
1242 int nfs3svc_encode_entryplus3(void *data
, const char *name
, int namlen
,
1243 loff_t offset
, u64 ino
, unsigned int d_type
)
1245 struct readdir_cd
*ccd
= data
;
1246 struct nfsd3_readdirres
*resp
= container_of(ccd
,
1247 struct nfsd3_readdirres
,
1249 unsigned int starting_length
= resp
->dirlist
.len
;
1251 /* The offset cookie for the previous entry */
1252 nfs3svc_encode_cookie3(resp
, offset
);
1254 if (!svcxdr_encode_entry3_common(resp
, name
, namlen
, offset
, ino
))
1256 if (!svcxdr_encode_entry3_plus(resp
, name
, namlen
, ino
))
1259 xdr_commit_encode(&resp
->xdr
);
1260 resp
->common
.err
= nfs_ok
;
1264 resp
->cookie_offset
= 0;
1265 resp
->common
.err
= nfserr_toosmall
;
1266 resp
->dirlist
.len
= starting_length
;
1271 svcxdr_encode_fsstat3resok(struct xdr_stream
*xdr
,
1272 const struct nfsd3_fsstatres
*resp
)
1274 const struct kstatfs
*s
= &resp
->stats
;
1275 u64 bs
= s
->f_bsize
;
1278 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 13);
1281 p
= xdr_encode_hyper(p
, bs
* s
->f_blocks
); /* total bytes */
1282 p
= xdr_encode_hyper(p
, bs
* s
->f_bfree
); /* free bytes */
1283 p
= xdr_encode_hyper(p
, bs
* s
->f_bavail
); /* user available bytes */
1284 p
= xdr_encode_hyper(p
, s
->f_files
); /* total inodes */
1285 p
= xdr_encode_hyper(p
, s
->f_ffree
); /* free inodes */
1286 p
= xdr_encode_hyper(p
, s
->f_ffree
); /* user available inodes */
1287 *p
= cpu_to_be32(resp
->invarsec
); /* mean unchanged time */
1294 nfs3svc_encode_fsstatres(struct svc_rqst
*rqstp
, __be32
*p
)
1296 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1297 struct nfsd3_fsstatres
*resp
= rqstp
->rq_resp
;
1299 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
1301 switch (resp
->status
) {
1303 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1305 if (!svcxdr_encode_fsstat3resok(xdr
, resp
))
1309 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1317 svcxdr_encode_fsinfo3resok(struct xdr_stream
*xdr
,
1318 const struct nfsd3_fsinfores
*resp
)
1322 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 12);
1325 *p
++ = cpu_to_be32(resp
->f_rtmax
);
1326 *p
++ = cpu_to_be32(resp
->f_rtpref
);
1327 *p
++ = cpu_to_be32(resp
->f_rtmult
);
1328 *p
++ = cpu_to_be32(resp
->f_wtmax
);
1329 *p
++ = cpu_to_be32(resp
->f_wtpref
);
1330 *p
++ = cpu_to_be32(resp
->f_wtmult
);
1331 *p
++ = cpu_to_be32(resp
->f_dtpref
);
1332 p
= xdr_encode_hyper(p
, resp
->f_maxfilesize
);
1333 p
= encode_nfstime3(p
, &nfs3svc_time_delta
);
1334 *p
= cpu_to_be32(resp
->f_properties
);
1341 nfs3svc_encode_fsinfores(struct svc_rqst
*rqstp
, __be32
*p
)
1343 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1344 struct nfsd3_fsinfores
*resp
= rqstp
->rq_resp
;
1346 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
1348 switch (resp
->status
) {
1350 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1352 if (!svcxdr_encode_fsinfo3resok(xdr
, resp
))
1356 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1364 svcxdr_encode_pathconf3resok(struct xdr_stream
*xdr
,
1365 const struct nfsd3_pathconfres
*resp
)
1369 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 6);
1372 *p
++ = cpu_to_be32(resp
->p_link_max
);
1373 *p
++ = cpu_to_be32(resp
->p_name_max
);
1374 p
= xdr_encode_bool(p
, resp
->p_no_trunc
);
1375 p
= xdr_encode_bool(p
, resp
->p_chown_restricted
);
1376 p
= xdr_encode_bool(p
, resp
->p_case_insensitive
);
1377 xdr_encode_bool(p
, resp
->p_case_preserving
);
1384 nfs3svc_encode_pathconfres(struct svc_rqst
*rqstp
, __be32
*p
)
1386 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1387 struct nfsd3_pathconfres
*resp
= rqstp
->rq_resp
;
1389 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
1391 switch (resp
->status
) {
1393 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1395 if (!svcxdr_encode_pathconf3resok(xdr
, resp
))
1399 if (!svcxdr_encode_post_op_attr(rqstp
, xdr
, &nfs3svc_null_fh
))
1408 nfs3svc_encode_commitres(struct svc_rqst
*rqstp
, __be32
*p
)
1410 struct xdr_stream
*xdr
= &rqstp
->rq_res_stream
;
1411 struct nfsd3_commitres
*resp
= rqstp
->rq_resp
;
1413 if (!svcxdr_encode_nfsstat3(xdr
, resp
->status
))
1415 switch (resp
->status
) {
1417 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->fh
))
1419 if (!svcxdr_encode_writeverf3(xdr
, resp
->verf
))
1423 if (!svcxdr_encode_wcc_data(rqstp
, xdr
, &resp
->fh
))
1431 * XDR release functions
1434 nfs3svc_release_fhandle(struct svc_rqst
*rqstp
)
1436 struct nfsd3_attrstat
*resp
= rqstp
->rq_resp
;
1442 nfs3svc_release_fhandle2(struct svc_rqst
*rqstp
)
1444 struct nfsd3_fhandle_pair
*resp
= rqstp
->rq_resp
;