Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131890945
D52156.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D52156.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D52156: pseudofs: defer initialization until first mount
Attached
Detach File
Event Timeline
Log In to Comment