151369649SPedro F. Giffuni /*-
251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni *
45fe58019SAttilio Rao * Copyright (c) 2007-2009 Google Inc. and Amit Singh
55fe58019SAttilio Rao * All rights reserved.
65fe58019SAttilio Rao *
75fe58019SAttilio Rao * Redistribution and use in source and binary forms, with or without
85fe58019SAttilio Rao * modification, are permitted provided that the following conditions are
95fe58019SAttilio Rao * met:
105fe58019SAttilio Rao *
115fe58019SAttilio Rao * * Redistributions of source code must retain the above copyright
125fe58019SAttilio Rao * notice, this list of conditions and the following disclaimer.
135fe58019SAttilio Rao * * Redistributions in binary form must reproduce the above
145fe58019SAttilio Rao * copyright notice, this list of conditions and the following disclaimer
155fe58019SAttilio Rao * in the documentation and/or other materials provided with the
165fe58019SAttilio Rao * distribution.
175fe58019SAttilio Rao * * Neither the name of Google Inc. nor the names of its
185fe58019SAttilio Rao * contributors may be used to endorse or promote products derived from
195fe58019SAttilio Rao * this software without specific prior written permission.
205fe58019SAttilio Rao *
215fe58019SAttilio Rao * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225fe58019SAttilio Rao * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235fe58019SAttilio Rao * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245fe58019SAttilio Rao * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255fe58019SAttilio Rao * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265fe58019SAttilio Rao * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275fe58019SAttilio Rao * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285fe58019SAttilio Rao * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295fe58019SAttilio Rao * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305fe58019SAttilio Rao * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315fe58019SAttilio Rao * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325fe58019SAttilio Rao *
335fe58019SAttilio Rao * Copyright (C) 2005 Csaba Henk.
345fe58019SAttilio Rao * All rights reserved.
355fe58019SAttilio Rao *
368aafc8c3SAlan Somers * Copyright (c) 2019 The FreeBSD Foundation
378aafc8c3SAlan Somers *
388aafc8c3SAlan Somers * Portions of this software were developed by BFF Storage Systems, LLC under
398aafc8c3SAlan Somers * sponsorship from the FreeBSD Foundation.
408aafc8c3SAlan Somers *
415fe58019SAttilio Rao * Redistribution and use in source and binary forms, with or without
425fe58019SAttilio Rao * modification, are permitted provided that the following conditions
435fe58019SAttilio Rao * are met:
445fe58019SAttilio Rao * 1. Redistributions of source code must retain the above copyright
455fe58019SAttilio Rao * notice, this list of conditions and the following disclaimer.
465fe58019SAttilio Rao * 2. Redistributions in binary form must reproduce the above copyright
475fe58019SAttilio Rao * notice, this list of conditions and the following disclaimer in the
485fe58019SAttilio Rao * documentation and/or other materials provided with the distribution.
495fe58019SAttilio Rao *
505fe58019SAttilio Rao * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
515fe58019SAttilio Rao * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
525fe58019SAttilio Rao * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
535fe58019SAttilio Rao * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
545fe58019SAttilio Rao * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
555fe58019SAttilio Rao * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
565fe58019SAttilio Rao * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
575fe58019SAttilio Rao * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
585fe58019SAttilio Rao * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
595fe58019SAttilio Rao * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
605fe58019SAttilio Rao * SUCH DAMAGE.
615fe58019SAttilio Rao */
625fe58019SAttilio Rao
635fe58019SAttilio Rao #ifndef _FUSE_INTERNAL_H_
645fe58019SAttilio Rao #define _FUSE_INTERNAL_H_
655fe58019SAttilio Rao
665fe58019SAttilio Rao #include <sys/types.h>
67560a55d0SAlan Somers #include <sys/counter.h>
68508abc94SAlan Somers #include <sys/limits.h>
695fe58019SAttilio Rao #include <sys/uio.h>
705fe58019SAttilio Rao #include <sys/stat.h>
715fe58019SAttilio Rao #include <sys/vnode.h>
725fe58019SAttilio Rao
735fe58019SAttilio Rao #include "fuse_ipc.h"
745fe58019SAttilio Rao #include "fuse_node.h"
755fe58019SAttilio Rao
76560a55d0SAlan Somers extern counter_u64_t fuse_lookup_cache_hits;
77560a55d0SAlan Somers extern counter_u64_t fuse_lookup_cache_misses;
780d2bf489SAlan Somers
7902295cafSConrad Meyer static inline bool
vfs_isrdonly(struct mount * mp)805fe58019SAttilio Rao vfs_isrdonly(struct mount *mp)
815fe58019SAttilio Rao {
8202295cafSConrad Meyer return ((mp->mnt_flag & MNT_RDONLY) != 0);
835fe58019SAttilio Rao }
845fe58019SAttilio Rao
8502295cafSConrad Meyer static inline struct mount *
vnode_mount(struct vnode * vp)865fe58019SAttilio Rao vnode_mount(struct vnode *vp)
875fe58019SAttilio Rao {
885fe58019SAttilio Rao return (vp->v_mount);
895fe58019SAttilio Rao }
905fe58019SAttilio Rao
91*ba8cc6d7SMateusz Guzik static inline __enum_uint8(vtype)
vnode_vtype(struct vnode * vp)925fe58019SAttilio Rao vnode_vtype(struct vnode *vp)
935fe58019SAttilio Rao {
945fe58019SAttilio Rao return (vp->v_type);
955fe58019SAttilio Rao }
965fe58019SAttilio Rao
9702295cafSConrad Meyer static inline bool
vnode_isvroot(struct vnode * vp)985fe58019SAttilio Rao vnode_isvroot(struct vnode *vp)
995fe58019SAttilio Rao {
10002295cafSConrad Meyer return ((vp->v_vflag & VV_ROOT) != 0);
1015fe58019SAttilio Rao }
1025fe58019SAttilio Rao
10302295cafSConrad Meyer static inline bool
vnode_isreg(struct vnode * vp)1045fe58019SAttilio Rao vnode_isreg(struct vnode *vp)
1055fe58019SAttilio Rao {
10602295cafSConrad Meyer return (vp->v_type == VREG);
1075fe58019SAttilio Rao }
1085fe58019SAttilio Rao
10902295cafSConrad Meyer static inline bool
vnode_isdir(struct vnode * vp)1105fe58019SAttilio Rao vnode_isdir(struct vnode *vp)
1115fe58019SAttilio Rao {
11202295cafSConrad Meyer return (vp->v_type == VDIR);
1135fe58019SAttilio Rao }
1145fe58019SAttilio Rao
11502295cafSConrad Meyer static inline bool
vnode_islnk(struct vnode * vp)1165fe58019SAttilio Rao vnode_islnk(struct vnode *vp)
1175fe58019SAttilio Rao {
11802295cafSConrad Meyer return (vp->v_type == VLNK);
1195fe58019SAttilio Rao }
1205fe58019SAttilio Rao
12102295cafSConrad Meyer static inline ssize_t
uio_resid(struct uio * uio)1225fe58019SAttilio Rao uio_resid(struct uio *uio)
1235fe58019SAttilio Rao {
1245fe58019SAttilio Rao return (uio->uio_resid);
1255fe58019SAttilio Rao }
1265fe58019SAttilio Rao
12702295cafSConrad Meyer static inline off_t
uio_offset(struct uio * uio)1285fe58019SAttilio Rao uio_offset(struct uio *uio)
1295fe58019SAttilio Rao {
1305fe58019SAttilio Rao return (uio->uio_offset);
1315fe58019SAttilio Rao }
1325fe58019SAttilio Rao
13302295cafSConrad Meyer static inline void
uio_setoffset(struct uio * uio,off_t offset)1345fe58019SAttilio Rao uio_setoffset(struct uio *uio, off_t offset)
1355fe58019SAttilio Rao {
1365fe58019SAttilio Rao uio->uio_offset = offset;
1375fe58019SAttilio Rao }
1385fe58019SAttilio Rao
1395fe58019SAttilio Rao /* miscellaneous */
1405fe58019SAttilio Rao
14102295cafSConrad Meyer static inline bool
fuse_isdeadfs(struct vnode * vp)1425fe58019SAttilio Rao fuse_isdeadfs(struct vnode *vp)
1435fe58019SAttilio Rao {
1445fe58019SAttilio Rao struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp));
1455fe58019SAttilio Rao
1465fe58019SAttilio Rao return (data->dataflags & FSESS_DEAD);
1475fe58019SAttilio Rao }
1485fe58019SAttilio Rao
14902295cafSConrad Meyer static inline uint64_t
fuse_iosize(struct vnode * vp)1505fe58019SAttilio Rao fuse_iosize(struct vnode *vp)
1515fe58019SAttilio Rao {
15202295cafSConrad Meyer return (vp->v_mount->mnt_stat.f_iosize);
1535fe58019SAttilio Rao }
1545fe58019SAttilio Rao
15544f10c6eSAlan Somers /*
15644f10c6eSAlan Somers * Make a cacheable timeout in bintime format value based on a fuse_attr_out
15744f10c6eSAlan Somers * response
15844f10c6eSAlan Somers */
15944f10c6eSAlan Somers static inline void
fuse_validity_2_bintime(uint64_t attr_valid,uint32_t attr_valid_nsec,struct bintime * timeout)16044f10c6eSAlan Somers fuse_validity_2_bintime(uint64_t attr_valid, uint32_t attr_valid_nsec,
16144f10c6eSAlan Somers struct bintime *timeout)
16244f10c6eSAlan Somers {
16344f10c6eSAlan Somers struct timespec now, duration, timeout_ts;
16444f10c6eSAlan Somers
16544f10c6eSAlan Somers getnanouptime(&now);
16644f10c6eSAlan Somers /* "+ 2" is the bound of attr_valid_nsec + now.tv_nsec */
16744f10c6eSAlan Somers /* Why oh why isn't there a TIME_MAX defined? */
16844f10c6eSAlan Somers if (attr_valid >= INT_MAX || attr_valid + now.tv_sec + 2 >= INT_MAX) {
16944f10c6eSAlan Somers timeout->sec = INT_MAX;
17044f10c6eSAlan Somers } else {
17144f10c6eSAlan Somers duration.tv_sec = attr_valid;
17244f10c6eSAlan Somers duration.tv_nsec = attr_valid_nsec;
17344f10c6eSAlan Somers timespecadd(&duration, &now, &timeout_ts);
17444f10c6eSAlan Somers timespec2bintime(&timeout_ts, timeout);
17544f10c6eSAlan Somers }
17644f10c6eSAlan Somers }
17744f10c6eSAlan Somers
17844f10c6eSAlan Somers /*
17944f10c6eSAlan Somers * Make a cacheable timeout value in timespec format based on the fuse_entry_out
18044f10c6eSAlan Somers * response
18144f10c6eSAlan Somers */
18244f10c6eSAlan Somers static inline void
fuse_validity_2_timespec(const struct fuse_entry_out * feo,struct timespec * timeout)18344f10c6eSAlan Somers fuse_validity_2_timespec(const struct fuse_entry_out *feo,
18444f10c6eSAlan Somers struct timespec *timeout)
18544f10c6eSAlan Somers {
18644f10c6eSAlan Somers struct timespec duration, now;
18744f10c6eSAlan Somers
18844f10c6eSAlan Somers getnanouptime(&now);
18944f10c6eSAlan Somers /* "+ 2" is the bound of entry_valid_nsec + now.tv_nsec */
19044f10c6eSAlan Somers if (feo->entry_valid >= INT_MAX ||
19144f10c6eSAlan Somers feo->entry_valid + now.tv_sec + 2 >= INT_MAX) {
19244f10c6eSAlan Somers timeout->tv_sec = INT_MAX;
19344f10c6eSAlan Somers } else {
19444f10c6eSAlan Somers duration.tv_sec = feo->entry_valid;
19544f10c6eSAlan Somers duration.tv_nsec = feo->entry_valid_nsec;
19644f10c6eSAlan Somers timespecadd(&duration, &now, timeout);
19744f10c6eSAlan Somers }
19844f10c6eSAlan Somers }
19944f10c6eSAlan Somers
200eae1ae13SAlan Somers /* VFS ops */
201eae1ae13SAlan Somers int
202eae1ae13SAlan Somers fuse_internal_get_cached_vnode(struct mount*, ino_t, int, struct vnode**);
203eae1ae13SAlan Somers
2045fe58019SAttilio Rao /* access */
20502295cafSConrad Meyer static inline int
fuse_match_cred(struct ucred * basecred,struct ucred * usercred)2065fe58019SAttilio Rao fuse_match_cred(struct ucred *basecred, struct ucred *usercred)
2075fe58019SAttilio Rao {
2085fe58019SAttilio Rao if (basecred->cr_uid == usercred->cr_uid &&
2095fe58019SAttilio Rao basecred->cr_uid == usercred->cr_ruid &&
2105fe58019SAttilio Rao basecred->cr_uid == usercred->cr_svuid &&
2115fe58019SAttilio Rao basecred->cr_groups[0] == usercred->cr_groups[0] &&
2125fe58019SAttilio Rao basecred->cr_groups[0] == usercred->cr_rgid &&
2135fe58019SAttilio Rao basecred->cr_groups[0] == usercred->cr_svgid)
21402295cafSConrad Meyer return (0);
2155fe58019SAttilio Rao
21602295cafSConrad Meyer return (EPERM);
2175fe58019SAttilio Rao }
2185fe58019SAttilio Rao
219ff4fbdf5SAlan Somers int fuse_internal_access(struct vnode *vp, accmode_t mode,
220666f8543SAlan Somers struct thread *td, struct ucred *cred);
2215fe58019SAttilio Rao
2225fe58019SAttilio Rao /* attributes */
2237e4844f7SAlan Somers void fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr,
2245d94aaacSAlan Somers uint64_t attr_valid, uint32_t attr_valid_nsec, struct vattr *vap,
2255d94aaacSAlan Somers bool from_server);
2265fe58019SAttilio Rao
2275fe58019SAttilio Rao /* fsync */
2285fe58019SAttilio Rao
229915012e0SAlan Somers int fuse_internal_fsync(struct vnode *vp, struct thread *td, int waitfor,
230915012e0SAlan Somers bool datasync);
23102295cafSConrad Meyer int fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio);
2325fe58019SAttilio Rao
233cad67791SAlan Somers /* getattr */
2343d15b234SAlan Somers int fuse_internal_do_getattr(struct vnode *vp, struct vattr *vap,
2353d15b234SAlan Somers struct ucred *cred, struct thread *td);
236cad67791SAlan Somers int fuse_internal_getattr(struct vnode *vp, struct vattr *vap,
237cad67791SAlan Somers struct ucred *cred, struct thread *td);
238cad67791SAlan Somers
239c2d70d6eSAlan Somers /* asynchronous invalidation */
240c2d70d6eSAlan Somers int fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio);
241eae1ae13SAlan Somers int fuse_internal_invalidate_inode(struct mount *mp, struct uio *uio);
2425fe58019SAttilio Rao
243d5ff2688SAlan Somers /* mknod */
244d5ff2688SAlan Somers int fuse_internal_mknod(struct vnode *dvp, struct vnode **vpp,
245d5ff2688SAlan Somers struct componentname *cnp, struct vattr *vap);
246d5ff2688SAlan Somers
247d5ff2688SAlan Somers /* readdir */
248c2d70d6eSAlan Somers struct pseudo_dirent {
249c2d70d6eSAlan Somers uint32_t d_namlen;
250c2d70d6eSAlan Somers };
25100134a07SAlan Somers int fuse_internal_readdir(struct vnode *vp, struct uio *uio,
252e76986fdSAlan Somers struct fuse_filehandle *fufh, struct fuse_iov *cookediov, int *ncookies,
253b214fcceSAlan Somers uint64_t *cookies);
25400134a07SAlan Somers int fuse_internal_readdir_processdata(struct uio *uio, size_t reqsize,
25500134a07SAlan Somers void *buf, size_t bufsize, struct fuse_iov *cookediov, int *ncookies,
25600134a07SAlan Somers uint64_t **cookiesp);
2575fe58019SAttilio Rao
2585fe58019SAttilio Rao /* remove */
2595fe58019SAttilio Rao
26002295cafSConrad Meyer int fuse_internal_remove(struct vnode *dvp, struct vnode *vp,
26102295cafSConrad Meyer struct componentname *cnp, enum fuse_opcode op);
2625fe58019SAttilio Rao
2635fe58019SAttilio Rao /* rename */
2645fe58019SAttilio Rao
26502295cafSConrad Meyer int fuse_internal_rename(struct vnode *fdvp, struct componentname *fcnp,
26602295cafSConrad Meyer struct vnode *tdvp, struct componentname *tcnp);
26702295cafSConrad Meyer
2685fe58019SAttilio Rao /* revoke */
2695fe58019SAttilio Rao
27002295cafSConrad Meyer void fuse_internal_vnode_disappear(struct vnode *vp);
2715fe58019SAttilio Rao
272a90e32deSAlan Somers /* setattr */
273a90e32deSAlan Somers int fuse_internal_setattr(struct vnode *vp, struct vattr *va,
274a90e32deSAlan Somers struct thread *td, struct ucred *cred);
275a90e32deSAlan Somers
27692bbfe1fSAlan Somers /* write */
27792bbfe1fSAlan Somers void fuse_internal_clear_suid_on_write(struct vnode *vp, struct ucred *cred,
27892bbfe1fSAlan Somers struct thread *td);
27992bbfe1fSAlan Somers
2805fe58019SAttilio Rao /* strategy */
2815fe58019SAttilio Rao
2825fe58019SAttilio Rao /* entity creation */
2835fe58019SAttilio Rao
28402295cafSConrad Meyer static inline int
fuse_internal_checkentry(struct fuse_entry_out * feo,__enum_uint8 (vtype)vtyp)285*ba8cc6d7SMateusz Guzik fuse_internal_checkentry(struct fuse_entry_out *feo, __enum_uint8(vtype) vtyp)
2865fe58019SAttilio Rao {
2875fe58019SAttilio Rao if (vtyp != IFTOVT(feo->attr.mode)) {
28802295cafSConrad Meyer return (EINVAL);
2895fe58019SAttilio Rao }
2905fe58019SAttilio Rao
2915fe58019SAttilio Rao if (feo->nodeid == FUSE_NULL_ID) {
29202295cafSConrad Meyer return (EINVAL);
2935fe58019SAttilio Rao }
2945fe58019SAttilio Rao
2955fe58019SAttilio Rao if (feo->nodeid == FUSE_ROOT_ID) {
29602295cafSConrad Meyer return (EINVAL);
2975fe58019SAttilio Rao }
2985fe58019SAttilio Rao
29902295cafSConrad Meyer return (0);
3005fe58019SAttilio Rao }
3015fe58019SAttilio Rao
30202295cafSConrad Meyer int fuse_internal_newentry(struct vnode *dvp, struct vnode **vpp,
30302295cafSConrad Meyer struct componentname *cnp, enum fuse_opcode op, void *buf, size_t bufsize,
304*ba8cc6d7SMateusz Guzik __enum_uint8(vtype) vtyp);
3055fe58019SAttilio Rao
30602295cafSConrad Meyer void fuse_internal_newentry_makerequest(struct mount *mp, uint64_t dnid,
30702295cafSConrad Meyer struct componentname *cnp, enum fuse_opcode op, void *buf, size_t bufsize,
3085fe58019SAttilio Rao struct fuse_dispatcher *fdip);
3095fe58019SAttilio Rao
31002295cafSConrad Meyer int fuse_internal_newentry_core(struct vnode *dvp, struct vnode **vpp,
311*ba8cc6d7SMateusz Guzik struct componentname *cnp, __enum_uint8(vtype) vtyp, struct fuse_dispatcher *fdip);
3125fe58019SAttilio Rao
3135fe58019SAttilio Rao /* entity destruction */
3145fe58019SAttilio Rao
31502295cafSConrad Meyer int fuse_internal_forget_callback(struct fuse_ticket *tick, struct uio *uio);
31602295cafSConrad Meyer void fuse_internal_forget_send(struct mount *mp, struct thread *td,
31702295cafSConrad Meyer struct ucred *cred, uint64_t nodeid, uint64_t nlookup);
3185fe58019SAttilio Rao
3195fe58019SAttilio Rao /* fuse start/stop */
3205fe58019SAttilio Rao
3215fe58019SAttilio Rao int fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio);
3225fe58019SAttilio Rao void fuse_internal_send_init(struct fuse_data *data, struct thread *td);
3235fe58019SAttilio Rao
324560a55d0SAlan Somers /* module load/unload */
325560a55d0SAlan Somers void fuse_internal_init(void);
326560a55d0SAlan Somers void fuse_internal_destroy(void);
327560a55d0SAlan Somers
3285fe58019SAttilio Rao #endif /* _FUSE_INTERNAL_H_ */
329