aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 3f92731a5b9..f1af2228a1b 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -1192,7 +1192,7 @@ err_unregister_chdev:
static void __exit cleanup_mtdchar(void)
{
unregister_mtd_user(&mtdchar_notifier);
- mntput(mtd_inode_mnt);
+ kern_unmount(mtd_inode_mnt);
unregister_filesystem(&mtd_inodefs_type);
__unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd");
}
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index c5567cb7843..4d433d34736 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -233,7 +233,7 @@ static int __init anon_inode_init(void)
return 0;
err_mntput:
- mntput(anon_inode_mnt);
+ kern_unmount(anon_inode_mnt);
err_unregister_filesystem:
unregister_filesystem(&anon_inode_fs_type);
err_exit:
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index 7aafeb8fa30..0b686cec997 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -1030,6 +1030,7 @@ static int __init init_hugetlbfs_fs(void)
static void __exit exit_hugetlbfs_fs(void)
{
kmem_cache_destroy(hugetlbfs_inode_cachep);
+ kern_unmount(hugetlbfs_vfsmount);
unregister_filesystem(&hugetlbfs_fs_type);
bdi_destroy(&hugetlbfs_backing_dev_info);
}
diff --git a/fs/namespace.c b/fs/namespace.c
index cda50fe9250..22bfe8273c6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2721,6 +2721,25 @@ EXPORT_SYMBOL(put_mnt_ns);
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);
+
+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);
diff --git a/fs/pipe.c b/fs/pipe.c
index da42f7db50d..1b7f9af67cc 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1291,8 +1291,8 @@ static int __init init_pipe_fs(void)
static void __exit exit_pipe_fs(void)
{
+ kern_unmount(pipe_mnt);
unregister_filesystem(&pipe_fs_type);
- mntput(pipe_mnt);
}
fs_initcall(init_pipe_fs);
diff --git a/include/linux/fs.h b/include/linux/fs.h
index b224dc468a2..7a757a48a5c 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1885,6 +1885,7 @@ extern int register_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);
#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(struct vfsmount *);
extern long do_mount(char *, char *, char *, unsigned long, void *);
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index 35459340019..de7900ef53d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -1984,6 +1984,7 @@ __initcall(init_sel_fs);
void exit_sel_fs(void)
{
kobject_put(selinuxfs_kobj);
+ kern_unmount(selinuxfs_mount);
unregister_filesystem(&sel_fs_type);
}
#endif