diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 292 |
1 files changed, 182 insertions, 110 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index d7513485c1f3..9263995bf6a1 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -196,7 +196,7 @@ unsigned int mnt_get_count(struct vfsmount *mnt) | |||
196 | #endif | 196 | #endif |
197 | } | 197 | } |
198 | 198 | ||
199 | struct vfsmount *alloc_vfsmnt(const char *name) | 199 | static struct vfsmount *alloc_vfsmnt(const char *name) |
200 | { | 200 | { |
201 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); | 201 | struct vfsmount *mnt = kmem_cache_zalloc(mnt_cache, GFP_KERNEL); |
202 | if (mnt) { | 202 | if (mnt) { |
@@ -466,15 +466,7 @@ static void __mnt_unmake_readonly(struct vfsmount *mnt) | |||
466 | br_write_unlock(vfsmount_lock); | 466 | br_write_unlock(vfsmount_lock); |
467 | } | 467 | } |
468 | 468 | ||
469 | void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) | 469 | static void free_vfsmnt(struct vfsmount *mnt) |
470 | { | ||
471 | mnt->mnt_sb = sb; | ||
472 | mnt->mnt_root = dget(sb->s_root); | ||
473 | } | ||
474 | |||
475 | EXPORT_SYMBOL(simple_set_mnt); | ||
476 | |||
477 | void free_vfsmnt(struct vfsmount *mnt) | ||
478 | { | 470 | { |
479 | kfree(mnt->mnt_devname); | 471 | kfree(mnt->mnt_devname); |
480 | mnt_free_id(mnt); | 472 | mnt_free_id(mnt); |
@@ -678,6 +670,36 @@ static struct vfsmount *skip_mnt_tree(struct vfsmount *p) | |||
678 | return p; | 670 | return p; |
679 | } | 671 | } |
680 | 672 | ||
673 | struct vfsmount * | ||
674 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | ||
675 | { | ||
676 | struct vfsmount *mnt; | ||
677 | struct dentry *root; | ||
678 | |||
679 | if (!type) | ||
680 | return ERR_PTR(-ENODEV); | ||
681 | |||
682 | mnt = alloc_vfsmnt(name); | ||
683 | if (!mnt) | ||
684 | return ERR_PTR(-ENOMEM); | ||
685 | |||
686 | if (flags & MS_KERNMOUNT) | ||
687 | mnt->mnt_flags = MNT_INTERNAL; | ||
688 | |||
689 | root = mount_fs(type, flags, name, data); | ||
690 | if (IS_ERR(root)) { | ||
691 | free_vfsmnt(mnt); | ||
692 | return ERR_CAST(root); | ||
693 | } | ||
694 | |||
695 | mnt->mnt_root = root; | ||
696 | mnt->mnt_sb = root->d_sb; | ||
697 | mnt->mnt_mountpoint = mnt->mnt_root; | ||
698 | mnt->mnt_parent = mnt; | ||
699 | return mnt; | ||
700 | } | ||
701 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | ||
702 | |||
681 | static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | 703 | static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, |
682 | int flag) | 704 | int flag) |
683 | { | 705 | { |
@@ -1641,9 +1663,35 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
1641 | return err; | 1663 | return err; |
1642 | } | 1664 | } |
1643 | 1665 | ||
1666 | static int lock_mount(struct path *path) | ||
1667 | { | ||
1668 | struct vfsmount *mnt; | ||
1669 | retry: | ||
1670 | mutex_lock(&path->dentry->d_inode->i_mutex); | ||
1671 | if (unlikely(cant_mount(path->dentry))) { | ||
1672 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1673 | return -ENOENT; | ||
1674 | } | ||
1675 | down_write(&namespace_sem); | ||
1676 | mnt = lookup_mnt(path); | ||
1677 | if (likely(!mnt)) | ||
1678 | return 0; | ||
1679 | up_write(&namespace_sem); | ||
1680 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1681 | path_put(path); | ||
1682 | path->mnt = mnt; | ||
1683 | path->dentry = dget(mnt->mnt_root); | ||
1684 | goto retry; | ||
1685 | } | ||
1686 | |||
1687 | static void unlock_mount(struct path *path) | ||
1688 | { | ||
1689 | up_write(&namespace_sem); | ||
1690 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1691 | } | ||
1692 | |||
1644 | static int graft_tree(struct vfsmount *mnt, struct path *path) | 1693 | static int graft_tree(struct vfsmount *mnt, struct path *path) |
1645 | { | 1694 | { |
1646 | int err; | ||
1647 | if (mnt->mnt_sb->s_flags & MS_NOUSER) | 1695 | if (mnt->mnt_sb->s_flags & MS_NOUSER) |
1648 | return -EINVAL; | 1696 | return -EINVAL; |
1649 | 1697 | ||
@@ -1651,16 +1699,10 @@ static int graft_tree(struct vfsmount *mnt, struct path *path) | |||
1651 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) | 1699 | S_ISDIR(mnt->mnt_root->d_inode->i_mode)) |
1652 | return -ENOTDIR; | 1700 | return -ENOTDIR; |
1653 | 1701 | ||
1654 | err = -ENOENT; | 1702 | if (d_unlinked(path->dentry)) |
1655 | mutex_lock(&path->dentry->d_inode->i_mutex); | 1703 | return -ENOENT; |
1656 | if (cant_mount(path->dentry)) | ||
1657 | goto out_unlock; | ||
1658 | 1704 | ||
1659 | if (!d_unlinked(path->dentry)) | 1705 | return attach_recursive_mnt(mnt, path, NULL); |
1660 | err = attach_recursive_mnt(mnt, path, NULL); | ||
1661 | out_unlock: | ||
1662 | mutex_unlock(&path->dentry->d_inode->i_mutex); | ||
1663 | return err; | ||
1664 | } | 1706 | } |
1665 | 1707 | ||
1666 | /* | 1708 | /* |
@@ -1723,6 +1765,7 @@ static int do_change_type(struct path *path, int flag) | |||
1723 | static int do_loopback(struct path *path, char *old_name, | 1765 | static int do_loopback(struct path *path, char *old_name, |
1724 | int recurse) | 1766 | int recurse) |
1725 | { | 1767 | { |
1768 | LIST_HEAD(umount_list); | ||
1726 | struct path old_path; | 1769 | struct path old_path; |
1727 | struct vfsmount *mnt = NULL; | 1770 | struct vfsmount *mnt = NULL; |
1728 | int err = mount_is_safe(path); | 1771 | int err = mount_is_safe(path); |
@@ -1734,13 +1777,16 @@ static int do_loopback(struct path *path, char *old_name, | |||
1734 | if (err) | 1777 | if (err) |
1735 | return err; | 1778 | return err; |
1736 | 1779 | ||
1737 | down_write(&namespace_sem); | 1780 | err = lock_mount(path); |
1781 | if (err) | ||
1782 | goto out; | ||
1783 | |||
1738 | err = -EINVAL; | 1784 | err = -EINVAL; |
1739 | if (IS_MNT_UNBINDABLE(old_path.mnt)) | 1785 | if (IS_MNT_UNBINDABLE(old_path.mnt)) |
1740 | goto out; | 1786 | goto out2; |
1741 | 1787 | ||
1742 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) | 1788 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1743 | goto out; | 1789 | goto out2; |
1744 | 1790 | ||
1745 | err = -ENOMEM; | 1791 | err = -ENOMEM; |
1746 | if (recurse) | 1792 | if (recurse) |
@@ -1749,20 +1795,18 @@ static int do_loopback(struct path *path, char *old_name, | |||
1749 | mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); | 1795 | mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); |
1750 | 1796 | ||
1751 | if (!mnt) | 1797 | if (!mnt) |
1752 | goto out; | 1798 | goto out2; |
1753 | 1799 | ||
1754 | err = graft_tree(mnt, path); | 1800 | err = graft_tree(mnt, path); |
1755 | if (err) { | 1801 | if (err) { |
1756 | LIST_HEAD(umount_list); | ||
1757 | |||
1758 | br_write_lock(vfsmount_lock); | 1802 | br_write_lock(vfsmount_lock); |
1759 | umount_tree(mnt, 0, &umount_list); | 1803 | umount_tree(mnt, 0, &umount_list); |
1760 | br_write_unlock(vfsmount_lock); | 1804 | br_write_unlock(vfsmount_lock); |
1761 | release_mounts(&umount_list); | ||
1762 | } | 1805 | } |
1763 | 1806 | out2: | |
1807 | unlock_mount(path); | ||
1808 | release_mounts(&umount_list); | ||
1764 | out: | 1809 | out: |
1765 | up_write(&namespace_sem); | ||
1766 | path_put(&old_path); | 1810 | path_put(&old_path); |
1767 | return err; | 1811 | return err; |
1768 | } | 1812 | } |
@@ -1851,18 +1895,12 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1851 | if (err) | 1895 | if (err) |
1852 | return err; | 1896 | return err; |
1853 | 1897 | ||
1854 | down_write(&namespace_sem); | 1898 | err = lock_mount(path); |
1855 | err = follow_down(path, true); | ||
1856 | if (err < 0) | 1899 | if (err < 0) |
1857 | goto out; | 1900 | goto out; |
1858 | 1901 | ||
1859 | err = -EINVAL; | 1902 | err = -EINVAL; |
1860 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) | 1903 | if (!check_mnt(path->mnt) || !check_mnt(old_path.mnt)) |
1861 | goto out; | ||
1862 | |||
1863 | err = -ENOENT; | ||
1864 | mutex_lock(&path->dentry->d_inode->i_mutex); | ||
1865 | if (cant_mount(path->dentry)) | ||
1866 | goto out1; | 1904 | goto out1; |
1867 | 1905 | ||
1868 | if (d_unlinked(path->dentry)) | 1906 | if (d_unlinked(path->dentry)) |
@@ -1904,16 +1942,87 @@ static int do_move_mount(struct path *path, char *old_name) | |||
1904 | * automatically */ | 1942 | * automatically */ |
1905 | list_del_init(&old_path.mnt->mnt_expire); | 1943 | list_del_init(&old_path.mnt->mnt_expire); |
1906 | out1: | 1944 | out1: |
1907 | mutex_unlock(&path->dentry->d_inode->i_mutex); | 1945 | unlock_mount(path); |
1908 | out: | 1946 | out: |
1909 | up_write(&namespace_sem); | ||
1910 | if (!err) | 1947 | if (!err) |
1911 | path_put(&parent_path); | 1948 | path_put(&parent_path); |
1912 | path_put(&old_path); | 1949 | path_put(&old_path); |
1913 | return err; | 1950 | return err; |
1914 | } | 1951 | } |
1915 | 1952 | ||
1916 | static int do_add_mount(struct vfsmount *, struct path *, int); | 1953 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) |
1954 | { | ||
1955 | int err; | ||
1956 | const char *subtype = strchr(fstype, '.'); | ||
1957 | if (subtype) { | ||
1958 | subtype++; | ||
1959 | err = -EINVAL; | ||
1960 | if (!subtype[0]) | ||
1961 | goto err; | ||
1962 | } else | ||
1963 | subtype = ""; | ||
1964 | |||
1965 | mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL); | ||
1966 | err = -ENOMEM; | ||
1967 | if (!mnt->mnt_sb->s_subtype) | ||
1968 | goto err; | ||
1969 | return mnt; | ||
1970 | |||
1971 | err: | ||
1972 | mntput(mnt); | ||
1973 | return ERR_PTR(err); | ||
1974 | } | ||
1975 | |||
1976 | struct vfsmount * | ||
1977 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | ||
1978 | { | ||
1979 | struct file_system_type *type = get_fs_type(fstype); | ||
1980 | struct vfsmount *mnt; | ||
1981 | if (!type) | ||
1982 | return ERR_PTR(-ENODEV); | ||
1983 | mnt = vfs_kern_mount(type, flags, name, data); | ||
1984 | if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && | ||
1985 | !mnt->mnt_sb->s_subtype) | ||
1986 | mnt = fs_set_subtype(mnt, fstype); | ||
1987 | put_filesystem(type); | ||
1988 | return mnt; | ||
1989 | } | ||
1990 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
1991 | |||
1992 | /* | ||
1993 | * add a mount into a namespace's mount tree | ||
1994 | */ | ||
1995 | static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | ||
1996 | { | ||
1997 | int err; | ||
1998 | |||
1999 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); | ||
2000 | |||
2001 | err = lock_mount(path); | ||
2002 | if (err) | ||
2003 | return err; | ||
2004 | |||
2005 | err = -EINVAL; | ||
2006 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) | ||
2007 | goto unlock; | ||
2008 | |||
2009 | /* Refuse the same filesystem on the same mount point */ | ||
2010 | err = -EBUSY; | ||
2011 | if (path->mnt->mnt_sb == newmnt->mnt_sb && | ||
2012 | path->mnt->mnt_root == path->dentry) | ||
2013 | goto unlock; | ||
2014 | |||
2015 | err = -EINVAL; | ||
2016 | if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) | ||
2017 | goto unlock; | ||
2018 | |||
2019 | newmnt->mnt_flags = mnt_flags; | ||
2020 | err = graft_tree(newmnt, path); | ||
2021 | |||
2022 | unlock: | ||
2023 | unlock_mount(path); | ||
2024 | return err; | ||
2025 | } | ||
1917 | 2026 | ||
1918 | /* | 2027 | /* |
1919 | * create a new mount for userspace and request it to be added into the | 2028 | * create a new mount for userspace and request it to be added into the |
@@ -1973,43 +2082,6 @@ fail: | |||
1973 | return err; | 2082 | return err; |
1974 | } | 2083 | } |
1975 | 2084 | ||
1976 | /* | ||
1977 | * add a mount into a namespace's mount tree | ||
1978 | */ | ||
1979 | static int do_add_mount(struct vfsmount *newmnt, struct path *path, int mnt_flags) | ||
1980 | { | ||
1981 | int err; | ||
1982 | |||
1983 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); | ||
1984 | |||
1985 | down_write(&namespace_sem); | ||
1986 | /* Something was mounted here while we slept */ | ||
1987 | err = follow_down(path, true); | ||
1988 | if (err < 0) | ||
1989 | goto unlock; | ||
1990 | |||
1991 | err = -EINVAL; | ||
1992 | if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(path->mnt)) | ||
1993 | goto unlock; | ||
1994 | |||
1995 | /* Refuse the same filesystem on the same mount point */ | ||
1996 | err = -EBUSY; | ||
1997 | if (path->mnt->mnt_sb == newmnt->mnt_sb && | ||
1998 | path->mnt->mnt_root == path->dentry) | ||
1999 | goto unlock; | ||
2000 | |||
2001 | err = -EINVAL; | ||
2002 | if (S_ISLNK(newmnt->mnt_root->d_inode->i_mode)) | ||
2003 | goto unlock; | ||
2004 | |||
2005 | newmnt->mnt_flags = mnt_flags; | ||
2006 | err = graft_tree(newmnt, path); | ||
2007 | |||
2008 | unlock: | ||
2009 | up_write(&namespace_sem); | ||
2010 | return err; | ||
2011 | } | ||
2012 | |||
2013 | /** | 2085 | /** |
2014 | * mnt_set_expiry - Put a mount on an expiration list | 2086 | * mnt_set_expiry - Put a mount on an expiration list |
2015 | * @mnt: The mount to list. | 2087 | * @mnt: The mount to list. |
@@ -2510,65 +2582,60 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2510 | error = user_path_dir(new_root, &new); | 2582 | error = user_path_dir(new_root, &new); |
2511 | if (error) | 2583 | if (error) |
2512 | goto out0; | 2584 | goto out0; |
2513 | error = -EINVAL; | ||
2514 | if (!check_mnt(new.mnt)) | ||
2515 | goto out1; | ||
2516 | 2585 | ||
2517 | error = user_path_dir(put_old, &old); | 2586 | error = user_path_dir(put_old, &old); |
2518 | if (error) | 2587 | if (error) |
2519 | goto out1; | 2588 | goto out1; |
2520 | 2589 | ||
2521 | error = security_sb_pivotroot(&old, &new); | 2590 | error = security_sb_pivotroot(&old, &new); |
2522 | if (error) { | 2591 | if (error) |
2523 | path_put(&old); | 2592 | goto out2; |
2524 | goto out1; | ||
2525 | } | ||
2526 | 2593 | ||
2527 | get_fs_root(current->fs, &root); | 2594 | get_fs_root(current->fs, &root); |
2528 | down_write(&namespace_sem); | 2595 | error = lock_mount(&old); |
2529 | mutex_lock(&old.dentry->d_inode->i_mutex); | 2596 | if (error) |
2597 | goto out3; | ||
2598 | |||
2530 | error = -EINVAL; | 2599 | error = -EINVAL; |
2531 | if (IS_MNT_SHARED(old.mnt) || | 2600 | if (IS_MNT_SHARED(old.mnt) || |
2532 | IS_MNT_SHARED(new.mnt->mnt_parent) || | 2601 | IS_MNT_SHARED(new.mnt->mnt_parent) || |
2533 | IS_MNT_SHARED(root.mnt->mnt_parent)) | 2602 | IS_MNT_SHARED(root.mnt->mnt_parent)) |
2534 | goto out2; | 2603 | goto out4; |
2535 | if (!check_mnt(root.mnt)) | 2604 | if (!check_mnt(root.mnt) || !check_mnt(new.mnt)) |
2536 | goto out2; | 2605 | goto out4; |
2537 | error = -ENOENT; | 2606 | error = -ENOENT; |
2538 | if (cant_mount(old.dentry)) | ||
2539 | goto out2; | ||
2540 | if (d_unlinked(new.dentry)) | 2607 | if (d_unlinked(new.dentry)) |
2541 | goto out2; | 2608 | goto out4; |
2542 | if (d_unlinked(old.dentry)) | 2609 | if (d_unlinked(old.dentry)) |
2543 | goto out2; | 2610 | goto out4; |
2544 | error = -EBUSY; | 2611 | error = -EBUSY; |
2545 | if (new.mnt == root.mnt || | 2612 | if (new.mnt == root.mnt || |
2546 | old.mnt == root.mnt) | 2613 | old.mnt == root.mnt) |
2547 | goto out2; /* loop, on the same file system */ | 2614 | goto out4; /* loop, on the same file system */ |
2548 | error = -EINVAL; | 2615 | error = -EINVAL; |
2549 | if (root.mnt->mnt_root != root.dentry) | 2616 | if (root.mnt->mnt_root != root.dentry) |
2550 | goto out2; /* not a mountpoint */ | 2617 | goto out4; /* not a mountpoint */ |
2551 | if (root.mnt->mnt_parent == root.mnt) | 2618 | if (root.mnt->mnt_parent == root.mnt) |
2552 | goto out2; /* not attached */ | 2619 | goto out4; /* not attached */ |
2553 | if (new.mnt->mnt_root != new.dentry) | 2620 | if (new.mnt->mnt_root != new.dentry) |
2554 | goto out2; /* not a mountpoint */ | 2621 | goto out4; /* not a mountpoint */ |
2555 | if (new.mnt->mnt_parent == new.mnt) | 2622 | if (new.mnt->mnt_parent == new.mnt) |
2556 | goto out2; /* not attached */ | 2623 | goto out4; /* not attached */ |
2557 | /* make sure we can reach put_old from new_root */ | 2624 | /* make sure we can reach put_old from new_root */ |
2558 | tmp = old.mnt; | 2625 | tmp = old.mnt; |
2559 | br_write_lock(vfsmount_lock); | ||
2560 | if (tmp != new.mnt) { | 2626 | if (tmp != new.mnt) { |
2561 | for (;;) { | 2627 | for (;;) { |
2562 | if (tmp->mnt_parent == tmp) | 2628 | if (tmp->mnt_parent == tmp) |
2563 | goto out3; /* already mounted on put_old */ | 2629 | goto out4; /* already mounted on put_old */ |
2564 | if (tmp->mnt_parent == new.mnt) | 2630 | if (tmp->mnt_parent == new.mnt) |
2565 | break; | 2631 | break; |
2566 | tmp = tmp->mnt_parent; | 2632 | tmp = tmp->mnt_parent; |
2567 | } | 2633 | } |
2568 | if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) | 2634 | if (!is_subdir(tmp->mnt_mountpoint, new.dentry)) |
2569 | goto out3; | 2635 | goto out4; |
2570 | } else if (!is_subdir(old.dentry, new.dentry)) | 2636 | } else if (!is_subdir(old.dentry, new.dentry)) |
2571 | goto out3; | 2637 | goto out4; |
2638 | br_write_lock(vfsmount_lock); | ||
2572 | detach_mnt(new.mnt, &parent_path); | 2639 | detach_mnt(new.mnt, &parent_path); |
2573 | detach_mnt(root.mnt, &root_parent); | 2640 | detach_mnt(root.mnt, &root_parent); |
2574 | /* mount old root on put_old */ | 2641 | /* mount old root on put_old */ |
@@ -2578,22 +2645,21 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
2578 | touch_mnt_namespace(current->nsproxy->mnt_ns); | 2645 | touch_mnt_namespace(current->nsproxy->mnt_ns); |
2579 | br_write_unlock(vfsmount_lock); | 2646 | br_write_unlock(vfsmount_lock); |
2580 | chroot_fs_refs(&root, &new); | 2647 | chroot_fs_refs(&root, &new); |
2581 | |||
2582 | error = 0; | 2648 | error = 0; |
2583 | path_put(&root_parent); | 2649 | out4: |
2584 | path_put(&parent_path); | 2650 | unlock_mount(&old); |
2585 | out2: | 2651 | if (!error) { |
2586 | mutex_unlock(&old.dentry->d_inode->i_mutex); | 2652 | path_put(&root_parent); |
2587 | up_write(&namespace_sem); | 2653 | path_put(&parent_path); |
2654 | } | ||
2655 | out3: | ||
2588 | path_put(&root); | 2656 | path_put(&root); |
2657 | out2: | ||
2589 | path_put(&old); | 2658 | path_put(&old); |
2590 | out1: | 2659 | out1: |
2591 | path_put(&new); | 2660 | path_put(&new); |
2592 | out0: | 2661 | out0: |
2593 | return error; | 2662 | return error; |
2594 | out3: | ||
2595 | br_write_unlock(vfsmount_lock); | ||
2596 | goto out2; | ||
2597 | } | 2663 | } |
2598 | 2664 | ||
2599 | static void __init init_mount_tree(void) | 2665 | static void __init init_mount_tree(void) |
@@ -2668,3 +2734,9 @@ void put_mnt_ns(struct mnt_namespace *ns) | |||
2668 | kfree(ns); | 2734 | kfree(ns); |
2669 | } | 2735 | } |
2670 | EXPORT_SYMBOL(put_mnt_ns); | 2736 | EXPORT_SYMBOL(put_mnt_ns); |
2737 | |||
2738 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | ||
2739 | { | ||
2740 | return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); | ||
2741 | } | ||
2742 | EXPORT_SYMBOL_GPL(kern_mount_data); | ||