diff options
author | kib <kib@FreeBSD.org> | 2014-08-17 09:07:21 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2014-08-17 09:07:21 +0000 |
commit | 94d67906ea5fe3906f9ca6700b842d9e4d0ecb60 (patch) | |
tree | 4a98692a9f91a0bf1eb66264fa2f665692127fe0 /sys/kern/vfs_init.c | |
parent | 75d88c0d5af7637b80b91ac5ad44544a638d5ea8 (diff) | |
download | FreeBSD-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.c | 93 |
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); } /* |