#ifndef _SYS_MOUNT_H_
#define _SYS_MOUNT_H_
#include <sys/types.h>
#include <sys/ucred.h>
#include <sys/queue.h>
#ifdef _KERNEL
#include <sys/lock.h>
#include <sys/lockmgr.h>
#include <sys/tslog.h>
#include <sys/_mutex.h>
#include <sys/_sx.h>
#elif defined(_WANT_MOUNT)
#include <sys/_lock.h>
#include <sys/_lockmgr.h>
#include <sys/_mutex.h>
#endif
typedef struct fsid { int32_t val[2]; } fsid_t;
static __inline int
fsidcmp(const fsid_t *a, const fsid_t *b)
{
return (a->val[0] != b->val[0] || a->val[1] != b->val[1]);
}
#define MAXFIDSZ 16
struct fid {
u_short fid_len;
u_short fid_data0;
char fid_data[MAXFIDSZ];
};
#define MFSNAMELEN 16
#define MNAMELEN 1024
#define STATFS_VERSION 0x20140518
struct statfs {
uint32_t f_version;
uint32_t f_type;
uint64_t f_flags;
uint64_t f_bsize;
uint64_t f_iosize;
uint64_t f_blocks;
uint64_t f_bfree;
int64_t f_bavail;
uint64_t f_files;
int64_t f_ffree;
uint64_t f_syncwrites;
uint64_t f_asyncwrites;
uint64_t f_syncreads;
uint64_t f_asyncreads;
uint32_t f_nvnodelistsize;
uint32_t f_spare0;
uint64_t f_spare[9];
uint32_t f_namemax;
uid_t f_owner;
fsid_t f_fsid;
char f_charspare[80];
char f_fstypename[MFSNAMELEN];
char f_mntfromname[MNAMELEN];
char f_mntonname[MNAMELEN];
};
#if defined(_WANT_FREEBSD11_STATFS) || defined(_KERNEL)
#define FREEBSD11_STATFS_VERSION 0x20030518
struct freebsd11_statfs {
uint32_t f_version;
uint32_t f_type;
uint64_t f_flags;
uint64_t f_bsize;
uint64_t f_iosize;
uint64_t f_blocks;
uint64_t f_bfree;
int64_t f_bavail;
uint64_t f_files;
int64_t f_ffree;
uint64_t f_syncwrites;
uint64_t f_asyncwrites;
uint64_t f_syncreads;
uint64_t f_asyncreads;
uint64_t f_spare[10];
uint32_t f_namemax;
uid_t f_owner;
fsid_t f_fsid;
char f_charspare[80];
char f_fstypename[16];
char f_mntfromname[88];
char f_mntonname[88];
};
#endif
#ifdef _KERNEL
#define OMFSNAMELEN 16
#define OMNAMELEN (88 - 2 * sizeof(long))
struct ostatfs {
long f_spare2;
long f_bsize;
long f_iosize;
long f_blocks;
long f_bfree;
long f_bavail;
long f_files;
long f_ffree;
fsid_t f_fsid;
uid_t f_owner;
int f_type;
int f_flags;
long f_syncwrites;
long f_asyncwrites;
char f_fstypename[OMFSNAMELEN];
char f_mntonname[OMNAMELEN];
long f_syncreads;
long f_asyncreads;
short f_spares1;
char f_mntfromname[OMNAMELEN];
short f_spares2;
long f_spare[2];
};
#endif
#if defined(_WANT_MOUNT) || defined(_KERNEL)
TAILQ_HEAD(vnodelst, vnode);
TAILQ_HEAD(vfsoptlist, vfsopt);
struct vfsopt {
TAILQ_ENTRY(vfsopt) link;
char *name;
void *value;
int len;
int pos;
int seen;
};
struct mount_pcpu {
int mntp_thread_in_ops;
int mntp_ref;
int mntp_lockref;
int mntp_writeopcount;
};
_Static_assert(sizeof(struct mount_pcpu) == 16,
"the struct is allocated from pcpu 16 zone");
struct mount_upper_node {
struct mount *mp;
TAILQ_ENTRY(mount_upper_node) mnt_upper_link;
};
struct mount {
int mnt_vfs_ops;
int mnt_kern_flag;
uint64_t mnt_flag;
struct mount_pcpu *mnt_pcpu;
struct vnode *mnt_rootvnode;
struct vnode *mnt_vnodecovered;
struct vfsops *mnt_op;
struct vfsconf *mnt_vfc;
struct mtx __aligned(CACHE_LINE_SIZE) mnt_mtx;
int mnt_gen;
#define mnt_startzero mnt_list
TAILQ_ENTRY(mount) mnt_list;
struct vnode *mnt_syncer;
int mnt_ref;
struct vnodelst mnt_nvnodelist;
int mnt_nvnodelistsize;
int mnt_writeopcount;
struct vfsoptlist *mnt_opt;
struct vfsoptlist *mnt_optnew;
struct statfs mnt_stat;
struct ucred *mnt_cred;
void * mnt_data;
time_t mnt_time;
int mnt_iosize_max;
struct netexport *mnt_export;
struct label *mnt_label;
u_int mnt_hashseed;
int mnt_lockref;
int mnt_secondary_writes;
int mnt_secondary_accwrites;
struct thread *mnt_susp_owner;
struct ucred *mnt_exjail;
#define mnt_endzero mnt_gjprovider
char *mnt_gjprovider;
struct mtx mnt_listmtx;
struct vnodelst mnt_lazyvnodelist;
int mnt_lazyvnodelistsize;
int mnt_upper_pending;
struct lock mnt_explock;
struct lock mnt_renamelock;
TAILQ_HEAD(, mount_upper_node) mnt_uppers;
TAILQ_HEAD(, mount_upper_node) mnt_notify;
STAILQ_ENTRY(mount) mnt_taskqueue_link;
uint64_t mnt_taskqueue_flags;
unsigned int mnt_unmount_retries;
};
#endif
#ifdef _KERNEL
struct vnode *__mnt_vnode_next_all(struct vnode **mvp, struct mount *mp);
struct vnode *__mnt_vnode_first_all(struct vnode **mvp, struct mount *mp);
void __mnt_vnode_markerfree_all(struct vnode **mvp, struct mount *mp);
#define MNT_VNODE_FOREACH_ALL(vp, mp, mvp) \
for (vp = __mnt_vnode_first_all(&(mvp), (mp)); \
(vp) != NULL; vp = __mnt_vnode_next_all(&(mvp), (mp)))
#define MNT_VNODE_FOREACH_ALL_ABORT(mp, mvp) \
do { \
MNT_ILOCK(mp); \
__mnt_vnode_markerfree_all(&(mvp), (mp)); \
\
mtx_assert(MNT_MTX(mp), MA_NOTOWNED); \
} while (0)
typedef int mnt_lazy_cb_t(struct vnode *, void *);
struct vnode *__mnt_vnode_next_lazy(struct vnode **mvp, struct mount *mp,
mnt_lazy_cb_t *cb, void *cbarg);
struct vnode *__mnt_vnode_first_lazy(struct vnode **mvp, struct mount *mp,
mnt_lazy_cb_t *cb, void *cbarg);
void __mnt_vnode_markerfree_lazy(struct vnode **mvp, struct mount *mp);
#define MNT_VNODE_FOREACH_LAZY(vp, mp, mvp, cb, cbarg) \
for (vp = __mnt_vnode_first_lazy(&(mvp), (mp), (cb), (cbarg)); \
(vp) != NULL; \
vp = __mnt_vnode_next_lazy(&(mvp), (mp), (cb), (cbarg)))
#define MNT_VNODE_FOREACH_LAZY_ABORT(mp, mvp) \
__mnt_vnode_markerfree_lazy(&(mvp), (mp))
#define MNT_ILOCK(mp) mtx_lock(&(mp)->mnt_mtx)
#define MNT_ITRYLOCK(mp) mtx_trylock(&(mp)->mnt_mtx)
#define MNT_IUNLOCK(mp) mtx_unlock(&(mp)->mnt_mtx)
#define MNT_MTX(mp) (&(mp)->mnt_mtx)
#define MNT_REF(mp) do { \
mtx_assert(MNT_MTX(mp), MA_OWNED); \
mp->mnt_ref++; \
} while (0)
#define MNT_REL(mp) do { \
mtx_assert(MNT_MTX(mp), MA_OWNED); \
(mp)->mnt_ref--; \
if ((mp)->mnt_vfs_ops && (mp)->mnt_ref < 0) \
vfs_dump_mount_counters(mp); \
if ((mp)->mnt_ref == 0 && (mp)->mnt_vfs_ops) \
wakeup((mp)); \
} while (0)
#endif
#if defined(_WANT_MNTOPTNAMES) || defined(_KERNEL)
struct mntoptnames {
uint64_t o_opt;
const char *o_name;
};
#define MNTOPT_NAMES \
{ MNT_ASYNC, "asynchronous" }, \
{ MNT_EXPORTED, "NFS exported" }, \
{ MNT_LOCAL, "local" }, \
{ MNT_NOATIME, "noatime" }, \
{ MNT_NOEXEC, "noexec" }, \
{ MNT_NOSUID, "nosuid" }, \
{ MNT_NOSYMFOLLOW, "nosymfollow" }, \
{ MNT_QUOTA, "with quotas" }, \
{ MNT_RDONLY, "read-only" }, \
{ MNT_SYNCHRONOUS, "synchronous" }, \
{ MNT_UNION, "union" }, \
{ MNT_NOCLUSTERR, "noclusterr" }, \
{ MNT_NOCLUSTERW, "noclusterw" }, \
{ MNT_SUIDDIR, "suiddir" }, \
{ MNT_SOFTDEP, "soft-updates" }, \
{ MNT_SUJ, "journaled soft-updates" }, \
{ MNT_MULTILABEL, "multilabel" }, \
{ MNT_ACLS, "acls" }, \
{ MNT_NFS4ACLS, "nfsv4acls" }, \
{ MNT_GJOURNAL, "gjournal" }, \
{ MNT_AUTOMOUNTED, "automounted" }, \
{ MNT_VERIFIED, "verified" }, \
{ MNT_UNTRUSTED, "untrusted" }, \
{ MNT_NOCOVER, "nocover" }, \
{ MNT_EMPTYDIR, "emptydir" }, \
{ MNT_UPDATE, "update" }, \
{ MNT_DELEXPORT, "delexport" }, \
{ MNT_RELOAD, "reload" }, \
{ MNT_FORCE, "force" }, \
{ MNT_SNAPSHOT, "snapshot" }, \
{ MNT_NAMEDATTR, "named attributes" }, \
{ 0, NULL }
#endif
#define MNT_RDONLY 0x0000000000000001ULL
#define MNT_SYNCHRONOUS 0x0000000000000002ULL
#define MNT_NOEXEC 0x0000000000000004ULL
#define MNT_NOSUID 0x0000000000000008ULL
#define MNT_NFS4ACLS 0x0000000000000010ULL
#define MNT_UNION 0x0000000000000020ULL
#define MNT_ASYNC 0x0000000000000040ULL
#define MNT_SUIDDIR 0x0000000000100000ULL
#define MNT_SOFTDEP 0x0000000000200000ULL
#define MNT_NOSYMFOLLOW 0x0000000000400000ULL
#define MNT_GJOURNAL 0x0000000002000000ULL
#define MNT_MULTILABEL 0x0000000004000000ULL
#define MNT_ACLS 0x0000000008000000ULL
#define MNT_NOATIME 0x0000000010000000ULL
#define MNT_NOCLUSTERR 0x0000000040000000ULL
#define MNT_NOCLUSTERW 0x0000000080000000ULL
#define MNT_SUJ 0x0000000100000000ULL
#define MNT_AUTOMOUNTED 0x0000000200000000ULL
#define MNT_UNTRUSTED 0x0000000800000000ULL
#define MNT_NAMEDATTR 0x0000020000000000ULL
#define MNT_EXRDONLY 0x0000000000000080ULL
#define MNT_EXPORTED 0x0000000000000100ULL
#define MNT_DEFEXPORTED 0x0000000000000200ULL
#define MNT_EXPORTANON 0x0000000000000400ULL
#define MNT_EXKERB 0x0000000000000800ULL
#define MNT_EXPUBLIC 0x0000000020000000ULL
#define MNT_EXTLS 0x0000004000000000ULL
#define MNT_EXTLSCERT 0x0000008000000000ULL
#define MNT_EXTLSCERTUSER 0x0000010000000000ULL
#define MNT_LOCAL 0x0000000000001000ULL
#define MNT_QUOTA 0x0000000000002000ULL
#define MNT_ROOTFS 0x0000000000004000ULL
#define MNT_USER 0x0000000000008000ULL
#define MNT_IGNORE 0x0000000000800000ULL
#define MNT_VERIFIED 0x0000000400000000ULL
#define MNT_VISFLAGMASK (MNT_RDONLY | MNT_SYNCHRONOUS | MNT_NOEXEC | \
MNT_NOSUID | MNT_UNION | MNT_SUJ | \
MNT_ASYNC | MNT_EXRDONLY | MNT_EXPORTED | \
MNT_DEFEXPORTED | MNT_EXPORTANON| MNT_EXKERB | \
MNT_LOCAL | MNT_USER | MNT_QUOTA | \
MNT_ROOTFS | MNT_NOATIME | MNT_NOCLUSTERR| \
MNT_NOCLUSTERW | MNT_SUIDDIR | MNT_SOFTDEP | \
MNT_IGNORE | MNT_EXPUBLIC | MNT_NOSYMFOLLOW | \
MNT_GJOURNAL | MNT_MULTILABEL | MNT_ACLS | \
MNT_NFS4ACLS | MNT_AUTOMOUNTED | MNT_VERIFIED | \
MNT_UNTRUSTED | MNT_NAMEDATTR)
#define MNT_UPDATEMASK (MNT_NOSUID | MNT_NOEXEC | \
MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | \
MNT_NOATIME | \
MNT_NOSYMFOLLOW | MNT_IGNORE | \
MNT_NOCLUSTERR | MNT_NOCLUSTERW | MNT_SUIDDIR | \
MNT_ACLS | MNT_USER | MNT_NFS4ACLS | \
MNT_AUTOMOUNTED | MNT_UNTRUSTED)
#define MNT_UPDATE 0x0000000000010000ULL
#define MNT_DELEXPORT 0x0000000000020000ULL
#define MNT_RELOAD 0x0000000000040000ULL
#define MNT_FORCE 0x0000000000080000ULL
#define MNT_SNAPSHOT 0x0000000001000000ULL
#define MNT_NONBUSY 0x0000000004000000ULL
#define MNT_BYFSID 0x0000000008000000ULL
#define MNT_NOCOVER 0x0000001000000000ULL
#define MNT_EMPTYDIR 0x0000002000000000ULL
#define MNT_RECURSE 0x0000100000000000ULL
#define MNT_DEFERRED 0x0000200000000000ULL
#define MNT_CMDFLAGS (MNT_UPDATE | MNT_DELEXPORT | MNT_RELOAD | \
MNT_FORCE | MNT_SNAPSHOT | MNT_NONBUSY | \
MNT_BYFSID | MNT_NOCOVER | MNT_EMPTYDIR | \
MNT_RECURSE | MNT_DEFERRED)
#define MNTK_UNMOUNTF 0x00000001
#define MNTK_ASYNC 0x00000002
#define MNTK_SOFTDEP 0x00000004
#define MNTK_NOMSYNC 0x00000008
#define MNTK_DRAINING 0x00000010
#define MNTK_REFEXPIRE 0x00000020
#define MNTK_EXTENDED_SHARED 0x00000040
#define MNTK_SHARED_WRITES 0x00000080
#define MNTK_NO_IOPF 0x00000100
#define MNTK_RECURSE 0x00000200
#define MNTK_UPPER_WAITER 0x00000400
#define MNTK_UNLOCKED_INSMNTQUE 0x00001000
#define MNTK_UNMAPPED_BUFS 0x00002000
#define MNTK_USES_BCACHE 0x00004000
#define MNTK_VMSETSIZE_BUG 0x00010000
#define MNTK_UNIONFS 0x00020000
#define MNTK_FPLOOKUP 0x00040000
#define MNTK_SUSPEND_ALL 0x00080000
#define MNTK_TASKQUEUE_WAITER 0x00100000
#define MNTK_NOASYNC 0x00800000
#define MNTK_UNMOUNT 0x01000000
#define MNTK_MWAIT 0x02000000
#define MNTK_SUSPEND 0x08000000
#define MNTK_SUSPEND2 0x04000000
#define MNTK_SUSPENDED 0x10000000
#define MNTK_NULL_NOCACHE 0x20000000
#define MNTK_LOOKUP_SHARED 0x40000000
#ifdef _KERNEL
static inline int
MNT_SHARED_WRITES(struct mount *mp)
{
return (mp != NULL && (mp->mnt_kern_flag & MNTK_SHARED_WRITES) != 0);
}
static inline int
MNT_EXTENDED_SHARED(struct mount *mp)
{
return (mp != NULL && (mp->mnt_kern_flag & MNTK_EXTENDED_SHARED) != 0);
}
#endif
#define VFS_VFSCONF 0
#define VFS_GENERIC 0
#define VFS_MAXTYPENUM 1
#define VFS_CONF 2
#define MNT_WAIT 1
#define MNT_NOWAIT 2
#define MNT_LAZY 3
#define MNT_SUSPEND 4
struct fhandle {
fsid_t fh_fsid;
struct fid fh_fid;
};
typedef struct fhandle fhandle_t;
struct oexport_args {
int ex_flags;
uid_t ex_root;
struct xucred ex_anon;
struct sockaddr *ex_addr;
u_char ex_addrlen;
struct sockaddr *ex_mask;
u_char ex_masklen;
char *ex_indexfile;
};
#define MAXSECFLAVORS 5
struct o2export_args {
int ex_flags;
uid_t ex_root;
struct xucred ex_anon;
struct sockaddr *ex_addr;
u_char ex_addrlen;
struct sockaddr *ex_mask;
u_char ex_masklen;
char *ex_indexfile;
int ex_numsecflavors;
int ex_secflavors[MAXSECFLAVORS];
};
struct export_args {
uint64_t ex_flags;
uid_t ex_root;
uid_t ex_uid;
int ex_ngroups;
gid_t *ex_groups;
struct sockaddr *ex_addr;
u_char ex_addrlen;
struct sockaddr *ex_mask;
u_char ex_masklen;
char *ex_indexfile;
int ex_numsecflavors;
int ex_secflavors[MAXSECFLAVORS];
};
struct nfs_public {
int np_valid;
fhandle_t np_handle;
struct mount *np_mount;
char *np_index;
};
struct vfsconf {
u_int vfc_version;
char vfc_name[MFSNAMELEN];
struct vfsops *vfc_vfsops;
struct vfsops *vfc_vfsops_sd;
int vfc_typenum;
int vfc_refcount;
int vfc_flags;
int vfc_prison_flag;
struct vfsoptdecl *vfc_opts;
TAILQ_ENTRY(vfsconf) vfc_list;
};
struct xvfsconf {
struct vfsops *vfc_vfsops;
char vfc_name[MFSNAMELEN];
int vfc_typenum;
int vfc_refcount;
int vfc_flags;
struct vfsconf *vfc_next;
};
#ifndef BURN_BRIDGES
struct ovfsconf {
void *vfc_vfsops;
char vfc_name[32];
int vfc_index;
int vfc_refcount;
int vfc_flags;
};
#endif
#define VFCF_STATIC 0x00010000
#define VFCF_NETWORK 0x00020000
#define VFCF_READONLY 0x00040000
#define VFCF_SYNTHETIC 0x00080000
#define VFCF_LOOPBACK 0x00100000
#define VFCF_UNICODE 0x00200000
#define VFCF_JAIL 0x00400000
#define VFCF_DELEGADMIN 0x00800000
#define VFCF_SBDRY 0x01000000
#define VFCF_FILEMOUNT 0x02000000
#define VFCF_FILEREVINC 0x04000000
#define VFCF_FILEREVCT 0x08000000
typedef uint32_t fsctlop_t;
struct vfsidctl {
int vc_vers;
fsid_t vc_fsid;
char vc_fstypename[MFSNAMELEN];
fsctlop_t vc_op;
void *vc_ptr;
size_t vc_len;
u_int32_t vc_spare[12];
};
#define VFS_CTL_VERS1 0x01
#define VFS_CTL_QUERY 0x00010001
#define VFS_CTL_TIMEO 0x00010002
#define VFS_CTL_NOLOCKS 0x00010003
struct vfsquery {
u_int32_t vq_flags;
u_int32_t vq_spare[31];
};
#define VQ_NOTRESP 0x0001
#define VQ_NEEDAUTH 0x0002
#define VQ_LOWDISK 0x0004
#define VQ_MOUNT 0x0008
#define VQ_UNMOUNT 0x0010
#define VQ_DEAD 0x0020
#define VQ_ASSIST 0x0040
#define VQ_NOTRESPLOCK 0x0080
#define VQ_FLAG0100 0x0100
#define VQ_FLAG0200 0x0200
#define VQ_FLAG0400 0x0400
#define VQ_FLAG0800 0x0800
#define VQ_FLAG1000 0x1000
#define VQ_FLAG2000 0x2000
#define VQ_FLAG4000 0x4000
#define VQ_FLAG8000 0x8000
#ifdef _KERNEL
#define VCTLTOREQ(vc, req) \
do { \
(req)->newptr = (vc)->vc_ptr; \
(req)->newlen = (vc)->vc_len; \
(req)->newidx = 0; \
} while (0)
#endif
struct iovec;
struct uio;
#ifdef _KERNEL
#define MBF_NOWAIT 0x01
#define MBF_MNTLSTLOCK 0x02
#define MBF_MASK (MBF_NOWAIT | MBF_MNTLSTLOCK)
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_MOUNT);
MALLOC_DECLARE(M_STATFS);
#endif
extern int maxvfsconf;
TAILQ_HEAD(vfsconfhead, vfsconf);
extern struct vfsconfhead vfsconf;
struct mount_args;
struct nameidata;
struct sysctl_req;
struct mntarg;
typedef int vfs_cmount_t(struct mntarg *ma, void *data, uint64_t flags);
typedef int vfs_unmount_t(struct mount *mp, int mntflags);
typedef int vfs_root_t(struct mount *mp, int flags, struct vnode **vpp);
typedef int vfs_quotactl_t(struct mount *mp, int cmds, uid_t uid, void *arg,
bool *mp_busy);
typedef int vfs_statfs_t(struct mount *mp, struct statfs *sbp);
typedef int vfs_sync_t(struct mount *mp, int waitfor);
typedef int vfs_vget_t(struct mount *mp, ino_t ino, int flags,
struct vnode **vpp);
typedef int vfs_fhtovp_t(struct mount *mp, struct fid *fhp,
int flags, struct vnode **vpp);
typedef int vfs_checkexp_t(struct mount *mp, struct sockaddr *nam,
uint64_t *extflagsp, struct ucred **credanonp,
int *numsecflavors, int *secflavors);
typedef int vfs_init_t(struct vfsconf *);
typedef int vfs_uninit_t(struct vfsconf *);
typedef int vfs_extattrctl_t(struct mount *mp, int cmd,
struct vnode *filename_vp, int attrnamespace,
const char *attrname);
typedef int vfs_mount_t(struct mount *mp);
typedef int vfs_sysctl_t(struct mount *mp, fsctlop_t op,
struct sysctl_req *req);
typedef void vfs_susp_clean_t(struct mount *mp);
typedef void vfs_notify_lowervp_t(struct mount *mp, struct vnode *lowervp);
typedef void vfs_purge_t(struct mount *mp);
struct sbuf;
typedef int vfs_report_lockf_t(struct mount *mp, struct sbuf *sb);
struct vfsops {
vfs_mount_t *vfs_mount;
vfs_cmount_t *vfs_cmount;
vfs_unmount_t *vfs_unmount;
vfs_root_t *vfs_root;
vfs_root_t *vfs_cachedroot;
vfs_quotactl_t *vfs_quotactl;
vfs_statfs_t *vfs_statfs;
vfs_sync_t *vfs_sync;
vfs_vget_t *vfs_vget;
vfs_fhtovp_t *vfs_fhtovp;
vfs_checkexp_t *vfs_checkexp;
vfs_init_t *vfs_init;
vfs_uninit_t *vfs_uninit;
vfs_extattrctl_t *vfs_extattrctl;
vfs_sysctl_t *vfs_sysctl;
vfs_susp_clean_t *vfs_susp_clean;
vfs_notify_lowervp_t *vfs_reclaim_lowervp;
vfs_notify_lowervp_t *vfs_unlink_lowervp;
vfs_purge_t *vfs_purge;
vfs_report_lockf_t *vfs_report_lockf;
vfs_mount_t *vfs_spare[6];
};
vfs_statfs_t __vfs_statfs;
#define VFS_MOUNT(MP) ({ \
int _rc; \
\
TSRAW(curthread, TS_ENTER, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\
_rc = (*(MP)->mnt_op->vfs_mount)(MP); \
TSRAW(curthread, TS_EXIT, "VFS_MOUNT", (MP)->mnt_vfc->vfc_name);\
_rc; })
#define VFS_UNMOUNT(MP, FORCE) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_unmount)(MP, FORCE); \
_rc; })
#define VFS_ROOT(MP, FLAGS, VPP) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_root)(MP, FLAGS, VPP); \
_rc; })
#define VFS_CACHEDROOT(MP, FLAGS, VPP) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_cachedroot)(MP, FLAGS, VPP); \
_rc; })
#define VFS_QUOTACTL(MP, C, U, A, MP_BUSY) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_quotactl)(MP, C, U, A, MP_BUSY); \
_rc; })
#define VFS_STATFS(MP, SBP) ({ \
int _rc; \
\
_rc = __vfs_statfs((MP), (SBP)); \
_rc; })
#define VFS_SYNC(MP, WAIT) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_sync)(MP, WAIT); \
_rc; })
#define VFS_VGET(MP, INO, FLAGS, VPP) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_vget)(MP, INO, FLAGS, VPP); \
_rc; })
#define VFS_FHTOVP(MP, FIDP, FLAGS, VPP) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_fhtovp)(MP, FIDP, FLAGS, VPP); \
_rc; })
#define VFS_CHECKEXP(MP, NAM, EXFLG, CRED, NUMSEC, SEC) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_checkexp)(MP, NAM, EXFLG, CRED, NUMSEC,\
SEC); \
_rc; })
#define VFS_EXTATTRCTL(MP, C, FN, NS, N) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_extattrctl)(MP, C, FN, NS, N); \
_rc; })
#define VFS_SYSCTL(MP, OP, REQ) ({ \
int _rc; \
\
_rc = (*(MP)->mnt_op->vfs_sysctl)(MP, OP, REQ); \
_rc; })
#define VFS_SUSP_CLEAN(MP) do { \
if (*(MP)->mnt_op->vfs_susp_clean != NULL) { \
(*(MP)->mnt_op->vfs_susp_clean)(MP); \
} \
} while (0)
#define VFS_RECLAIM_LOWERVP(MP, VP) do { \
if (*(MP)->mnt_op->vfs_reclaim_lowervp != NULL) { \
(*(MP)->mnt_op->vfs_reclaim_lowervp)((MP), (VP)); \
} \
} while (0)
#define VFS_UNLINK_LOWERVP(MP, VP) do { \
if (*(MP)->mnt_op->vfs_unlink_lowervp != NULL) { \
(*(MP)->mnt_op->vfs_unlink_lowervp)((MP), (VP)); \
} \
} while (0)
#define VFS_PURGE(MP) do { \
if (*(MP)->mnt_op->vfs_purge != NULL) { \
(*(MP)->mnt_op->vfs_purge)(MP); \
} \
} while (0)
#define VFS_KNOTE_LOCKED(vp, hint) do \
{ \
VN_KNOTE((vp), (hint), KNF_LISTLOCKED); \
} while (0)
#define VFS_KNOTE_UNLOCKED(vp, hint) do \
{ \
VN_KNOTE((vp), (hint), 0); \
} while (0)
#include <sys/module.h>
#define VFS_VERSION_00 0x19660120
#define VFS_VERSION_01 0x20121030
#define VFS_VERSION_02 0x20180504
#define VFS_VERSION VFS_VERSION_02
#define VFS_SET(vfsops, fsname, flags) \
static struct vfsconf fsname ## _vfsconf = { \
.vfc_version = VFS_VERSION, \
.vfc_name = #fsname, \
.vfc_vfsops = &vfsops, \
.vfc_typenum = -1, \
.vfc_flags = flags, \
}; \
static moduledata_t fsname ## _mod = { \
#fsname, \
vfs_modevent, \
& fsname ## _vfsconf \
}; \
DECLARE_MODULE(fsname, fsname ## _mod, SI_SUB_VFS, SI_ORDER_MIDDLE)
enum vfs_notify_upper_type {
VFS_NOTIFY_UPPER_RECLAIM,
VFS_NOTIFY_UPPER_UNLINK,
};
#define VFS_SUPPORTS_EXJAIL_CLONE 1
int dounmount(struct mount *, uint64_t, struct thread *);
int kernel_mount(struct mntarg *ma, uint64_t flags);
struct mntarg *mount_arg(struct mntarg *ma, const char *name, const void *val, int len);
struct mntarg *mount_argb(struct mntarg *ma, int flag, const char *name);
struct mntarg *mount_argf(struct mntarg *ma, const char *name, const char *fmt, ...);
struct mntarg *mount_argsu(struct mntarg *ma, const char *name, const void *val, int len);
void statfs_scale_blocks(struct statfs *sf, long max_size);
struct vfsconf *vfs_byname(const char *);
struct vfsconf *vfs_byname_kld(const char *, struct thread *td, int *);
void vfs_unref_vfsconf(struct vfsconf *vfsp);
void vfs_mount_destroy(struct mount *);
void vfs_event_signal(fsid_t *, u_int32_t, intptr_t);
void vfs_freeopts(struct vfsoptlist *opts);
void vfs_deleteopt(struct vfsoptlist *opts, const char *name);
int vfs_buildopts(struct uio *auio, struct vfsoptlist **options);
int vfs_flagopt(struct vfsoptlist *opts, const char *name, uint64_t *w,
uint64_t val);
int vfs_getopt(struct vfsoptlist *, const char *, void **, int *);
int vfs_getopt_pos(struct vfsoptlist *opts, const char *name);
int vfs_getopt_size(struct vfsoptlist *opts, const char *name,
off_t *value);
char *vfs_getopts(struct vfsoptlist *, const char *, int *error);
int vfs_copyopt(struct vfsoptlist *, const char *, void *, int);
int vfs_filteropt(struct vfsoptlist *, const char **legal);
void vfs_opterror(struct vfsoptlist *opts, const char *fmt, ...);
int vfs_scanopt(struct vfsoptlist *opts, const char *name, const char *fmt, ...);
int vfs_setopt(struct vfsoptlist *opts, const char *name, void *value,
int len);
int vfs_setopt_part(struct vfsoptlist *opts, const char *name, void *value,
int len);
int vfs_setopts(struct vfsoptlist *opts, const char *name,
const char *value);
int vfs_setpublicfs
(struct mount *, struct netexport *, struct export_args *);
void vfs_periodic(struct mount *, int);
int vfs_busy(struct mount *, int);
void vfs_exjail_clone(struct mount *, struct mount *);
void vfs_exjail_delete(struct prison *);
int vfs_export
(struct mount *, struct export_args *, bool);
void vfs_free_addrlist(struct netexport *);
void vfs_allocate_syncvnode(struct mount *);
void vfs_deallocate_syncvnode(struct mount *);
int vfs_donmount(struct thread *td, uint64_t fsflags,
struct uio *fsoptions);
void vfs_getnewfsid(struct mount *);
struct mount *vfs_getvfs(fsid_t *);
struct mount *vfs_busyfs(fsid_t *);
int vfs_modevent(module_t, int, void *);
void vfs_mount_error(struct mount *, const char *, ...);
void vfs_mountroot(void);
void vfs_mountedfrom(struct mount *, const char *from);
void vfs_notify_upper(struct vnode *, enum vfs_notify_upper_type);
struct mount *vfs_ref_from_vp(struct vnode *);
void vfs_ref(struct mount *);
void vfs_rel(struct mount *);
struct mount *vfs_mount_alloc(struct vnode *, struct vfsconf *, const char *,
struct ucred *);
int vfs_suser(struct mount *, struct thread *);
void vfs_unbusy(struct mount *);
void vfs_unmountall(void);
struct mount *vfs_register_upper_from_vp(struct vnode *,
struct mount *ump, struct mount_upper_node *);
void vfs_register_for_notification(struct mount *, struct mount *,
struct mount_upper_node *);
void vfs_unregister_for_notification(struct mount *,
struct mount_upper_node *);
void vfs_unregister_upper(struct mount *, struct mount_upper_node *);
int vfs_remount_ro(struct mount *mp);
int vfs_report_lockf(struct mount *mp, struct sbuf *sb);
extern TAILQ_HEAD(mntlist, mount) mountlist;
extern struct mtx_padalign mountlist_mtx;
extern struct nfs_public nfs_pub;
extern struct sx vfsconf_sx;
#define vfsconf_lock() sx_xlock(&vfsconf_sx)
#define vfsconf_unlock() sx_xunlock(&vfsconf_sx)
#define vfsconf_slock() sx_slock(&vfsconf_sx)
#define vfsconf_sunlock() sx_sunlock(&vfsconf_sx)
struct vnode *mntfs_allocvp(struct mount *, struct vnode *);
void mntfs_freevp(struct vnode *);
vfs_root_t vfs_stdroot;
vfs_quotactl_t vfs_stdquotactl;
vfs_statfs_t vfs_stdstatfs;
vfs_sync_t vfs_stdsync;
vfs_sync_t vfs_stdnosync;
vfs_vget_t vfs_stdvget;
vfs_fhtovp_t vfs_stdfhtovp;
vfs_checkexp_t vfs_stdcheckexp;
vfs_init_t vfs_stdinit;
vfs_uninit_t vfs_stduninit;
vfs_extattrctl_t vfs_stdextattrctl;
vfs_sysctl_t vfs_stdsysctl;
void syncer_suspend(void);
void syncer_resume(void);
struct vnode *vfs_cache_root_clear(struct mount *);
void vfs_cache_root_set(struct mount *, struct vnode *);
void vfs_op_barrier_wait(struct mount *);
void vfs_op_enter(struct mount *);
void vfs_op_exit_locked(struct mount *);
void vfs_op_exit(struct mount *);
#ifdef DIAGNOSTIC
void vfs_assert_mount_counters(struct mount *);
void vfs_dump_mount_counters(struct mount *);
#else
#define vfs_assert_mount_counters(mp) do { } while (0)
#define vfs_dump_mount_counters(mp) do { } while (0)
#endif
enum mount_counter { MNT_COUNT_REF, MNT_COUNT_LOCKREF, MNT_COUNT_WRITEOPCOUNT };
int vfs_mount_fetch_counter(struct mount *, enum mount_counter);
void suspend_all_fs(void);
void resume_all_fs(void);
#define vfs_mount_pcpu(mp) zpcpu_get(mp->mnt_pcpu)
#define vfs_mount_pcpu_remote(mp, cpu) zpcpu_get_cpu(mp->mnt_pcpu, cpu)
#define vfs_op_thread_entered(mp) ({ \
MPASS(curthread->td_critnest > 0); \
struct mount_pcpu *_mpcpu = vfs_mount_pcpu(mp); \
_mpcpu->mntp_thread_in_ops == 1; \
})
#define vfs_op_thread_enter_crit(mp, _mpcpu) ({ \
bool _retval_crit = true; \
MPASS(curthread->td_critnest > 0); \
_mpcpu = vfs_mount_pcpu(mp); \
MPASS(mpcpu->mntp_thread_in_ops == 0); \
_mpcpu->mntp_thread_in_ops = 1; \
atomic_interrupt_fence(); \
if (__predict_false(mp->mnt_vfs_ops > 0)) { \
vfs_op_thread_exit_crit(mp, _mpcpu); \
_retval_crit = false; \
} \
_retval_crit; \
})
#define vfs_op_thread_enter(mp, _mpcpu) ({ \
bool _retval; \
critical_enter(); \
_retval = vfs_op_thread_enter_crit(mp, _mpcpu); \
if (__predict_false(!_retval)) \
critical_exit(); \
_retval; \
})
#define vfs_op_thread_exit_crit(mp, _mpcpu) do { \
MPASS(_mpcpu == vfs_mount_pcpu(mp)); \
MPASS(_mpcpu->mntp_thread_in_ops == 1); \
atomic_interrupt_fence(); \
_mpcpu->mntp_thread_in_ops = 0; \
} while (0)
#define vfs_op_thread_exit(mp, _mpcpu) do { \
vfs_op_thread_exit_crit(mp, _mpcpu); \
critical_exit(); \
} while (0)
#define vfs_mp_count_add_pcpu(_mpcpu, count, val) do { \
MPASS(_mpcpu->mntp_thread_in_ops == 1); \
_mpcpu->mntp_##count += val; \
} while (0)
#define vfs_mp_count_sub_pcpu(_mpcpu, count, val) do { \
MPASS(_mpcpu->mntp_thread_in_ops == 1); \
_mpcpu->mntp_##count -= val; \
} while (0)
#else
#include <sys/cdefs.h>
struct stat;
__BEGIN_DECLS
int fhlink(struct fhandle *, const char *);
int fhlinkat(struct fhandle *, int, const char *);
int fhopen(const struct fhandle *, int);
int fhreadlink(struct fhandle *, char *, size_t);
int fhstat(const struct fhandle *, struct stat *);
int fhstatfs(const struct fhandle *, struct statfs *);
int fstatfs(int, struct statfs *);
int getfh(const char *, fhandle_t *);
int getfhat(int, char *, struct fhandle *, int);
int getfsstat(struct statfs *, long, int);
int getmntinfo(struct statfs **, int);
int lgetfh(const char *, fhandle_t *);
int mount(const char *, const char *, int, void *);
int nmount(struct iovec *, unsigned int, int);
int statfs(const char *, struct statfs *);
int unmount(const char *, int);
int getvfsbyname(const char *, struct xvfsconf *);
__END_DECLS
#endif
#endif