diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c index efeeb57e6448..20cb87c6c6d5 100644 --- a/sys/fs/pseudofs/pseudofs.c +++ b/sys/fs/pseudofs/pseudofs.c @@ -1,534 +1,589 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2001 Dag-Erling 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. */ #include #include "opt_pseudofs.h" #include #include #include #include #include #include #include #include #include +#include #include +#include #include #include #include #include +static int pfs_setup(struct pfs_info *pi, struct vfsconf *vfc); +static int pfs_teardown(struct pfs_info *pi, struct vfsconf *vfc); + static MALLOC_DEFINE(M_PFSNODES, "pfs_nodes", "pseudofs nodes"); SYSCTL_NODE(_vfs, OID_AUTO, pfs, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "pseudofs"); #ifdef PSEUDOFS_TRACE int pfs_trace; SYSCTL_INT(_vfs_pfs, OID_AUTO, trace, CTLFLAG_RW, &pfs_trace, 0, "enable tracing of pseudofs vnode operations"); #endif #if PFS_FSNAMELEN != MFSNAMELEN #error "PFS_FSNAMELEN is not equal to MFSNAMELEN" #endif /* * Allocate and initialize a node */ static struct pfs_node * pfs_alloc_node_flags(struct pfs_info *pi, const char *name, pfs_type_t type, int flags) { struct pfs_node *pn; int malloc_flags; size_t len; len = strlen(name); KASSERT(len < PFS_NAMELEN, ("%s(): node name is too long", __func__)); if (flags & PFS_NOWAIT) malloc_flags = M_NOWAIT | M_ZERO; else malloc_flags = M_WAITOK | M_ZERO; pn = malloc(sizeof(*pn) + len + 1, M_PFSNODES, malloc_flags); if (pn == NULL) return (NULL); mtx_init(&pn->pn_mutex, "pfs_node", NULL, MTX_DEF | MTX_DUPOK); memcpy(pn->pn_name, name, len); pn->pn_type = type; pn->pn_info = pi; return (pn); } static struct pfs_node * pfs_alloc_node(struct pfs_info *pi, const char *name, pfs_type_t type) { return (pfs_alloc_node_flags(pi, name, type, 0)); } /* * Add a node to a directory */ static int pfs_add_node(struct pfs_node *parent, struct pfs_node *pn) { struct pfs_node *iter; KASSERT(parent != NULL, ("%s(): parent is NULL", __func__)); KASSERT(pn->pn_parent == NULL, ("%s(): node already has a parent", __func__)); KASSERT(parent->pn_info != NULL, ("%s(): parent has no pn_info", __func__)); KASSERT(parent->pn_type == pfstype_dir || parent->pn_type == pfstype_procdir || parent->pn_type == pfstype_root, ("%s(): parent is not a directory", __func__)); #ifdef INVARIANTS /* XXX no locking! */ if (pn->pn_type == pfstype_procdir) for (iter = parent; iter != NULL; iter = iter->pn_parent) KASSERT(iter->pn_type != pfstype_procdir, ("%s(): nested process directories", __func__)); for (iter = parent->pn_nodes; iter != NULL; iter = iter->pn_next) { if (pn->pn_type == pfstype_procdir) KASSERT(iter->pn_type != pfstype_procdir, ("%s(): sibling process directories", __func__)); } #endif pn->pn_parent = parent; pfs_fileno_alloc(pn); pfs_lock(parent); for (iter = parent->pn_nodes; iter != NULL; iter = iter->pn_next) { if (strcmp(pn->pn_name, iter->pn_name) != 0) continue; printf("pfs_add_node: homonymous siblings: '%s/%s' type %d\n", parent->pn_name, pn->pn_name, pn->pn_type); /* Do not detach, because we are not yet attached. */ pn->pn_parent = NULL; pfs_unlock(parent); return (EEXIST); } if ((parent->pn_flags & PFS_PROCDEP) != 0) pn->pn_flags |= PFS_PROCDEP; if (parent->pn_nodes == NULL) { KASSERT(parent->pn_last_node == NULL, ("%s(): pn_last_node not NULL", __func__)); parent->pn_nodes = pn; parent->pn_last_node = pn; } else { KASSERT(parent->pn_last_node != NULL, ("%s(): pn_last_node is NULL", __func__)); KASSERT(parent->pn_last_node->pn_next == NULL, ("%s(): pn_last_node->pn_next not NULL", __func__)); parent->pn_last_node->pn_next = pn; parent->pn_last_node = pn; } pfs_unlock(parent); return (0); } /* * Detach a node from its parent */ static void pfs_detach_node(struct pfs_node *pn) { struct pfs_node *node, *parent = pn->pn_parent; struct pfs_node **iter; KASSERT(parent != NULL, ("%s(): node has no parent", __func__)); KASSERT(parent->pn_info == pn->pn_info, ("%s(): parent has different pn_info", __func__)); pfs_lock(parent); if (pn == parent->pn_last_node) { if (pn == pn->pn_nodes) { parent->pn_last_node = NULL; } else { for (node = parent->pn_nodes; node->pn_next != pn; node = node->pn_next) continue; parent->pn_last_node = node; } } iter = &parent->pn_nodes; while (*iter != NULL) { if (*iter == pn) { *iter = pn->pn_next; break; } iter = &(*iter)->pn_next; } pn->pn_parent = NULL; pfs_unlock(parent); } /* * Add . and .. to a directory */ static int pfs_fixup_dir_flags(struct pfs_node *parent, int flags) { struct pfs_node *dot, *dotdot; int rc; dot = pfs_alloc_node_flags(parent->pn_info, ".", pfstype_this, flags); if (dot == NULL) return (ENOMEM); dotdot = pfs_alloc_node_flags(parent->pn_info, "..", pfstype_parent, flags); if (dotdot == NULL) { pfs_destroy(dot); return (ENOMEM); } rc = pfs_add_node(parent, dot); if (rc == 0) rc = pfs_add_node(parent, dotdot); if (rc != 0) { pfs_destroy(dot); pfs_destroy(dotdot); } return (rc); } static void pfs_fixup_dir(struct pfs_node *parent) { pfs_fixup_dir_flags(parent, 0); } /* * Create a directory */ 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 *pn; int rc; pn = pfs_alloc_node_flags(parent->pn_info, name, (flags & PFS_PROCDEP) ? pfstype_procdir : pfstype_dir, flags); if (pn == NULL) return (NULL); pn->pn_attr = attr; pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; rc = pfs_add_node(parent, pn); if (rc == 0) rc = pfs_fixup_dir_flags(pn, flags); if (rc != 0) { pfs_destroy(pn); pn = NULL; } return (pn); } /* * Create a file */ 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 *pn; pn = pfs_alloc_node_flags(parent->pn_info, name, pfstype_file, flags); if (pn == NULL) return (NULL); pn->pn_fill = fill; pn->pn_attr = attr; pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; if (pfs_add_node(parent, pn) != 0) { pfs_destroy(pn); pn = NULL; } return (pn); } /* * Create a symlink */ 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 *pn; pn = pfs_alloc_node_flags(parent->pn_info, name, pfstype_symlink, flags); if (pn == NULL) return (NULL); pn->pn_fill = fill; pn->pn_attr = attr; pn->pn_vis = vis; pn->pn_destroy = destroy; pn->pn_flags = flags; if (pfs_add_node(parent, pn) != 0) { pfs_destroy(pn); pn = NULL; } return (pn); } /* * Locate a node by name */ struct pfs_node * pfs_find_node(struct pfs_node *parent, const char *name) { struct pfs_node *pn; pfs_lock(parent); for (pn = parent->pn_nodes; pn != NULL; pn = pn->pn_next) if (strcmp(pn->pn_name, name) == 0) break; pfs_unlock(parent); return (pn); } /* * Destroy a node and all its descendants. If the node to be destroyed * has a parent, the parent's mutex must be held. */ int pfs_destroy(struct pfs_node *pn) { struct pfs_node *iter; KASSERT(pn != NULL, ("%s(): node is NULL", __func__)); KASSERT(pn->pn_info != NULL, ("%s(): node has no pn_info", __func__)); if (pn->pn_parent) pfs_detach_node(pn); /* destroy children */ if (pn->pn_type == pfstype_dir || pn->pn_type == pfstype_procdir || pn->pn_type == pfstype_root) { pfs_lock(pn); while (pn->pn_nodes != NULL) { iter = pn->pn_nodes; pn->pn_nodes = iter->pn_next; iter->pn_parent = NULL; pfs_unlock(pn); pfs_destroy(iter); pfs_lock(pn); } pfs_unlock(pn); } /* revoke vnodes and fileno */ pfs_purge(pn); /* callback to free any private resources */ if (pn->pn_destroy != NULL) pn_destroy(pn); /* destroy the node */ pfs_fileno_free(pn); mtx_destroy(&pn->pn_mutex); free(pn, M_PFSNODES); return (0); } /* * Mount a pseudofs instance */ int pfs_mount(struct pfs_info *pi, struct mount *mp) { struct statfs *sbp; + int error = 0; if (mp->mnt_flag & MNT_UPDATE) return (EOPNOTSUPP); + sx_xlock(&pi->pi_mountlock); + if (pi->pi_root == NULL) + error = pfs_setup(pi, mp->mnt_vfc); + if (error == 0) + refcount_acquire(&pi->pi_mounts); + sx_xunlock(&pi->pi_mountlock); + if (error != 0) + return (error); + MNT_ILOCK(mp); mp->mnt_flag |= MNT_LOCAL; mp->mnt_kern_flag |= MNTK_NOMSYNC; MNT_IUNLOCK(mp); mp->mnt_data = pi; vfs_getnewfsid(mp); sbp = &mp->mnt_stat; vfs_mountedfrom(mp, pi->pi_name); sbp->f_bsize = PAGE_SIZE; sbp->f_iosize = PAGE_SIZE; sbp->f_blocks = 2; sbp->f_bfree = 2; sbp->f_bavail = 2; sbp->f_files = 0; sbp->f_ffree = 0; return (0); } /* * Compatibility shim for old mount(2) system call */ int pfs_cmount(struct mntarg *ma, void *data, uint64_t flags) { int error; error = kernel_mount(ma, flags); return (error); } /* * Unmount a pseudofs instance */ int pfs_unmount(struct mount *mp, int mntflags) { + struct pfs_info *pi; int error; error = vflush(mp, 0, (mntflags & MNT_FORCE) ? FORCECLOSE : 0, curthread); + if (error != 0) + return (error); + + pi = (struct pfs_info *)mp->mnt_data; + sx_xlock(&pi->pi_mountlock); + if (!refcount_release_if_not_last(&pi->pi_mounts)) { + error = pfs_teardown(pi, mp->mnt_vfc); + if (error == 0) + refcount_release(&pi->pi_mounts); + } + sx_xunlock(&pi->pi_mountlock); + return (error); } /* * Return a root vnode */ int pfs_root(struct mount *mp, int flags, struct vnode **vpp) { struct pfs_info *pi; pi = (struct pfs_info *)mp->mnt_data; return (pfs_vncache_alloc(mp, vpp, pi->pi_root, NO_PID)); } /* * Return filesystem stats */ int pfs_statfs(struct mount *mp, struct statfs *sbp) { /* no-op: always called with mp->mnt_stat */ return (0); } /* - * Initialize a pseudofs instance + * Initialize pseudofs synchronization bits. These will generally be needed + * in order to avoid problems with parallel mounting of pseudofs consumers. */ int -pfs_init(struct pfs_info *pi, struct vfsconf *vfc) +pfs_vfsinit(struct pfs_info *pi, struct vfsconf *vfc) +{ + + sx_init(&pi->pi_mountlock, "pfs mountlock"); + refcount_init(&pi->pi_mounts, 0); + return (0); +} + +int +pfs_vfsuninit(struct pfs_info *pi, struct vfsconf *vfc) +{ + + MPASS(pi->pi_root == NULL); + sx_destroy(&pi->pi_mountlock); + + if (bootverbose) + printf("%s unregistered\n", pi->pi_name); + return (0); +} + +/* + * Initialize a pseudofs instance + */ +static int +pfs_setup(struct pfs_info *pi, struct vfsconf *vfc) { struct pfs_node *root; int error; pfs_fileno_init(pi); /* set up the root directory */ root = pfs_alloc_node(pi, "/", pfstype_root); pi->pi_root = root; pfs_fileno_alloc(root); pfs_fixup_dir(root); /* construct file hierarchy */ error = (pi->pi_init)(pi, vfc); if (error) { pfs_destroy(root); pi->pi_root = NULL; pfs_fileno_uninit(pi); return (error); } if (bootverbose) printf("%s registered\n", pi->pi_name); return (0); } /* * Destroy a pseudofs instance */ -int -pfs_uninit(struct pfs_info *pi, struct vfsconf *vfc) +static int +pfs_teardown(struct pfs_info *pi, struct vfsconf *vfc) { int error; + MPASS(pi->pi_root != NULL); + error = (pi->pi_uninit)(pi, vfc); + if (error != 0) + return (error); + pfs_destroy(pi->pi_root); pi->pi_root = NULL; pfs_fileno_uninit(pi); - if (bootverbose) - printf("%s unregistered\n", pi->pi_name); - error = (pi->pi_uninit)(pi, vfc); - return (error); + return (0); } /* * Handle load / unload events */ static int pfs_modevent(module_t mod, int evt, void *arg) { switch (evt) { case MOD_LOAD: pfs_vncache_load(); break; case MOD_UNLOAD: case MOD_SHUTDOWN: pfs_vncache_unload(); break; default: return EOPNOTSUPP; break; } return 0; } /* * Module declaration */ static moduledata_t pseudofs_data = { "pseudofs", pfs_modevent, NULL }; DECLARE_MODULE(pseudofs, pseudofs_data, SI_SUB_EXEC, SI_ORDER_FIRST); MODULE_VERSION(pseudofs, 1); diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h index c60dd7b339d1..461a1d2402e4 100644 --- a/sys/fs/pseudofs/pseudofs.h +++ b/sys/fs/pseudofs/pseudofs.h @@ -1,312 +1,317 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 2001 Dag-Erling 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. */ #ifndef _PSEUDOFS_H_INCLUDED #define _PSEUDOFS_H_INCLUDED +#include #include /* * 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 */ #define PFS_AUTODRAIN 0x0040 /* sbuf_print can sleep to drain */ /* * 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. + * The pi_mutex is used to avoid using the global subr_unit lock for unrhdr, and + * the pi_mountlock is used to coordinate initialization of the consumer + * filesystem on first mount. The rest of struct pfs_info is only modified + * during pi_init() and pi_uninit() of the consumer filesystem, which are fully + * serialized. */ 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 sx pi_mountlock; struct pfs_node *pi_root; struct mtx pi_mutex; struct unrhdr *pi_unrhdr; + u_int pi_mounts; }; /* * 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 { 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_last_node; /* (o) */ struct pfs_node *pn_next; /* (p) */ char pn_name[]; /* Keep it last */ }; /* * 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); +int pfs_vfsinit (struct pfs_info *pi, struct vfsconf *vfc); +int pfs_vfsuninit (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, \ + .pi_name = #name, \ + .pi_init = name##_init, \ + .pi_uninit = 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)); \ +_##name##_vfsinit(struct vfsconf *vfc) { \ + return (pfs_vfsinit(&name##_info, vfc)); \ } \ \ static int \ -_##name##_uninit(struct vfsconf *vfc) { \ - return (pfs_uninit(&name##_info, vfc)); \ +_##name##_vfsuninit(struct vfsconf *vfc) { \ + return (pfs_vfsuninit(&name##_info, vfc)); \ } \ \ static struct vfsops name##_vfsops = { \ .vfs_cmount = pfs_cmount, \ - .vfs_init = _##name##_init, \ + .vfs_init = _##name##_vfsinit, \ .vfs_mount = _##name##_mount, \ .vfs_root = pfs_root, \ .vfs_statfs = pfs_statfs, \ - .vfs_uninit = _##name##_uninit, \ + .vfs_uninit = _##name##_vfsuninit, \ .vfs_unmount = pfs_unmount, \ }; \ VFS_SET(name##_vfsops, name, VFCF_SYNTHETIC | flags); \ MODULE_VERSION(name, version); \ MODULE_DEPEND(name, pseudofs, 1, 1, 1); #endif diff --git a/sys/modules/pseudofs/Makefile b/sys/modules/pseudofs/Makefile index cb92b8912c86..3928c950ab70 100644 --- a/sys/modules/pseudofs/Makefile +++ b/sys/modules/pseudofs/Makefile @@ -1,29 +1,29 @@ .PATH: ${SRCTOP}/sys/fs/pseudofs KMOD= pseudofs SRCS= opt_pseudofs.h \ vnode_if.h \ pseudofs.c \ pseudofs_fileno.c \ pseudofs_vncache.c \ pseudofs_vnops.c EXPORT_SYMS= pfs_cmount \ pfs_mount \ pfs_unmount \ pfs_root \ pfs_statfs \ - pfs_init \ - pfs_uninit \ + pfs_vfsinit \ + pfs_vfsuninit \ pfs_create_dir \ pfs_create_file \ pfs_create_link \ pfs_destroy .if !defined(KERNBUILDDIR) .if defined(PSEUDOFS_TRACE) CFLAGS+=-DPSEUDOFS_TRACE .endif .endif .include