summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_init.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2014-08-17 09:07:21 +0000
committerkib <kib@FreeBSD.org>2014-08-17 09:07:21 +0000
commit94d67906ea5fe3906f9ca6700b842d9e4d0ecb60 (patch)
tree4a98692a9f91a0bf1eb66264fa2f665692127fe0 /sys/kern/vfs_init.c
parent75d88c0d5af7637b80b91ac5ad44544a638d5ea8 (diff)
downloadFreeBSD-src-94d67906ea5fe3906f9ca6700b842d9e4d0ecb60.zip
FreeBSD-src-94d67906ea5fe3906f9ca6700b842d9e4d0ecb60.tar.gz
MFC r269457:
Remove Giant acquisition from the mount and unmount pathes.
Diffstat (limited to 'sys/kern/vfs_init.c')
-rw-r--r--sys/kern/vfs_init.c93
1 files changed, 61 insertions, 32 deletions
diff --git a/sys/kern/vfs_init.c b/sys/kern/vfs_init.c
index eab48fb..dd21743 100644
--- a/sys/kern/vfs_init.c
+++ b/sys/kern/vfs_init.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <sys/linker.h>
#include <sys/mount.h>
#include <sys/proc.h>
+#include <sys/sx.h>
#include <sys/syscallsubr.h>
#include <sys/sysctl.h>
#include <sys/vnode.h>
@@ -64,6 +65,8 @@ int maxvfsconf = VFS_GENERIC + 1;
* New entries are added/deleted by vfs_register()/vfs_unregister()
*/
struct vfsconfhead vfsconf = TAILQ_HEAD_INITIALIZER(vfsconf);
+struct sx vfsconf_sx;
+SX_SYSINIT(vfsconf, &vfsconf_sx, "vfsconf");
/*
* Loader.conf variable vfs.typenumhash enables setting vfc_typenum using a hash
@@ -105,20 +108,33 @@ struct vattr va_null;
* Routines having to do with the management of the vnode table.
*/
-struct vfsconf *
-vfs_byname(const char *name)
+static struct vfsconf *
+vfs_byname_locked(const char *name)
{
struct vfsconf *vfsp;
+ sx_assert(&vfsconf_sx, SA_LOCKED);
if (!strcmp(name, "ffs"))
name = "ufs";
- TAILQ_FOREACH(vfsp, &vfsconf, vfc_list)
+ TAILQ_FOREACH(vfsp, &vfsconf, vfc_list) {
if (!strcmp(name, vfsp->vfc_name))
return (vfsp);
+ }
return (NULL);
}
struct vfsconf *
+vfs_byname(const char *name)
+{
+ struct vfsconf *vfsp;
+
+ vfsconf_slock();
+ vfsp = vfs_byname_locked(name);
+ vfsconf_sunlock();
+ return (vfsp);
+}
+
+struct vfsconf *
vfs_byname_kld(const char *fstype, struct thread *td, int *error)
{
struct vfsconf *vfsp;
@@ -169,8 +185,11 @@ vfs_register(struct vfsconf *vfc)
vfc->vfc_name, vfc->vfc_version);
return (EINVAL);
}
- if (vfs_byname(vfc->vfc_name) != NULL)
+ vfsconf_lock();
+ if (vfs_byname_locked(vfc->vfc_name) != NULL) {
+ vfsconf_unlock();
return (EEXIST);
+ }
if (vfs_typenumhash != 0) {
/*
@@ -203,26 +222,6 @@ vfs_register(struct vfsconf *vfc)
TAILQ_INSERT_TAIL(&vfsconf, vfc, vfc_list);
/*
- * If this filesystem has a sysctl node under vfs
- * (i.e. vfs.xxfs), then change the oid number of that node to
- * match the filesystem's type number. This allows user code
- * which uses the type number to read sysctl variables defined
- * by the filesystem to continue working. Since the oids are
- * in a sorted list, we need to make sure the order is
- * preserved by re-registering the oid after modifying its
- * number.
- */
- sysctl_lock();
- SLIST_FOREACH(oidp, &sysctl__vfs_children, oid_link)
- if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
- sysctl_unregister_oid(oidp);
- oidp->oid_number = vfc->vfc_typenum;
- sysctl_register_oid(oidp);
- break;
- }
- sysctl_unlock();
-
- /*
* Initialise unused ``struct vfsops'' fields, to use
* the vfs_std*() functions. Note, we need the mount
* and unmount operations, at the least. The check
@@ -281,8 +280,30 @@ vfs_register(struct vfsconf *vfc)
* Call init function for this VFS...
*/
(*(vfc->vfc_vfsops->vfs_init))(vfc);
+ vfsconf_unlock();
- return 0;
+ /*
+ * If this filesystem has a sysctl node under vfs
+ * (i.e. vfs.xxfs), then change the oid number of that node to
+ * match the filesystem's type number. This allows user code
+ * which uses the type number to read sysctl variables defined
+ * by the filesystem to continue working. Since the oids are
+ * in a sorted list, we need to make sure the order is
+ * preserved by re-registering the oid after modifying its
+ * number.
+ */
+ sysctl_lock();
+ SLIST_FOREACH(oidp, &sysctl__vfs_children, oid_link) {
+ if (strcmp(oidp->oid_name, vfc->vfc_name) == 0) {
+ sysctl_unregister_oid(oidp);
+ oidp->oid_number = vfc->vfc_typenum;
+ sysctl_register_oid(oidp);
+ break;
+ }
+ }
+ sysctl_unlock();
+
+ return (0);
}
@@ -295,15 +316,22 @@ vfs_unregister(struct vfsconf *vfc)
i = vfc->vfc_typenum;
- vfsp = vfs_byname(vfc->vfc_name);
- if (vfsp == NULL)
- return EINVAL;
- if (vfsp->vfc_refcount)
- return EBUSY;
+ vfsconf_lock();
+ vfsp = vfs_byname_locked(vfc->vfc_name);
+ if (vfsp == NULL) {
+ vfsconf_unlock();
+ return (EINVAL);
+ }
+ if (vfsp->vfc_refcount != 0) {
+ vfsconf_unlock();
+ return (EBUSY);
+ }
if (vfc->vfc_vfsops->vfs_uninit != NULL) {
error = (*vfc->vfc_vfsops->vfs_uninit)(vfsp);
- if (error)
+ if (error != 0) {
+ vfsconf_unlock();
return (error);
+ }
}
TAILQ_REMOVE(&vfsconf, vfsp, vfc_list);
maxtypenum = VFS_GENERIC;
@@ -311,7 +339,8 @@ vfs_unregister(struct vfsconf *vfc)
if (maxtypenum < vfsp->vfc_typenum)
maxtypenum = vfsp->vfc_typenum;
maxvfsconf = maxtypenum + 1;
- return 0;
+ vfsconf_unlock();
+ return (0);
}
/*
OpenPOWER on IntegriCloud