diff options
Diffstat (limited to 'freebsd/sys/fs/pseudofs/pseudofs.h')
-rw-r--r-- | freebsd/sys/fs/pseudofs/pseudofs.h | 312 |
1 files changed, 312 insertions, 0 deletions
diff --git a/freebsd/sys/fs/pseudofs/pseudofs.h b/freebsd/sys/fs/pseudofs/pseudofs.h new file mode 100644 index 00000000..602e1fbf --- /dev/null +++ b/freebsd/sys/fs/pseudofs/pseudofs.h @@ -0,0 +1,312 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 Dag-Erling Coïdan Smørgrav + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#ifndef _PSEUDOFS_H_INCLUDED +#define _PSEUDOFS_H_INCLUDED + +#include <sys/jail.h> + +/* + * Opaque structures + */ +struct mntarg; +struct mount; +struct nameidata; +struct proc; +struct sbuf; +struct statfs; +struct thread; +struct uio; +struct vfsconf; +struct vnode; + +/* + * Limits and constants + */ +#define PFS_NAMELEN 128 +#define PFS_FSNAMELEN 16 /* equal to MFSNAMELEN */ +#define PFS_DELEN (offsetof(struct dirent, d_name) + PFS_NAMELEN) + +typedef enum { + pfstype_none = 0, + pfstype_root, + pfstype_dir, + pfstype_this, + pfstype_parent, + pfstype_file, + pfstype_symlink, + pfstype_procdir +} pfs_type_t; + +/* + * Flags + */ +#define PFS_RD 0x0001 /* readable */ +#define PFS_WR 0x0002 /* writeable */ +#define PFS_RDWR (PFS_RD|PFS_WR) +#define PFS_RAWRD 0x0004 /* raw reader */ +#define PFS_RAWWR 0x0008 /* raw writer */ +#define PFS_RAW (PFS_RAWRD|PFS_RAWWR) +#define PFS_PROCDEP 0x0010 /* process-dependent */ +#define PFS_NOWAIT 0x0020 /* allow malloc to fail */ + +/* + * Data structures + */ +struct pfs_info; +struct pfs_node; + +/* + * Init / uninit callback + */ +#define PFS_INIT_ARGS \ + struct pfs_info *pi, struct vfsconf *vfc +#define PFS_INIT_ARGNAMES \ + pi, vfc +#define PFS_INIT_PROTO(name) \ + int name(PFS_INIT_ARGS); +typedef int (*pfs_init_t)(PFS_INIT_ARGS); + +/* + * Filler callback + * Called with proc held but unlocked + */ +#define PFS_FILL_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn, \ + struct sbuf *sb, struct uio *uio +#define PFS_FILL_ARGNAMES \ + td, p, pn, sb, uio +#define PFS_FILL_PROTO(name) \ + int name(PFS_FILL_ARGS); +typedef int (*pfs_fill_t)(PFS_FILL_ARGS); + +/* + * Attribute callback + * Called with proc locked + */ +struct vattr; +#define PFS_ATTR_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn, \ + struct vattr *vap +#define PFS_ATTR_ARGNAMES \ + td, p, pn, vap +#define PFS_ATTR_PROTO(name) \ + int name(PFS_ATTR_ARGS); +typedef int (*pfs_attr_t)(PFS_ATTR_ARGS); + +/* + * Visibility callback + * Called with proc locked + */ +#define PFS_VIS_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn +#define PFS_VIS_ARGNAMES \ + td, p, pn +#define PFS_VIS_PROTO(name) \ + int name(PFS_VIS_ARGS); +typedef int (*pfs_vis_t)(PFS_VIS_ARGS); + +/* + * Ioctl callback + * Called with proc locked + */ +#define PFS_IOCTL_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn, \ + unsigned long cmd, void *data +#define PFS_IOCTL_ARGNAMES \ + td, p, pn, cmd, data +#define PFS_IOCTL_PROTO(name) \ + int name(PFS_IOCTL_ARGS); +typedef int (*pfs_ioctl_t)(PFS_IOCTL_ARGS); + +/* + * Getextattr callback + * Called with proc locked + */ +#define PFS_GETEXTATTR_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn, \ + int attrnamespace, const char *name, struct uio *uio, \ + size_t *size, struct ucred *cred +#define PFS_GETEXTATTR_ARGNAMES \ + td, p, pn, attrnamespace, name, uio, size, cred +#define PFS_GETEXTATTR_PROTO(name) \ + int name(PFS_GETEXTATTR_ARGS); +struct ucred; +typedef int (*pfs_getextattr_t)(PFS_GETEXTATTR_ARGS); + +/* + * Last-close callback + * Called with proc locked + */ +#define PFS_CLOSE_ARGS \ + struct thread *td, struct proc *p, struct pfs_node *pn +#define PFS_CLOSE_ARGNAMES \ + td, p, pn +#define PFS_CLOSE_PROTO(name) \ + int name(PFS_CLOSE_ARGS); +typedef int (*pfs_close_t)(PFS_CLOSE_ARGS); + +/* + * Destroy callback + */ +#define PFS_DESTROY_ARGS \ + struct pfs_node *pn +#define PFS_DESTROY_ARGNAMES \ + pn +#define PFS_DESTROY_PROTO(name) \ + int name(PFS_DESTROY_ARGS); +typedef int (*pfs_destroy_t)(PFS_DESTROY_ARGS); + +/* + * pfs_info: describes a pseudofs instance + * + * The pi_mutex is only used to avoid using the global subr_unit lock + * for unrhdr. The rest of struct pfs_info is only modified during + * vfs_init() and vfs_uninit() of the consumer filesystem. + */ +struct pfs_info { + char pi_name[PFS_FSNAMELEN]; + pfs_init_t pi_init; + pfs_init_t pi_uninit; + + /* members below this line are initialized at run time */ + struct pfs_node *pi_root; + struct mtx pi_mutex; + struct unrhdr *pi_unrhdr; +}; + +/* + * pfs_node: describes a node (file or directory) within a pseudofs + * + * - Fields marked (o) are protected by the node's own mutex. + * - Fields marked (p) are protected by the node's parent's mutex. + * - Remaining fields are not protected by any lock and are assumed to be + * immutable once the node has been created. + * + * To prevent deadlocks, if a node's mutex is to be held at the same time + * as its parent's (e.g. when adding or removing nodes to a directory), + * the parent's mutex must always be acquired first. Unfortunately, this + * is not enforcable by WITNESS. + */ +struct pfs_node { + char pn_name[PFS_NAMELEN]; + pfs_type_t pn_type; + int pn_flags; + struct mtx pn_mutex; + void *pn_data; /* (o) */ + + pfs_fill_t pn_fill; + pfs_ioctl_t pn_ioctl; + pfs_close_t pn_close; + pfs_attr_t pn_attr; + pfs_vis_t pn_vis; + pfs_getextattr_t pn_getextattr; + pfs_destroy_t pn_destroy; + + struct pfs_info *pn_info; + u_int32_t pn_fileno; /* (o) */ + + struct pfs_node *pn_parent; /* (o) */ + struct pfs_node *pn_nodes; /* (o) */ + struct pfs_node *pn_next; /* (p) */ +}; + +/* + * VFS interface + */ +int pfs_mount (struct pfs_info *pi, struct mount *mp); +int pfs_cmount (struct mntarg *ma, void *data, uint64_t flags); +int pfs_unmount (struct mount *mp, int mntflags); +int pfs_root (struct mount *mp, int flags, + struct vnode **vpp); +int pfs_statfs (struct mount *mp, struct statfs *sbp); +int pfs_init (struct pfs_info *pi, struct vfsconf *vfc); +int pfs_uninit (struct pfs_info *pi, struct vfsconf *vfc); + +/* + * Directory structure construction and manipulation + */ +struct pfs_node *pfs_create_dir (struct pfs_node *parent, const char *name, + pfs_attr_t attr, pfs_vis_t vis, + pfs_destroy_t destroy, int flags); +struct pfs_node *pfs_create_file(struct pfs_node *parent, const char *name, + pfs_fill_t fill, pfs_attr_t attr, + pfs_vis_t vis, pfs_destroy_t destroy, + int flags); +struct pfs_node *pfs_create_link(struct pfs_node *parent, const char *name, + pfs_fill_t fill, pfs_attr_t attr, + pfs_vis_t vis, pfs_destroy_t destroy, + int flags); +struct pfs_node *pfs_find_node (struct pfs_node *parent, const char *name); +void pfs_purge (struct pfs_node *pn); +int pfs_destroy (struct pfs_node *pn); + +/* + * Now for some initialization magic... + */ +#define PSEUDOFS(name, version, flags) \ + \ +static struct pfs_info name##_info = { \ + #name, \ + name##_init, \ + name##_uninit, \ +}; \ + \ +static int \ +_##name##_mount(struct mount *mp) { \ + return (pfs_mount(&name##_info, mp)); \ +} \ + \ +static int \ +_##name##_init(struct vfsconf *vfc) { \ + return (pfs_init(&name##_info, vfc)); \ +} \ + \ +static int \ +_##name##_uninit(struct vfsconf *vfc) { \ + return (pfs_uninit(&name##_info, vfc)); \ +} \ + \ +static struct vfsops name##_vfsops = { \ + .vfs_cmount = pfs_cmount, \ + .vfs_init = _##name##_init, \ + .vfs_mount = _##name##_mount, \ + .vfs_root = pfs_root, \ + .vfs_statfs = pfs_statfs, \ + .vfs_uninit = _##name##_uninit, \ + .vfs_unmount = pfs_unmount, \ +}; \ +VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | flags); \ +MODULE_VERSION(name, version); \ +MODULE_DEPEND(name, pseudofs, 1, 1, 1); + +#endif |