1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
13 * Mapping of S_IF* types to NFS file types
15 static const u32 nfs_ftypes
[] = {
16 NFNON
, NFCHR
, NFCHR
, NFBAD
,
17 NFDIR
, NFBAD
, NFBLK
, NFBAD
,
18 NFREG
, NFBAD
, NFLNK
, NFBAD
,
19 NFSOCK
, NFBAD
, NFLNK
, NFBAD
,
24 * Basic NFSv2 data types (RFC 1094 Section 2.3)
28 * svcxdr_encode_stat - Encode an NFSv2 status code
30 * @status: status value to encode
33 * %false: Send buffer space was exhausted
37 svcxdr_encode_stat(struct xdr_stream
*xdr
, __be32 status
)
41 p
= xdr_reserve_space(xdr
, sizeof(status
));
50 * svcxdr_decode_fhandle - Decode an NFSv2 file handle
51 * @xdr: XDR stream positioned at an encoded NFSv2 FH
52 * @fhp: OUT: filled-in server file handle
55 * %false: The encoded file handle was not valid
56 * %true: @fhp has been initialized
59 svcxdr_decode_fhandle(struct xdr_stream
*xdr
, struct svc_fh
*fhp
)
63 p
= xdr_inline_decode(xdr
, NFS_FHSIZE
);
66 fh_init(fhp
, NFS_FHSIZE
);
67 memcpy(&fhp
->fh_handle
.fh_raw
, p
, NFS_FHSIZE
);
68 fhp
->fh_handle
.fh_size
= NFS_FHSIZE
;
74 svcxdr_encode_fhandle(struct xdr_stream
*xdr
, const struct svc_fh
*fhp
)
78 p
= xdr_reserve_space(xdr
, NFS_FHSIZE
);
81 memcpy(p
, &fhp
->fh_handle
.fh_raw
, NFS_FHSIZE
);
87 encode_timeval(__be32
*p
, const struct timespec64
*time
)
89 *p
++ = cpu_to_be32((u32
)time
->tv_sec
);
91 *p
++ = cpu_to_be32(time
->tv_nsec
/ NSEC_PER_USEC
);
98 svcxdr_decode_filename(struct xdr_stream
*xdr
, char **name
, unsigned int *len
)
104 if (xdr_stream_decode_u32(xdr
, &size
) < 0)
106 if (size
== 0 || size
> NFS_MAXNAMLEN
)
108 p
= xdr_inline_decode(xdr
, size
);
114 for (i
= 0, c
= *name
; i
< size
; i
++, c
++)
115 if (*c
== '\0' || *c
== '/')
122 svcxdr_decode_diropargs(struct xdr_stream
*xdr
, struct svc_fh
*fhp
,
123 char **name
, unsigned int *len
)
125 return svcxdr_decode_fhandle(xdr
, fhp
) &&
126 svcxdr_decode_filename(xdr
, name
, len
);
130 svcxdr_decode_sattr(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
136 p
= xdr_inline_decode(xdr
, XDR_UNIT
* 8);
143 * Some Sun clients put 0xffff in the mode field when they
146 tmp1
= be32_to_cpup(p
++);
147 if (tmp1
!= (u32
)-1 && tmp1
!= 0xffff) {
148 iap
->ia_valid
|= ATTR_MODE
;
152 tmp1
= be32_to_cpup(p
++);
153 if (tmp1
!= (u32
)-1) {
154 iap
->ia_uid
= make_kuid(nfsd_user_namespace(rqstp
), tmp1
);
155 if (uid_valid(iap
->ia_uid
))
156 iap
->ia_valid
|= ATTR_UID
;
159 tmp1
= be32_to_cpup(p
++);
160 if (tmp1
!= (u32
)-1) {
161 iap
->ia_gid
= make_kgid(nfsd_user_namespace(rqstp
), tmp1
);
162 if (gid_valid(iap
->ia_gid
))
163 iap
->ia_valid
|= ATTR_GID
;
166 tmp1
= be32_to_cpup(p
++);
167 if (tmp1
!= (u32
)-1) {
168 iap
->ia_valid
|= ATTR_SIZE
;
172 tmp1
= be32_to_cpup(p
++);
173 tmp2
= be32_to_cpup(p
++);
174 if (tmp1
!= (u32
)-1 && tmp2
!= (u32
)-1) {
175 iap
->ia_valid
|= ATTR_ATIME
| ATTR_ATIME_SET
;
176 iap
->ia_atime
.tv_sec
= tmp1
;
177 iap
->ia_atime
.tv_nsec
= tmp2
* NSEC_PER_USEC
;
180 tmp1
= be32_to_cpup(p
++);
181 tmp2
= be32_to_cpup(p
++);
182 if (tmp1
!= (u32
)-1 && tmp2
!= (u32
)-1) {
183 iap
->ia_valid
|= ATTR_MTIME
| ATTR_MTIME_SET
;
184 iap
->ia_mtime
.tv_sec
= tmp1
;
185 iap
->ia_mtime
.tv_nsec
= tmp2
* NSEC_PER_USEC
;
187 * Passing the invalid value useconds=1000000 for mtime
188 * is a Sun convention for "set both mtime and atime to
189 * current server time". It's needed to make permissions
190 * checks for the "touch" program across v2 mounts to
191 * Solaris and Irix boxes work correctly. See description of
192 * sattr in section 6.1 of "NFS Illustrated" by
193 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
196 iap
->ia_valid
&= ~(ATTR_ATIME_SET
|ATTR_MTIME_SET
);
203 * svcxdr_encode_fattr - Encode NFSv2 file attributes
204 * @rqstp: Context of a completed RPC transaction
206 * @fhp: File handle to encode
207 * @stat: Attributes to encode
210 * %false: Send buffer space was exhausted
214 svcxdr_encode_fattr(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
,
215 const struct svc_fh
*fhp
, const struct kstat
*stat
)
217 struct user_namespace
*userns
= nfsd_user_namespace(rqstp
);
218 struct dentry
*dentry
= fhp
->fh_dentry
;
219 int type
= stat
->mode
& S_IFMT
;
220 struct timespec64 time
;
224 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 17);
228 *p
++ = cpu_to_be32(nfs_ftypes
[type
>> 12]);
229 *p
++ = cpu_to_be32((u32
)stat
->mode
);
230 *p
++ = cpu_to_be32((u32
)stat
->nlink
);
231 *p
++ = cpu_to_be32((u32
)from_kuid_munged(userns
, stat
->uid
));
232 *p
++ = cpu_to_be32((u32
)from_kgid_munged(userns
, stat
->gid
));
234 if (S_ISLNK(type
) && stat
->size
> NFS_MAXPATHLEN
)
235 *p
++ = cpu_to_be32(NFS_MAXPATHLEN
);
237 *p
++ = cpu_to_be32((u32
) stat
->size
);
238 *p
++ = cpu_to_be32((u32
) stat
->blksize
);
239 if (S_ISCHR(type
) || S_ISBLK(type
))
240 *p
++ = cpu_to_be32(new_encode_dev(stat
->rdev
));
242 *p
++ = cpu_to_be32(0xffffffff);
243 *p
++ = cpu_to_be32((u32
)stat
->blocks
);
245 switch (fsid_source(fhp
)) {
246 case FSIDSOURCE_FSID
:
247 fsid
= (u32
)fhp
->fh_export
->ex_fsid
;
249 case FSIDSOURCE_UUID
:
250 fsid
= ((u32
*)fhp
->fh_export
->ex_uuid
)[0];
251 fsid
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[1];
252 fsid
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[2];
253 fsid
^= ((u32
*)fhp
->fh_export
->ex_uuid
)[3];
256 fsid
= new_encode_dev(stat
->dev
);
259 *p
++ = cpu_to_be32(fsid
);
261 *p
++ = cpu_to_be32((u32
)stat
->ino
);
262 p
= encode_timeval(p
, &stat
->atime
);
264 lease_get_mtime(d_inode(dentry
), &time
);
265 p
= encode_timeval(p
, &time
);
266 encode_timeval(p
, &stat
->ctime
);
272 * XDR decode functions
276 nfssvc_decode_fhandleargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
278 struct nfsd_fhandle
*args
= rqstp
->rq_argp
;
280 return svcxdr_decode_fhandle(xdr
, &args
->fh
);
284 nfssvc_decode_sattrargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
286 struct nfsd_sattrargs
*args
= rqstp
->rq_argp
;
288 return svcxdr_decode_fhandle(xdr
, &args
->fh
) &&
289 svcxdr_decode_sattr(rqstp
, xdr
, &args
->attrs
);
293 nfssvc_decode_diropargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
295 struct nfsd_diropargs
*args
= rqstp
->rq_argp
;
297 return svcxdr_decode_diropargs(xdr
, &args
->fh
, &args
->name
, &args
->len
);
301 nfssvc_decode_readargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
303 struct nfsd_readargs
*args
= rqstp
->rq_argp
;
306 if (!svcxdr_decode_fhandle(xdr
, &args
->fh
))
308 if (xdr_stream_decode_u32(xdr
, &args
->offset
) < 0)
310 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
312 /* totalcount is ignored */
313 if (xdr_stream_decode_u32(xdr
, &totalcount
) < 0)
320 nfssvc_decode_writeargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
322 struct nfsd_writeargs
*args
= rqstp
->rq_argp
;
323 u32 beginoffset
, totalcount
;
325 if (!svcxdr_decode_fhandle(xdr
, &args
->fh
))
327 /* beginoffset is ignored */
328 if (xdr_stream_decode_u32(xdr
, &beginoffset
) < 0)
330 if (xdr_stream_decode_u32(xdr
, &args
->offset
) < 0)
332 /* totalcount is ignored */
333 if (xdr_stream_decode_u32(xdr
, &totalcount
) < 0)
337 if (xdr_stream_decode_u32(xdr
, &args
->len
) < 0)
339 if (args
->len
> NFSSVC_MAXBLKSIZE_V2
)
342 return xdr_stream_subsegment(xdr
, &args
->payload
, args
->len
);
346 nfssvc_decode_createargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
348 struct nfsd_createargs
*args
= rqstp
->rq_argp
;
350 return svcxdr_decode_diropargs(xdr
, &args
->fh
,
351 &args
->name
, &args
->len
) &&
352 svcxdr_decode_sattr(rqstp
, xdr
, &args
->attrs
);
356 nfssvc_decode_renameargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
358 struct nfsd_renameargs
*args
= rqstp
->rq_argp
;
360 return svcxdr_decode_diropargs(xdr
, &args
->ffh
,
361 &args
->fname
, &args
->flen
) &&
362 svcxdr_decode_diropargs(xdr
, &args
->tfh
,
363 &args
->tname
, &args
->tlen
);
367 nfssvc_decode_linkargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
369 struct nfsd_linkargs
*args
= rqstp
->rq_argp
;
371 return svcxdr_decode_fhandle(xdr
, &args
->ffh
) &&
372 svcxdr_decode_diropargs(xdr
, &args
->tfh
,
373 &args
->tname
, &args
->tlen
);
377 nfssvc_decode_symlinkargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
379 struct nfsd_symlinkargs
*args
= rqstp
->rq_argp
;
380 struct kvec
*head
= rqstp
->rq_arg
.head
;
382 if (!svcxdr_decode_diropargs(xdr
, &args
->ffh
, &args
->fname
, &args
->flen
))
384 if (xdr_stream_decode_u32(xdr
, &args
->tlen
) < 0)
389 args
->first
.iov_len
= head
->iov_len
- xdr_stream_pos(xdr
);
390 args
->first
.iov_base
= xdr_inline_decode(xdr
, args
->tlen
);
391 if (!args
->first
.iov_base
)
393 return svcxdr_decode_sattr(rqstp
, xdr
, &args
->attrs
);
397 nfssvc_decode_readdirargs(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
399 struct nfsd_readdirargs
*args
= rqstp
->rq_argp
;
401 if (!svcxdr_decode_fhandle(xdr
, &args
->fh
))
403 if (xdr_stream_decode_u32(xdr
, &args
->cookie
) < 0)
405 if (xdr_stream_decode_u32(xdr
, &args
->count
) < 0)
412 * XDR encode functions
416 nfssvc_encode_statres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
418 struct nfsd_stat
*resp
= rqstp
->rq_resp
;
420 return svcxdr_encode_stat(xdr
, resp
->status
);
424 nfssvc_encode_attrstatres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
426 struct nfsd_attrstat
*resp
= rqstp
->rq_resp
;
428 if (!svcxdr_encode_stat(xdr
, resp
->status
))
430 switch (resp
->status
) {
432 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
441 nfssvc_encode_diropres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
443 struct nfsd_diropres
*resp
= rqstp
->rq_resp
;
445 if (!svcxdr_encode_stat(xdr
, resp
->status
))
447 switch (resp
->status
) {
449 if (!svcxdr_encode_fhandle(xdr
, &resp
->fh
))
451 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
460 nfssvc_encode_readlinkres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
462 struct nfsd_readlinkres
*resp
= rqstp
->rq_resp
;
463 struct kvec
*head
= rqstp
->rq_res
.head
;
465 if (!svcxdr_encode_stat(xdr
, resp
->status
))
467 switch (resp
->status
) {
469 if (xdr_stream_encode_u32(xdr
, resp
->len
) < 0)
471 svcxdr_encode_opaque_pages(rqstp
, xdr
, &resp
->page
, 0,
473 if (svc_encode_result_payload(rqstp
, head
->iov_len
, resp
->len
) < 0)
482 nfssvc_encode_readres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
484 struct nfsd_readres
*resp
= rqstp
->rq_resp
;
485 struct kvec
*head
= rqstp
->rq_res
.head
;
487 if (!svcxdr_encode_stat(xdr
, resp
->status
))
489 switch (resp
->status
) {
491 if (!svcxdr_encode_fattr(rqstp
, xdr
, &resp
->fh
, &resp
->stat
))
493 if (xdr_stream_encode_u32(xdr
, resp
->count
) < 0)
495 svcxdr_encode_opaque_pages(rqstp
, xdr
, resp
->pages
,
496 rqstp
->rq_res
.page_base
,
498 if (svc_encode_result_payload(rqstp
, head
->iov_len
, resp
->count
) < 0)
507 nfssvc_encode_readdirres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
509 struct nfsd_readdirres
*resp
= rqstp
->rq_resp
;
510 struct xdr_buf
*dirlist
= &resp
->dirlist
;
512 if (!svcxdr_encode_stat(xdr
, resp
->status
))
514 switch (resp
->status
) {
516 svcxdr_encode_opaque_pages(rqstp
, xdr
, dirlist
->pages
, 0,
518 /* no more entries */
519 if (xdr_stream_encode_item_absent(xdr
) < 0)
521 if (xdr_stream_encode_bool(xdr
, resp
->common
.err
== nfserr_eof
) < 0)
530 nfssvc_encode_statfsres(struct svc_rqst
*rqstp
, struct xdr_stream
*xdr
)
532 struct nfsd_statfsres
*resp
= rqstp
->rq_resp
;
533 struct kstatfs
*stat
= &resp
->stats
;
536 if (!svcxdr_encode_stat(xdr
, resp
->status
))
538 switch (resp
->status
) {
540 p
= xdr_reserve_space(xdr
, XDR_UNIT
* 5);
543 *p
++ = cpu_to_be32(NFSSVC_MAXBLKSIZE_V2
);
544 *p
++ = cpu_to_be32(stat
->f_bsize
);
545 *p
++ = cpu_to_be32(stat
->f_blocks
);
546 *p
++ = cpu_to_be32(stat
->f_bfree
);
547 *p
= cpu_to_be32(stat
->f_bavail
);
555 * nfssvc_encode_nfscookie - Encode a directory offset cookie
556 * @resp: readdir result context
557 * @offset: offset cookie to encode
559 * The buffer space for the offset cookie has already been reserved
560 * by svcxdr_encode_entry_common().
562 void nfssvc_encode_nfscookie(struct nfsd_readdirres
*resp
, u32 offset
)
564 __be32 cookie
= cpu_to_be32(offset
);
566 if (!resp
->cookie_offset
)
569 write_bytes_to_xdr_buf(&resp
->dirlist
, resp
->cookie_offset
, &cookie
,
571 resp
->cookie_offset
= 0;
575 svcxdr_encode_entry_common(struct nfsd_readdirres
*resp
, const char *name
,
576 int namlen
, loff_t offset
, u64 ino
)
578 struct xdr_buf
*dirlist
= &resp
->dirlist
;
579 struct xdr_stream
*xdr
= &resp
->xdr
;
581 if (xdr_stream_encode_item_present(xdr
) < 0)
584 if (xdr_stream_encode_u32(xdr
, (u32
)ino
) < 0)
587 if (xdr_stream_encode_opaque(xdr
, name
, min(namlen
, NFS2_MAXNAMLEN
)) < 0)
590 resp
->cookie_offset
= dirlist
->len
;
591 if (xdr_stream_encode_u32(xdr
, ~0U) < 0)
598 * nfssvc_encode_entry - encode one NFSv2 READDIR entry
599 * @data: directory context
600 * @name: name of the object to be encoded
601 * @namlen: length of that name, in bytes
602 * @offset: the offset of the previous entry
603 * @ino: the fileid of this entry
607 * %0: Entry was successfully encoded.
608 * %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
610 * On exit, the following fields are updated:
613 * - resp->cookie_offset
615 int nfssvc_encode_entry(void *data
, const char *name
, int namlen
,
616 loff_t offset
, u64 ino
, unsigned int d_type
)
618 struct readdir_cd
*ccd
= data
;
619 struct nfsd_readdirres
*resp
= container_of(ccd
,
620 struct nfsd_readdirres
,
622 unsigned int starting_length
= resp
->dirlist
.len
;
624 /* The offset cookie for the previous entry */
625 nfssvc_encode_nfscookie(resp
, offset
);
627 if (!svcxdr_encode_entry_common(resp
, name
, namlen
, offset
, ino
))
630 xdr_commit_encode(&resp
->xdr
);
631 resp
->common
.err
= nfs_ok
;
635 resp
->cookie_offset
= 0;
636 resp
->common
.err
= nfserr_toosmall
;
637 resp
->dirlist
.len
= starting_length
;
642 * XDR release functions
644 void nfssvc_release_attrstat(struct svc_rqst
*rqstp
)
646 struct nfsd_attrstat
*resp
= rqstp
->rq_resp
;
651 void nfssvc_release_diropres(struct svc_rqst
*rqstp
)
653 struct nfsd_diropres
*resp
= rqstp
->rq_resp
;
658 void nfssvc_release_readres(struct svc_rqst
*rqstp
)
660 struct nfsd_readres
*resp
= rqstp
->rq_resp
;