diff options
| -rw-r--r-- | Documentation/filesystems/vfs.txt | 6 | ||||
| -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 | ||||
| -rw-r--r-- | include/linux/dcache.h | 2 | ||||
| -rw-r--r-- | include/linux/fs.h | 1 | ||||
| -rw-r--r-- | include/linux/namei.h | 2 |
12 files changed, 271 insertions, 269 deletions
diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index ef0714aa8e40..306f0ae8df09 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt | |||
| @@ -873,7 +873,7 @@ struct dentry_operations { | |||
| 873 | void (*d_iput)(struct dentry *, struct inode *); | 873 | void (*d_iput)(struct dentry *, struct inode *); |
| 874 | char *(*d_dname)(struct dentry *, char *, int); | 874 | char *(*d_dname)(struct dentry *, char *, int); |
| 875 | struct vfsmount *(*d_automount)(struct path *); | 875 | struct vfsmount *(*d_automount)(struct path *); |
| 876 | int (*d_manage)(struct dentry *, bool, bool); | 876 | int (*d_manage)(struct dentry *, bool); |
| 877 | }; | 877 | }; |
| 878 | 878 | ||
| 879 | d_revalidate: called when the VFS needs to revalidate a dentry. This | 879 | d_revalidate: called when the VFS needs to revalidate a dentry. This |
| @@ -969,10 +969,6 @@ struct dentry_operations { | |||
| 969 | mounted on it and not to check the automount flag. Any other error | 969 | mounted on it and not to check the automount flag. Any other error |
| 970 | code will abort pathwalk completely. | 970 | code will abort pathwalk completely. |
| 971 | 971 | ||
| 972 | If the 'mounting_here' parameter is true, then namespace_sem is being | ||
| 973 | held by the caller and the function should not initiate any mounts or | ||
| 974 | unmounts that it will then wait for. | ||
| 975 | |||
| 976 | If the 'rcu_walk' parameter is true, then the caller is doing a | 972 | If the 'rcu_walk' parameter is true, then the caller is doing a |
| 977 | pathwalk in RCU-walk mode. Sleeping is not permitted in this mode, | 973 | pathwalk in RCU-walk mode. Sleeping is not permitted in this mode, |
| 978 | and the caller can be asked to leave it and call again by returing | 974 | and the caller can be asked to leave it and call again by returing |
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); | ||
diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f958c19e3ca5..1a87760d6532 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h | |||
| @@ -168,7 +168,7 @@ struct dentry_operations { | |||
| 168 | void (*d_iput)(struct dentry *, struct inode *); | 168 | void (*d_iput)(struct dentry *, struct inode *); |
| 169 | char *(*d_dname)(struct dentry *, char *, int); | 169 | char *(*d_dname)(struct dentry *, char *, int); |
| 170 | struct vfsmount *(*d_automount)(struct path *); | 170 | struct vfsmount *(*d_automount)(struct path *); |
| 171 | int (*d_manage)(struct dentry *, bool, bool); | 171 | int (*d_manage)(struct dentry *, bool); |
| 172 | } ____cacheline_aligned; | 172 | } ____cacheline_aligned; |
| 173 | 173 | ||
| 174 | /* | 174 | /* |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 92f7e04aea11..7061a8587ee3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1839,7 +1839,6 @@ extern struct dentry *mount_pseudo(struct file_system_type *, char *, | |||
| 1839 | const struct super_operations *ops, | 1839 | const struct super_operations *ops, |
| 1840 | const struct dentry_operations *dops, | 1840 | const struct dentry_operations *dops, |
| 1841 | unsigned long); | 1841 | unsigned long); |
| 1842 | extern void simple_set_mnt(struct vfsmount *mnt, struct super_block *sb); | ||
| 1843 | 1842 | ||
| 1844 | static inline void sb_mark_dirty(struct super_block *sb) | 1843 | static inline void sb_mark_dirty(struct super_block *sb) |
| 1845 | { | 1844 | { |
diff --git a/include/linux/namei.h b/include/linux/namei.h index 9c8603872c36..eba45ea10298 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h | |||
| @@ -85,7 +85,7 @@ extern struct file *lookup_instantiate_filp(struct nameidata *nd, struct dentry | |||
| 85 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); | 85 | extern struct dentry *lookup_one_len(const char *, struct dentry *, int); |
| 86 | 86 | ||
| 87 | extern int follow_down_one(struct path *); | 87 | extern int follow_down_one(struct path *); |
| 88 | extern int follow_down(struct path *, bool); | 88 | extern int follow_down(struct path *); |
| 89 | extern int follow_up(struct path *); | 89 | extern int follow_up(struct path *); |
| 90 | 90 | ||
| 91 | extern struct dentry *lock_rename(struct dentry *, struct dentry *); | 91 | extern struct dentry *lock_rename(struct dentry *, struct dentry *); |
