Commit 423e0ab0 authored by Tim Chen's avatar Tim Chen Committed by Al Viro

VFS : mount lock scalability for internal mounts

For a number of file systems that don't have a mount point (e.g. sockfs
and pipefs), they are not marked as long term. Therefore in
mntput_no_expire, all locks in vfs_mount lock are taken instead of just
local cpu's lock to aggregate reference counts when we release
reference to file objects.  In fact, only local lock need to have been
taken to update ref counts as these file systems are in no danger of
going away until we are ready to unregister them.

The attached patch marks file systems using kern_mount without
mount point as long term.  The contentions of vfs_mount lock
is now eliminated.  Before un-registering such file system,
kern_unmount should be called to remove the long term flag and
make the mount point ready to be freed.
Signed-off-by: default avatarTim Chen <tim.c.chen@linux.intel.com>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent bbd9d6f7
...@@ -1192,7 +1192,7 @@ static int __init init_mtdchar(void) ...@@ -1192,7 +1192,7 @@ static int __init init_mtdchar(void)
static void __exit cleanup_mtdchar(void) static void __exit cleanup_mtdchar(void)
{ {
unregister_mtd_user(&mtdchar_notifier); unregister_mtd_user(&mtdchar_notifier);
mntput(mtd_inode_mnt); kern_unmount(mtd_inode_mnt);
unregister_filesystem(&mtd_inodefs_type); unregister_filesystem(&mtd_inodefs_type);
__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
} }
......
...@@ -233,7 +233,7 @@ static int __init anon_inode_init(void) ...@@ -233,7 +233,7 @@ static int __init anon_inode_init(void)
return 0; return 0;
err_mntput: err_mntput:
mntput(anon_inode_mnt); kern_unmount(anon_inode_mnt);
err_unregister_filesystem: err_unregister_filesystem:
unregister_filesystem(&anon_inode_fs_type); unregister_filesystem(&anon_inode_fs_type);
err_exit: err_exit:
......
...@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void) ...@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void)
static void __exit exit_hugetlbfs_fs(void) static void __exit exit_hugetlbfs_fs(void)
{ {
kmem_cache_destroy(hugetlbfs_inode_cachep); kmem_cache_destroy(hugetlbfs_inode_cachep);
kern_unmount(hugetlbfs_vfsmount);
unregister_filesystem(&hugetlbfs_fs_type); unregister_filesystem(&hugetlbfs_fs_type);
bdi_destroy(&hugetlbfs_backing_dev_info); bdi_destroy(&hugetlbfs_backing_dev_info);
} }
......
...@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns); ...@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns);
struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
{ {
return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); struct vfsmount *mnt;
mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
if (!IS_ERR(mnt)) {
/*
* it is a longterm mount, don't release mnt until
* we unmount before file sys is unregistered
*/
mnt_make_longterm(mnt);
}
return mnt;
} }
EXPORT_SYMBOL_GPL(kern_mount_data); EXPORT_SYMBOL_GPL(kern_mount_data);
void kern_unmount(struct vfsmount *mnt)
{
/* release long term mount so mount point can be released */
if (!IS_ERR_OR_NULL(mnt)) {
mnt_make_shortterm(mnt);
mntput(mnt);
}
}
EXPORT_SYMBOL(kern_unmount);
...@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void) ...@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void)
static void __exit exit_pipe_fs(void) static void __exit exit_pipe_fs(void)
{ {
kern_unmount(pipe_mnt);
unregister_filesystem(&pipe_fs_type); unregister_filesystem(&pipe_fs_type);
mntput(pipe_mnt);
} }
fs_initcall(init_pipe_fs); fs_initcall(init_pipe_fs);
......
...@@ -1885,6 +1885,7 @@ extern int register_filesystem(struct file_system_type *); ...@@ -1885,6 +1885,7 @@ extern int register_filesystem(struct file_system_type *);
extern int unregister_filesystem(struct file_system_type *); extern int unregister_filesystem(struct file_system_type *);
extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data); extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
#define kern_mount(type) kern_mount_data(type, NULL) #define kern_mount(type) kern_mount_data(type, NULL)
extern void kern_unmount(struct vfsmount *mnt);
extern int may_umount_tree(struct vfsmount *); extern int may_umount_tree(struct vfsmount *);
extern int may_umount(struct vfsmount *); extern int may_umount(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *); extern long do_mount(char *, char *, char *, unsigned long, void *);
......
...@@ -1984,6 +1984,7 @@ __initcall(init_sel_fs); ...@@ -1984,6 +1984,7 @@ __initcall(init_sel_fs);
void exit_sel_fs(void) void exit_sel_fs(void)
{ {
kobject_put(selinuxfs_kobj); kobject_put(selinuxfs_kobj);
kern_unmount(selinuxfs_mount);
unregister_filesystem(&sel_fs_type); unregister_filesystem(&sel_fs_type);
} }
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment