Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/fuse/fuse_internal.h
Show All 26 Lines | |||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
* | * | ||||
* Copyright (C) 2005 Csaba Henk. | * Copyright (C) 2005 Csaba Henk. | ||||
* All rights reserved. | * All rights reserved. | ||||
* | * | ||||
* Copyright (c) 2019 The FreeBSD Foundation | |||||
* | |||||
* Portions of this software were developed by BFF Storage Systems, LLC under | |||||
* sponsorship from the FreeBSD Foundation. | |||||
* | |||||
* Redistribution and use in source and binary forms, with or without | * Redistribution and use in source and binary forms, with or without | ||||
* modification, are permitted provided that the following conditions | * modification, are permitted provided that the following conditions | ||||
* are met: | * are met: | ||||
* 1. Redistributions of source code must retain the above copyright | * 1. Redistributions of source code must retain the above copyright | ||||
* notice, this list of conditions and the following disclaimer. | * notice, this list of conditions and the following disclaimer. | ||||
* 2. Redistributions in binary form must reproduce the above copyright | * 2. Redistributions in binary form must reproduce the above copyright | ||||
* notice, this list of conditions and the following disclaimer in the | * notice, this list of conditions and the following disclaimer in the | ||||
* documentation and/or other materials provided with the distribution. | * documentation and/or other materials provided with the distribution. | ||||
Show All 12 Lines | |||||
* | * | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#ifndef _FUSE_INTERNAL_H_ | #ifndef _FUSE_INTERNAL_H_ | ||||
#define _FUSE_INTERNAL_H_ | #define _FUSE_INTERNAL_H_ | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/counter.h> | |||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <sys/vnode.h> | #include <sys/vnode.h> | ||||
#include "fuse_ipc.h" | #include "fuse_ipc.h" | ||||
#include "fuse_node.h" | #include "fuse_node.h" | ||||
extern counter_u64_t fuse_lookup_cache_hits; | |||||
extern counter_u64_t fuse_lookup_cache_misses; | |||||
static inline bool | static inline bool | ||||
vfs_isrdonly(struct mount *mp) | vfs_isrdonly(struct mount *mp) | ||||
{ | { | ||||
return ((mp->mnt_flag & MNT_RDONLY) != 0); | return ((mp->mnt_flag & MNT_RDONLY) != 0); | ||||
} | } | ||||
static inline struct mount * | static inline struct mount * | ||||
vnode_mount(struct vnode *vp) | vnode_mount(struct vnode *vp) | ||||
{ | { | ||||
return (vp->v_mount); | return (vp->v_mount); | ||||
} | } | ||||
static inline bool | |||||
vnode_mountedhere(struct vnode *vp) | |||||
{ | |||||
return (vp->v_mountedhere != NULL); | |||||
} | |||||
static inline enum vtype | static inline enum vtype | ||||
vnode_vtype(struct vnode *vp) | vnode_vtype(struct vnode *vp) | ||||
{ | { | ||||
return (vp->v_type); | return (vp->v_type); | ||||
} | } | ||||
static inline bool | static inline bool | ||||
vnode_isvroot(struct vnode *vp) | vnode_isvroot(struct vnode *vp) | ||||
Show All 32 Lines | |||||
} | } | ||||
static inline void | static inline void | ||||
uio_setoffset(struct uio *uio, off_t offset) | uio_setoffset(struct uio *uio, off_t offset) | ||||
{ | { | ||||
uio->uio_offset = offset; | uio->uio_offset = offset; | ||||
} | } | ||||
static inline void | |||||
uio_setresid(struct uio *uio, ssize_t resid) | |||||
{ | |||||
uio->uio_resid = resid; | |||||
} | |||||
/* miscellaneous */ | /* miscellaneous */ | ||||
static inline bool | static inline bool | ||||
fuse_isdeadfs(struct vnode *vp) | fuse_isdeadfs(struct vnode *vp) | ||||
{ | { | ||||
struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); | struct fuse_data *data = fuse_get_mpdata(vnode_mount(vp)); | ||||
return (data->dataflags & FSESS_DEAD); | return (data->dataflags & FSESS_DEAD); | ||||
} | } | ||||
static inline uint64_t | static inline uint64_t | ||||
fuse_iosize(struct vnode *vp) | fuse_iosize(struct vnode *vp) | ||||
{ | { | ||||
return (vp->v_mount->mnt_stat.f_iosize); | return (vp->v_mount->mnt_stat.f_iosize); | ||||
} | } | ||||
/* access */ | /* | ||||
* Make a cacheable timeout in bintime format value based on a fuse_attr_out | |||||
* response | |||||
*/ | |||||
static inline void | |||||
fuse_validity_2_bintime(uint64_t attr_valid, uint32_t attr_valid_nsec, | |||||
struct bintime *timeout) | |||||
{ | |||||
struct timespec now, duration, timeout_ts; | |||||
#define FVP_ACCESS_NOOP 0x01 | getnanouptime(&now); | ||||
/* "+ 2" is the bound of attr_valid_nsec + now.tv_nsec */ | |||||
/* Why oh why isn't there a TIME_MAX defined? */ | |||||
if (attr_valid >= INT_MAX || attr_valid + now.tv_sec + 2 >= INT_MAX) { | |||||
timeout->sec = INT_MAX; | |||||
} else { | |||||
duration.tv_sec = attr_valid; | |||||
duration.tv_nsec = attr_valid_nsec; | |||||
timespecadd(&duration, &now, &timeout_ts); | |||||
timespec2bintime(&timeout_ts, timeout); | |||||
} | |||||
} | |||||
#define FACCESS_VA_VALID 0x01 | /* | ||||
#define FACCESS_DO_ACCESS 0x02 | * Make a cacheable timeout value in timespec format based on the fuse_entry_out | ||||
#define FACCESS_STICKY 0x04 | * response | ||||
#define FACCESS_CHOWN 0x08 | */ | ||||
#define FACCESS_NOCHECKSPY 0x10 | static inline void | ||||
#define FACCESS_SETGID 0x12 | fuse_validity_2_timespec(const struct fuse_entry_out *feo, | ||||
struct timespec *timeout) | |||||
{ | |||||
struct timespec duration, now; | |||||
#define FACCESS_XQUERIES (FACCESS_STICKY | FACCESS_CHOWN | FACCESS_SETGID) | getnanouptime(&now); | ||||
/* "+ 2" is the bound of entry_valid_nsec + now.tv_nsec */ | |||||
if (feo->entry_valid >= INT_MAX || | |||||
feo->entry_valid + now.tv_sec + 2 >= INT_MAX) { | |||||
timeout->tv_sec = INT_MAX; | |||||
} else { | |||||
duration.tv_sec = feo->entry_valid; | |||||
duration.tv_nsec = feo->entry_valid_nsec; | |||||
timespecadd(&duration, &now, timeout); | |||||
} | |||||
} | |||||
struct fuse_access_param { | |||||
uid_t xuid; | |||||
gid_t xgid; | |||||
uint32_t facc_flags; | |||||
}; | |||||
/* VFS ops */ | |||||
int | |||||
fuse_internal_get_cached_vnode(struct mount*, ino_t, int, struct vnode**); | |||||
/* access */ | |||||
static inline int | static inline int | ||||
fuse_match_cred(struct ucred *basecred, struct ucred *usercred) | fuse_match_cred(struct ucred *basecred, struct ucred *usercred) | ||||
{ | { | ||||
if (basecred->cr_uid == usercred->cr_uid && | if (basecred->cr_uid == usercred->cr_uid && | ||||
basecred->cr_uid == usercred->cr_ruid && | basecred->cr_uid == usercred->cr_ruid && | ||||
basecred->cr_uid == usercred->cr_svuid && | basecred->cr_uid == usercred->cr_svuid && | ||||
basecred->cr_groups[0] == usercred->cr_groups[0] && | basecred->cr_groups[0] == usercred->cr_groups[0] && | ||||
basecred->cr_groups[0] == usercred->cr_rgid && | basecred->cr_groups[0] == usercred->cr_rgid && | ||||
basecred->cr_groups[0] == usercred->cr_svgid) | basecred->cr_groups[0] == usercred->cr_svgid) | ||||
return (0); | return (0); | ||||
return (EPERM); | return (EPERM); | ||||
} | } | ||||
int fuse_internal_access(struct vnode *vp, mode_t mode, | int fuse_internal_access(struct vnode *vp, accmode_t mode, | ||||
struct fuse_access_param *facp, struct thread *td, struct ucred *cred); | struct thread *td, struct ucred *cred); | ||||
/* attributes */ | /* attributes */ | ||||
void fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr, | void fuse_internal_cache_attrs(struct vnode *vp, struct fuse_attr *attr, | ||||
uint64_t attr_valid, uint32_t attr_valid_nsec, struct vattr *vap); | uint64_t attr_valid, uint32_t attr_valid_nsec, struct vattr *vap); | ||||
/* fsync */ | /* fsync */ | ||||
int fuse_internal_fsync(struct vnode *vp, struct thread *td, | int fuse_internal_fsync(struct vnode *vp, struct thread *td, int waitfor, | ||||
struct ucred *cred, struct fuse_filehandle *fufh); | bool datasync); | ||||
int fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio); | int fuse_internal_fsync_callback(struct fuse_ticket *tick, struct uio *uio); | ||||
/* readdir */ | /* getattr */ | ||||
int fuse_internal_do_getattr(struct vnode *vp, struct vattr *vap, | |||||
struct ucred *cred, struct thread *td); | |||||
int fuse_internal_getattr(struct vnode *vp, struct vattr *vap, | |||||
struct ucred *cred, struct thread *td); | |||||
/* asynchronous invalidation */ | |||||
int fuse_internal_invalidate_entry(struct mount *mp, struct uio *uio); | |||||
int fuse_internal_invalidate_inode(struct mount *mp, struct uio *uio); | |||||
/* mknod */ | |||||
int fuse_internal_mknod(struct vnode *dvp, struct vnode **vpp, | |||||
struct componentname *cnp, struct vattr *vap); | |||||
/* readdir */ | |||||
struct pseudo_dirent { | struct pseudo_dirent { | ||||
uint32_t d_namlen; | uint32_t d_namlen; | ||||
}; | }; | ||||
int fuse_internal_readdir(struct vnode *vp, struct uio *uio, off_t startoff, | |||||
struct fuse_filehandle *fufh, struct fuse_iov *cookediov, int *ncookies, | |||||
u_long *cookies); | |||||
int fuse_internal_readdir_processdata(struct uio *uio, off_t startoff, | |||||
int *fnd_start, size_t reqsize, void *buf, size_t bufsize, | |||||
struct fuse_iov *cookediov, int *ncookies, u_long **cookiesp); | |||||
int fuse_internal_readdir(struct vnode *vp, struct uio *uio, | |||||
struct fuse_filehandle *fufh, struct fuse_iov *cookediov); | |||||
int fuse_internal_readdir_processdata(struct uio *uio, size_t reqsize, | |||||
void *buf, size_t bufsize, void *param); | |||||
/* remove */ | /* remove */ | ||||
int fuse_internal_remove(struct vnode *dvp, struct vnode *vp, | int fuse_internal_remove(struct vnode *dvp, struct vnode *vp, | ||||
struct componentname *cnp, enum fuse_opcode op); | struct componentname *cnp, enum fuse_opcode op); | ||||
/* rename */ | /* rename */ | ||||
int fuse_internal_rename(struct vnode *fdvp, struct componentname *fcnp, | int fuse_internal_rename(struct vnode *fdvp, struct componentname *fcnp, | ||||
struct vnode *tdvp, struct componentname *tcnp); | struct vnode *tdvp, struct componentname *tcnp); | ||||
/* revoke */ | /* revoke */ | ||||
void fuse_internal_vnode_disappear(struct vnode *vp); | void fuse_internal_vnode_disappear(struct vnode *vp); | ||||
/* setattr */ | |||||
int fuse_internal_setattr(struct vnode *vp, struct vattr *va, | |||||
struct thread *td, struct ucred *cred); | |||||
/* strategy */ | /* strategy */ | ||||
/* entity creation */ | /* entity creation */ | ||||
static inline int | static inline int | ||||
fuse_internal_checkentry(struct fuse_entry_out *feo, enum vtype vtyp) | fuse_internal_checkentry(struct fuse_entry_out *feo, enum vtype vtyp) | ||||
{ | { | ||||
if (vtyp != IFTOVT(feo->attr.mode)) { | if (vtyp != IFTOVT(feo->attr.mode)) { | ||||
Show All 27 Lines | |||||
int fuse_internal_forget_callback(struct fuse_ticket *tick, struct uio *uio); | int fuse_internal_forget_callback(struct fuse_ticket *tick, struct uio *uio); | ||||
void fuse_internal_forget_send(struct mount *mp, struct thread *td, | void fuse_internal_forget_send(struct mount *mp, struct thread *td, | ||||
struct ucred *cred, uint64_t nodeid, uint64_t nlookup); | struct ucred *cred, uint64_t nodeid, uint64_t nlookup); | ||||
/* fuse start/stop */ | /* fuse start/stop */ | ||||
int fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio); | int fuse_internal_init_callback(struct fuse_ticket *tick, struct uio *uio); | ||||
void fuse_internal_send_init(struct fuse_data *data, struct thread *td); | void fuse_internal_send_init(struct fuse_data *data, struct thread *td); | ||||
/* module load/unload */ | |||||
void fuse_internal_init(void); | |||||
void fuse_internal_destroy(void); | |||||
#endif /* _FUSE_INTERNAL_H_ */ | #endif /* _FUSE_INTERNAL_H_ */ |