aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Chen <tim.c.chen@linux.intel.com>2011-07-19 12:32:38 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2011-07-24 10:08:32 -0400
commit423e0ab086ad8b33626e45fa94ac7613146b7ffa (patch)
tree249c9337a02254fe5dbede7436f78dfcc1ec508f
parentbbd9d6f7fbb0305c9a592bf05a32e87eb364a4ff (diff)
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: Tim Chen <tim.c.chen@linux.intel.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--drivers/mtd/mtdchar.c2
-rw-r--r--fs/anon_inodes.c2
-rw-r--r--fs/hugetlbfs/inode.c1
-rw-r--r--fs/namespace.c21
-rw-r--r--fs/pipe.c2
-rw-r--r--include/linux/fs.h1
-rw-r--r--security/selinux/selinuxfs.c1
7 files changed, 26 insertions, 4 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3f92731a5b9e..f1af2228a1b1 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1192,7 +1192,7 @@ err_unregister_chdev:
1192static void __exit cleanup_mtdchar(void) 1192static void __exit cleanup_mtdchar(void)
1193{ 1193{
1194 unregister_mtd_user(&mtdchar_notifier); 1194 unregister_mtd_user(&mtdchar_notifier);
1195 mntput(mtd_inode_mnt); 1195 kern_unmount(mtd_inode_mnt);
1196 unregister_filesystem(&mtd_inodefs_type); 1196 unregister_filesystem(&mtd_inodefs_type);
1197 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); 1197 __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
1198} 1198}
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index c5567cb78432..4d433d34736f 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -233,7 +233,7 @@ static int __init anon_inode_init(void)
233 return 0; 233 return 0;
234 234
235err_mntput: 235err_mntput:
236 mntput(anon_inode_mnt); 236 kern_unmount(anon_inode_mnt);
237err_unregister_filesystem: 237err_unregister_filesystem:
238 unregister_filesystem(&anon_inode_fs_type); 238 unregister_filesystem(&anon_inode_fs_type);
239err_exit: 239err_exit:
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7aafeb8fa300..0b686cec9976 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void)
1030static void __exit exit_hugetlbfs_fs(void) 1030static void __exit exit_hugetlbfs_fs(void)
1031{ 1031{
1032 kmem_cache_destroy(hugetlbfs_inode_cachep); 1032 kmem_cache_destroy(hugetlbfs_inode_cachep);
1033 kern_unmount(hugetlbfs_vfsmount);
1033 unregister_filesystem(&hugetlbfs_fs_type); 1034 unregister_filesystem(&hugetlbfs_fs_type);
1034 bdi_destroy(&hugetlbfs_backing_dev_info); 1035 bdi_destroy(&hugetlbfs_backing_dev_info);
1035} 1036}
diff --git a/fs/namespace.c b/fs/namespace.c
index cda50fe9250a..22bfe8273c68 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns);
2721 2721
2722struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) 2722struct vfsmount *kern_mount_data(struct file_system_type *type, void *data)
2723{ 2723{
2724 return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); 2724 struct vfsmount *mnt;
2725 mnt = vfs_kern_mount(type, MS_KERNMOUNT, type->name, data);
2726 if (!IS_ERR(mnt)) {
2727 /*
2728 * it is a longterm mount, don't release mnt until
2729 * we unmount before file sys is unregistered
2730 */
2731 mnt_make_longterm(mnt);
2732 }
2733 return mnt;
2725} 2734}
2726EXPORT_SYMBOL_GPL(kern_mount_data); 2735EXPORT_SYMBOL_GPL(kern_mount_data);
2736
2737void kern_unmount(struct vfsmount *mnt)
2738{
2739 /* release long term mount so mount point can be released */
2740 if (!IS_ERR_OR_NULL(mnt)) {
2741 mnt_make_shortterm(mnt);
2742 mntput(mnt);
2743 }
2744}
2745EXPORT_SYMBOL(kern_unmount);
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7db50de..1b7f9af67ccf 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void)
1291 1291
1292static void __exit exit_pipe_fs(void) 1292static void __exit exit_pipe_fs(void)
1293{ 1293{
1294 kern_unmount(pipe_mnt);
1294 unregister_filesystem(&pipe_fs_type); 1295 unregister_filesystem(&pipe_fs_type);
1295 mntput(pipe_mnt);
1296} 1296}
1297 1297
1298fs_initcall(init_pipe_fs); 1298fs_initcall(init_pipe_fs);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b224dc468a23..7a757a48a5c6 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1885,6 +1885,7 @@ extern int register_filesystem(struct file_system_type *);
1885extern int unregister_filesystem(struct file_system_type *); 1885extern int unregister_filesystem(struct file_system_type *);
1886extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data); 1886extern struct vfsmount *kern_mount_data(struct file_system_type *, void *data);
1887#define kern_mount(type) kern_mount_data(type, NULL) 1887#define kern_mount(type) kern_mount_data(type, NULL)
1888extern void kern_unmount(struct vfsmount *mnt);
1888extern int may_umount_tree(struct vfsmount *); 1889extern int may_umount_tree(struct vfsmount *);
1889extern int may_umount(struct vfsmount *); 1890extern int may_umount(struct vfsmount *);
1890extern long do_mount(char *, char *, char *, unsigned long, void *); 1891extern long do_mount(char *, char *, char *, unsigned long, void *);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 35459340019e..de7900ef53da 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1984,6 +1984,7 @@ __initcall(init_sel_fs);
1984void exit_sel_fs(void) 1984void exit_sel_fs(void)
1985{ 1985{
1986 kobject_put(selinuxfs_kobj); 1986 kobject_put(selinuxfs_kobj);
1987 kern_unmount(selinuxfs_mount);
1987 unregister_filesystem(&sel_fs_type); 1988 unregister_filesystem(&sel_fs_type);
1988} 1989}
1989#endif 1990#endif