Page MenuHomeFreeBSD

D52156.id.diff
No OneTemporary

D52156.id.diff

diff --git a/sys/fs/pseudofs/pseudofs.h b/sys/fs/pseudofs/pseudofs.h
--- a/sys/fs/pseudofs/pseudofs.h
+++ b/sys/fs/pseudofs/pseudofs.h
@@ -31,6 +31,7 @@
#ifndef _PSEUDOFS_H_INCLUDED
#define _PSEUDOFS_H_INCLUDED
+#include <sys/_sx.h>
#include <sys/jail.h>
/*
@@ -188,9 +189,11 @@
/*
* 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];
@@ -198,9 +201,11 @@
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;
};
/*
@@ -249,8 +254,8 @@
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
@@ -276,9 +281,9 @@
#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 \
@@ -287,22 +292,22 @@
} \
\
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); \
diff --git a/sys/fs/pseudofs/pseudofs.c b/sys/fs/pseudofs/pseudofs.c
--- a/sys/fs/pseudofs/pseudofs.c
+++ b/sys/fs/pseudofs/pseudofs.c
@@ -40,13 +40,18 @@
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/refcount.h>
#include <sys/sbuf.h>
+#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
#include <fs/pseudofs/pseudofs.h>
#include <fs/pseudofs/pseudofs_internal.h>
+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,
@@ -382,10 +387,20 @@
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;
@@ -424,10 +439,23 @@
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);
}
@@ -454,10 +482,35 @@
}
/*
- * 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;
@@ -487,18 +540,20 @@
/*
* 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);
}
/*
diff --git a/sys/modules/pseudofs/Makefile b/sys/modules/pseudofs/Makefile
--- a/sys/modules/pseudofs/Makefile
+++ b/sys/modules/pseudofs/Makefile
@@ -13,8 +13,8 @@
pfs_unmount \
pfs_root \
pfs_statfs \
- pfs_init \
- pfs_uninit \
+ pfs_vfsinit \
+ pfs_vfsuninit \
pfs_create_dir \
pfs_create_file \
pfs_create_link \

File Metadata

Mime Type
text/plain
Expires
Mon, Oct 13, 12:31 AM (6 h, 7 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23612675
Default Alt Text
D52156.id.diff (6 KB)

Event Timeline