diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:51:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-03-18 13:51:11 -0400 |
commit | f539abece1b7e36fae6add4f9ea29203d40badcb (patch) | |
tree | 786c08f3131a1871ece13343c3fa3832930c1408 /fs | |
parent | 3f6f7e6d57b8a0ae2810ae7aac70c51b6f2a6304 (diff) | |
parent | 24ff6663ccfdaf088dfa7acae489cb11ed4f43c4 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6:
fs: call security_d_instantiate in d_obtain_alias V2
lose 'mounting_here' argument in ->d_manage()
don't pass 'mounting_here' flag to follow_down()
change the locking order for namespace_sem
fix deadlock in pivot_root()
vfs: split off vfsmount-related parts of vfs_kern_mount()
Some fixes for pstore
kill simple_set_mnt()
Diffstat (limited to 'fs')
-rw-r--r-- | fs/autofs4/root.c | 6 | ||||
-rw-r--r-- | fs/dcache.c | 3 | ||||
-rw-r--r-- | fs/internal.h | 5 | ||||
-rw-r--r-- | fs/namei.c | 9 | ||||
-rw-r--r-- | fs/namespace.c | 292 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 2 | ||||
-rw-r--r-- | fs/pstore/inode.c | 116 | ||||
-rw-r--r-- | fs/super.c | 96 |
8 files changed, 268 insertions, 261 deletions
diff --git a/fs/autofs4/root.c b/fs/autofs4/root.c index 014e7aba3b08..e6f84d26f4cf 100644 --- a/fs/autofs4/root.c +++ b/fs/autofs4/root.c | |||
@@ -36,7 +36,7 @@ static long autofs4_root_compat_ioctl(struct file *,unsigned int,unsigned long); | |||
36 | static int autofs4_dir_open(struct inode *inode, struct file *file); | 36 | static int autofs4_dir_open(struct inode *inode, struct file *file); |
37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); | 37 | static struct dentry *autofs4_lookup(struct inode *,struct dentry *, struct nameidata *); |
38 | static struct vfsmount *autofs4_d_automount(struct path *); | 38 | static struct vfsmount *autofs4_d_automount(struct path *); |
39 | static int autofs4_d_manage(struct dentry *, bool, bool); | 39 | static int autofs4_d_manage(struct dentry *, bool); |
40 | static void autofs4_dentry_release(struct dentry *); | 40 | static void autofs4_dentry_release(struct dentry *); |
41 | 41 | ||
42 | const struct file_operations autofs4_root_operations = { | 42 | const struct file_operations autofs4_root_operations = { |
@@ -446,7 +446,7 @@ done: | |||
446 | return NULL; | 446 | return NULL; |
447 | } | 447 | } |
448 | 448 | ||
449 | int autofs4_d_manage(struct dentry *dentry, bool mounting_here, bool rcu_walk) | 449 | int autofs4_d_manage(struct dentry *dentry, bool rcu_walk) |
450 | { | 450 | { |
451 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); | 451 | struct autofs_sb_info *sbi = autofs4_sbi(dentry->d_sb); |
452 | 452 | ||
@@ -454,7 +454,7 @@ int autofs4_d_manage(struct dentry *dentry, bool mounting_here, bool rcu_walk) | |||
454 | dentry, dentry->d_name.len, dentry->d_name.name); | 454 | dentry, dentry->d_name.len, dentry->d_name.name); |
455 | 455 | ||
456 | /* The daemon never waits. */ | 456 | /* The daemon never waits. */ |
457 | if (autofs4_oz_mode(sbi) || mounting_here) { | 457 | if (autofs4_oz_mode(sbi)) { |
458 | if (!d_mountpoint(dentry)) | 458 | if (!d_mountpoint(dentry)) |
459 | return -EISDIR; | 459 | return -EISDIR; |
460 | return 0; | 460 | return 0; |
diff --git a/fs/dcache.c b/fs/dcache.c index 8b1f8425549f..ad25c4cec7d5 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -1612,10 +1612,13 @@ struct dentry *d_obtain_alias(struct inode *inode) | |||
1612 | __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); | 1612 | __bit_spin_unlock(0, (unsigned long *)&tmp->d_sb->s_anon.first); |
1613 | spin_unlock(&tmp->d_lock); | 1613 | spin_unlock(&tmp->d_lock); |
1614 | spin_unlock(&inode->i_lock); | 1614 | spin_unlock(&inode->i_lock); |
1615 | security_d_instantiate(tmp, inode); | ||
1615 | 1616 | ||
1616 | return tmp; | 1617 | return tmp; |
1617 | 1618 | ||
1618 | out_iput: | 1619 | out_iput: |
1620 | if (res && !IS_ERR(res)) | ||
1621 | security_d_instantiate(res, inode); | ||
1619 | iput(inode); | 1622 | iput(inode); |
1620 | return res; | 1623 | return res; |
1621 | } | 1624 | } |
diff --git a/fs/internal.h b/fs/internal.h index f3d15de44b15..17191546d527 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/lglock.h> | 12 | #include <linux/lglock.h> |
13 | 13 | ||
14 | struct super_block; | 14 | struct super_block; |
15 | struct file_system_type; | ||
15 | struct linux_binprm; | 16 | struct linux_binprm; |
16 | struct path; | 17 | struct path; |
17 | 18 | ||
@@ -61,8 +62,6 @@ extern int check_unsafe_exec(struct linux_binprm *); | |||
61 | extern int copy_mount_options(const void __user *, unsigned long *); | 62 | extern int copy_mount_options(const void __user *, unsigned long *); |
62 | extern int copy_mount_string(const void __user *, char **); | 63 | extern int copy_mount_string(const void __user *, char **); |
63 | 64 | ||
64 | extern void free_vfsmnt(struct vfsmount *); | ||
65 | extern struct vfsmount *alloc_vfsmnt(const char *); | ||
66 | extern unsigned int mnt_get_count(struct vfsmount *mnt); | 65 | extern unsigned int mnt_get_count(struct vfsmount *mnt); |
67 | extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); | 66 | extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); |
68 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, | 67 | extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, |
@@ -99,6 +98,8 @@ extern struct file *get_empty_filp(void); | |||
99 | extern int do_remount_sb(struct super_block *, int, void *, int); | 98 | extern int do_remount_sb(struct super_block *, int, void *, int); |
100 | extern void __put_super(struct super_block *sb); | 99 | extern void __put_super(struct super_block *sb); |
101 | extern void put_super(struct super_block *sb); | 100 | extern void put_super(struct super_block *sb); |
101 | extern struct dentry *mount_fs(struct file_system_type *, | ||
102 | int, const char *, void *); | ||
102 | 103 | ||
103 | /* | 104 | /* |
104 | * open.c | 105 | * open.c |
diff --git a/fs/namei.c b/fs/namei.c index b912b7abe747..5a9a6c3094da 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -933,8 +933,7 @@ static int follow_managed(struct path *path, unsigned flags) | |||
933 | if (managed & DCACHE_MANAGE_TRANSIT) { | 933 | if (managed & DCACHE_MANAGE_TRANSIT) { |
934 | BUG_ON(!path->dentry->d_op); | 934 | BUG_ON(!path->dentry->d_op); |
935 | BUG_ON(!path->dentry->d_op->d_manage); | 935 | BUG_ON(!path->dentry->d_op->d_manage); |
936 | ret = path->dentry->d_op->d_manage(path->dentry, | 936 | ret = path->dentry->d_op->d_manage(path->dentry, false); |
937 | false, false); | ||
938 | if (ret < 0) | 937 | if (ret < 0) |
939 | return ret == -EISDIR ? 0 : ret; | 938 | return ret == -EISDIR ? 0 : ret; |
940 | } | 939 | } |
@@ -999,7 +998,7 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path, | |||
999 | struct vfsmount *mounted; | 998 | struct vfsmount *mounted; |
1000 | if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) && | 999 | if (unlikely(path->dentry->d_flags & DCACHE_MANAGE_TRANSIT) && |
1001 | !reverse_transit && | 1000 | !reverse_transit && |
1002 | path->dentry->d_op->d_manage(path->dentry, false, true) < 0) | 1001 | path->dentry->d_op->d_manage(path->dentry, true) < 0) |
1003 | return false; | 1002 | return false; |
1004 | mounted = __lookup_mnt(path->mnt, path->dentry, 1); | 1003 | mounted = __lookup_mnt(path->mnt, path->dentry, 1); |
1005 | if (!mounted) | 1004 | if (!mounted) |
@@ -1065,7 +1064,7 @@ failed: | |||
1065 | * Care must be taken as namespace_sem may be held (indicated by mounting_here | 1064 | * Care must be taken as namespace_sem may be held (indicated by mounting_here |
1066 | * being true). | 1065 | * being true). |
1067 | */ | 1066 | */ |
1068 | int follow_down(struct path *path, bool mounting_here) | 1067 | int follow_down(struct path *path) |
1069 | { | 1068 | { |
1070 | unsigned managed; | 1069 | unsigned managed; |
1071 | int ret; | 1070 | int ret; |
@@ -1086,7 +1085,7 @@ int follow_down(struct path *path, bool mounting_here) | |||
1086 | BUG_ON(!path->dentry->d_op); | 1085 | BUG_ON(!path->dentry->d_op); |
1087 | BUG_ON(!path->dentry->d_op->d_manage); | 1086 | BUG_ON(!path->dentry->d_op->d_manage); |
1088 | ret = path->dentry->d_op->d_manage( | 1087 | ret = path->dentry->d_op->d_manage( |
1089 | path->dentry, mounting_here, false); | 1088 | path->dentry, false); |
1090 | if (ret < 0) | 1089 | if (ret < 0) |
1091 | return ret == -EISDIR ? 0 : ret; | 1090 | return ret == -EISDIR ? 0 : ret; |
1092 | } | 1091 | } |
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); | ||
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index da1d9701f8e4..ff93025ae2f7 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -87,7 +87,7 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp, | |||
87 | .dentry = dget(dentry)}; | 87 | .dentry = dget(dentry)}; |
88 | int err = 0; | 88 | int err = 0; |
89 | 89 | ||
90 | err = follow_down(&path, false); | 90 | err = follow_down(&path); |
91 | if (err < 0) | 91 | if (err < 0) |
92 | goto out; | 92 | goto out; |
93 | 93 | ||
diff --git a/fs/pstore/inode.c b/fs/pstore/inode.c index 549d245d0b42..08342232cb1c 100644 --- a/fs/pstore/inode.c +++ b/fs/pstore/inode.c | |||
@@ -40,9 +40,29 @@ | |||
40 | struct pstore_private { | 40 | struct pstore_private { |
41 | u64 id; | 41 | u64 id; |
42 | int (*erase)(u64); | 42 | int (*erase)(u64); |
43 | ssize_t size; | ||
44 | char data[]; | ||
43 | }; | 45 | }; |
44 | 46 | ||
45 | #define pstore_get_inode ramfs_get_inode | 47 | static int pstore_file_open(struct inode *inode, struct file *file) |
48 | { | ||
49 | file->private_data = inode->i_private; | ||
50 | return 0; | ||
51 | } | ||
52 | |||
53 | static ssize_t pstore_file_read(struct file *file, char __user *userbuf, | ||
54 | size_t count, loff_t *ppos) | ||
55 | { | ||
56 | struct pstore_private *ps = file->private_data; | ||
57 | |||
58 | return simple_read_from_buffer(userbuf, count, ppos, ps->data, ps->size); | ||
59 | } | ||
60 | |||
61 | static const struct file_operations pstore_file_operations = { | ||
62 | .open = pstore_file_open, | ||
63 | .read = pstore_file_read, | ||
64 | .llseek = default_llseek, | ||
65 | }; | ||
46 | 66 | ||
47 | /* | 67 | /* |
48 | * When a file is unlinked from our file system we call the | 68 | * When a file is unlinked from our file system we call the |
@@ -63,6 +83,30 @@ static const struct inode_operations pstore_dir_inode_operations = { | |||
63 | .unlink = pstore_unlink, | 83 | .unlink = pstore_unlink, |
64 | }; | 84 | }; |
65 | 85 | ||
86 | static struct inode *pstore_get_inode(struct super_block *sb, | ||
87 | const struct inode *dir, int mode, dev_t dev) | ||
88 | { | ||
89 | struct inode *inode = new_inode(sb); | ||
90 | |||
91 | if (inode) { | ||
92 | inode->i_ino = get_next_ino(); | ||
93 | inode->i_uid = inode->i_gid = 0; | ||
94 | inode->i_mode = mode; | ||
95 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
96 | switch (mode & S_IFMT) { | ||
97 | case S_IFREG: | ||
98 | inode->i_fop = &pstore_file_operations; | ||
99 | break; | ||
100 | case S_IFDIR: | ||
101 | inode->i_op = &pstore_dir_inode_operations; | ||
102 | inode->i_fop = &simple_dir_operations; | ||
103 | inc_nlink(inode); | ||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | return inode; | ||
108 | } | ||
109 | |||
66 | static const struct super_operations pstore_ops = { | 110 | static const struct super_operations pstore_ops = { |
67 | .statfs = simple_statfs, | 111 | .statfs = simple_statfs, |
68 | .drop_inode = generic_delete_inode, | 112 | .drop_inode = generic_delete_inode, |
@@ -70,37 +114,10 @@ static const struct super_operations pstore_ops = { | |||
70 | }; | 114 | }; |
71 | 115 | ||
72 | static struct super_block *pstore_sb; | 116 | static struct super_block *pstore_sb; |
73 | static struct vfsmount *pstore_mnt; | ||
74 | 117 | ||
75 | int pstore_is_mounted(void) | 118 | int pstore_is_mounted(void) |
76 | { | 119 | { |
77 | return pstore_mnt != NULL; | 120 | return pstore_sb != NULL; |
78 | } | ||
79 | |||
80 | /* | ||
81 | * Set up a file structure as if we had opened this file and | ||
82 | * write our data to it. | ||
83 | */ | ||
84 | static int pstore_writefile(struct inode *inode, struct dentry *dentry, | ||
85 | char *data, size_t size) | ||
86 | { | ||
87 | struct file f; | ||
88 | ssize_t n; | ||
89 | mm_segment_t old_fs = get_fs(); | ||
90 | |||
91 | memset(&f, '0', sizeof f); | ||
92 | f.f_mapping = inode->i_mapping; | ||
93 | f.f_path.dentry = dentry; | ||
94 | f.f_path.mnt = pstore_mnt; | ||
95 | f.f_pos = 0; | ||
96 | f.f_op = inode->i_fop; | ||
97 | set_fs(KERNEL_DS); | ||
98 | n = do_sync_write(&f, data, size, &f.f_pos); | ||
99 | set_fs(old_fs); | ||
100 | |||
101 | fsnotify_modify(&f); | ||
102 | |||
103 | return n == size; | ||
104 | } | 121 | } |
105 | 122 | ||
106 | /* | 123 | /* |
@@ -123,8 +140,7 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, | |||
123 | inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0); | 140 | inode = pstore_get_inode(pstore_sb, root->d_inode, S_IFREG | 0444, 0); |
124 | if (!inode) | 141 | if (!inode) |
125 | goto fail; | 142 | goto fail; |
126 | inode->i_uid = inode->i_gid = 0; | 143 | private = kmalloc(sizeof *private + size, GFP_KERNEL); |
127 | private = kmalloc(sizeof *private, GFP_KERNEL); | ||
128 | if (!private) | 144 | if (!private) |
129 | goto fail_alloc; | 145 | goto fail_alloc; |
130 | private->id = id; | 146 | private->id = id; |
@@ -152,28 +168,19 @@ int pstore_mkfile(enum pstore_type_id type, char *psname, u64 id, | |||
152 | if (IS_ERR(dentry)) | 168 | if (IS_ERR(dentry)) |
153 | goto fail_lockedalloc; | 169 | goto fail_lockedalloc; |
154 | 170 | ||
155 | d_add(dentry, inode); | 171 | memcpy(private->data, data, size); |
156 | 172 | inode->i_size = private->size = size; | |
157 | mutex_unlock(&root->d_inode->i_mutex); | ||
158 | |||
159 | if (!pstore_writefile(inode, dentry, data, size)) | ||
160 | goto fail_write; | ||
161 | 173 | ||
162 | inode->i_private = private; | 174 | inode->i_private = private; |
163 | 175 | ||
164 | if (time.tv_sec) | 176 | if (time.tv_sec) |
165 | inode->i_mtime = inode->i_ctime = time; | 177 | inode->i_mtime = inode->i_ctime = time; |
166 | 178 | ||
167 | return 0; | 179 | d_add(dentry, inode); |
168 | 180 | ||
169 | fail_write: | ||
170 | kfree(private); | ||
171 | inode->i_nlink--; | ||
172 | mutex_lock(&root->d_inode->i_mutex); | ||
173 | d_delete(dentry); | ||
174 | dput(dentry); | ||
175 | mutex_unlock(&root->d_inode->i_mutex); | 181 | mutex_unlock(&root->d_inode->i_mutex); |
176 | goto fail; | 182 | |
183 | return 0; | ||
177 | 184 | ||
178 | fail_lockedalloc: | 185 | fail_lockedalloc: |
179 | mutex_unlock(&root->d_inode->i_mutex); | 186 | mutex_unlock(&root->d_inode->i_mutex); |
@@ -225,32 +232,21 @@ fail: | |||
225 | return err; | 232 | return err; |
226 | } | 233 | } |
227 | 234 | ||
228 | static int pstore_get_sb(struct file_system_type *fs_type, | 235 | static struct dentry *pstore_mount(struct file_system_type *fs_type, |
229 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 236 | int flags, const char *dev_name, void *data) |
230 | { | 237 | { |
231 | struct dentry *root; | 238 | return mount_single(fs_type, flags, data, pstore_fill_super); |
232 | |||
233 | root = mount_nodev(fs_type, flags, data, pstore_fill_super); | ||
234 | if (IS_ERR(root)) | ||
235 | return -ENOMEM; | ||
236 | |||
237 | mnt->mnt_root = root; | ||
238 | mnt->mnt_sb = root->d_sb; | ||
239 | pstore_mnt = mnt; | ||
240 | |||
241 | return 0; | ||
242 | } | 239 | } |
243 | 240 | ||
244 | static void pstore_kill_sb(struct super_block *sb) | 241 | static void pstore_kill_sb(struct super_block *sb) |
245 | { | 242 | { |
246 | kill_litter_super(sb); | 243 | kill_litter_super(sb); |
247 | pstore_sb = NULL; | 244 | pstore_sb = NULL; |
248 | pstore_mnt = NULL; | ||
249 | } | 245 | } |
250 | 246 | ||
251 | static struct file_system_type pstore_fs_type = { | 247 | static struct file_system_type pstore_fs_type = { |
252 | .name = "pstore", | 248 | .name = "pstore", |
253 | .get_sb = pstore_get_sb, | 249 | .mount = pstore_mount, |
254 | .kill_sb = pstore_kill_sb, | 250 | .kill_sb = pstore_kill_sb, |
255 | }; | 251 | }; |
256 | 252 | ||
diff --git a/fs/super.c b/fs/super.c index 4bae0ef6110e..e84864908264 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -910,29 +910,18 @@ struct dentry *mount_single(struct file_system_type *fs_type, | |||
910 | } | 910 | } |
911 | EXPORT_SYMBOL(mount_single); | 911 | EXPORT_SYMBOL(mount_single); |
912 | 912 | ||
913 | struct vfsmount * | 913 | struct dentry * |
914 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) | 914 | mount_fs(struct file_system_type *type, int flags, const char *name, void *data) |
915 | { | 915 | { |
916 | struct vfsmount *mnt; | ||
917 | struct dentry *root; | 916 | struct dentry *root; |
917 | struct super_block *sb; | ||
918 | char *secdata = NULL; | 918 | char *secdata = NULL; |
919 | int error; | 919 | int error = -ENOMEM; |
920 | |||
921 | if (!type) | ||
922 | return ERR_PTR(-ENODEV); | ||
923 | |||
924 | error = -ENOMEM; | ||
925 | mnt = alloc_vfsmnt(name); | ||
926 | if (!mnt) | ||
927 | goto out; | ||
928 | |||
929 | if (flags & MS_KERNMOUNT) | ||
930 | mnt->mnt_flags = MNT_INTERNAL; | ||
931 | 920 | ||
932 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { | 921 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { |
933 | secdata = alloc_secdata(); | 922 | secdata = alloc_secdata(); |
934 | if (!secdata) | 923 | if (!secdata) |
935 | goto out_mnt; | 924 | goto out; |
936 | 925 | ||
937 | error = security_sb_copy_data(data, secdata); | 926 | error = security_sb_copy_data(data, secdata); |
938 | if (error) | 927 | if (error) |
@@ -944,13 +933,12 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
944 | error = PTR_ERR(root); | 933 | error = PTR_ERR(root); |
945 | goto out_free_secdata; | 934 | goto out_free_secdata; |
946 | } | 935 | } |
947 | mnt->mnt_root = root; | 936 | sb = root->d_sb; |
948 | mnt->mnt_sb = root->d_sb; | 937 | BUG_ON(!sb); |
949 | BUG_ON(!mnt->mnt_sb); | 938 | WARN_ON(!sb->s_bdi); |
950 | WARN_ON(!mnt->mnt_sb->s_bdi); | 939 | sb->s_flags |= MS_BORN; |
951 | mnt->mnt_sb->s_flags |= MS_BORN; | ||
952 | 940 | ||
953 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); | 941 | error = security_sb_kern_mount(sb, flags, secdata); |
954 | if (error) | 942 | if (error) |
955 | goto out_sb; | 943 | goto out_sb; |
956 | 944 | ||
@@ -961,27 +949,21 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
961 | * violate this rule. This warning should be either removed or | 949 | * violate this rule. This warning should be either removed or |
962 | * converted to a BUG() in 2.6.34. | 950 | * converted to a BUG() in 2.6.34. |
963 | */ | 951 | */ |
964 | WARN((mnt->mnt_sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " | 952 | WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to " |
965 | "negative value (%lld)\n", type->name, mnt->mnt_sb->s_maxbytes); | 953 | "negative value (%lld)\n", type->name, sb->s_maxbytes); |
966 | 954 | ||
967 | mnt->mnt_mountpoint = mnt->mnt_root; | 955 | up_write(&sb->s_umount); |
968 | mnt->mnt_parent = mnt; | ||
969 | up_write(&mnt->mnt_sb->s_umount); | ||
970 | free_secdata(secdata); | 956 | free_secdata(secdata); |
971 | return mnt; | 957 | return root; |
972 | out_sb: | 958 | out_sb: |
973 | dput(mnt->mnt_root); | 959 | dput(root); |
974 | deactivate_locked_super(mnt->mnt_sb); | 960 | deactivate_locked_super(sb); |
975 | out_free_secdata: | 961 | out_free_secdata: |
976 | free_secdata(secdata); | 962 | free_secdata(secdata); |
977 | out_mnt: | ||
978 | free_vfsmnt(mnt); | ||
979 | out: | 963 | out: |
980 | return ERR_PTR(error); | 964 | return ERR_PTR(error); |
981 | } | 965 | } |
982 | 966 | ||
983 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | ||
984 | |||
985 | /** | 967 | /** |
986 | * freeze_super - lock the filesystem and force it into a consistent state | 968 | * freeze_super - lock the filesystem and force it into a consistent state |
987 | * @sb: the super to lock | 969 | * @sb: the super to lock |
@@ -1071,49 +1053,3 @@ out: | |||
1071 | return 0; | 1053 | return 0; |
1072 | } | 1054 | } |
1073 | EXPORT_SYMBOL(thaw_super); | 1055 | EXPORT_SYMBOL(thaw_super); |
1074 | |||
1075 | static struct vfsmount *fs_set_subtype(struct vfsmount *mnt, const char *fstype) | ||
1076 | { | ||
1077 | int err; | ||
1078 | const char *subtype = strchr(fstype, '.'); | ||
1079 | if (subtype) { | ||
1080 | subtype++; | ||
1081 | err = -EINVAL; | ||
1082 | if (!subtype[0]) | ||
1083 | goto err; | ||
1084 | } else | ||
1085 | subtype = ""; | ||
1086 | |||
1087 | mnt->mnt_sb->s_subtype = kstrdup(subtype, GFP_KERNEL); | ||
1088 | err = -ENOMEM; | ||
1089 | if (!mnt->mnt_sb->s_subtype) | ||
1090 | goto err; | ||
1091 | return mnt; | ||
1092 | |||
1093 | err: | ||
1094 | mntput(mnt); | ||
1095 | return ERR_PTR(err); | ||
1096 | } | ||
1097 | |||
1098 | struct vfsmount * | ||
1099 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | ||
1100 | { | ||
1101 | struct file_system_type *type = get_fs_type(fstype); | ||
1102 | struct vfsmount *mnt; | ||
1103 | if (!type) | ||
1104 | return ERR_PTR(-ENODEV); | ||
1105 | mnt = vfs_kern_mount(type, flags, name, data); | ||
1106 | if (!IS_ERR(mnt) && (type->fs_flags & FS_HAS_SUBTYPE) && | ||
1107 | !mnt->mnt_sb->s_subtype) | ||
1108 | mnt = fs_set_subtype(mnt, fstype); | ||
1109 | put_filesystem(type); | ||
1110 | return mnt; | ||
1111 | } | ||
1112 | EXPORT_SYMBOL_GPL(do_kern_mount); | ||
1113 | |||
1114 | struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | ||
1115 | { | ||
1116 | return vfs_kern_mount(type, MS_KERNMOUNT, type->name, data); | ||
1117 | } | ||
1118 | |||
1119 | EXPORT_SYMBOL_GPL(kern_mount_data); | ||