aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-11-23 19:34:49 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-03 22:52:36 -0500
commitafac7cba7ed31968a95e181dc25e204e45009ea8 (patch)
tree282cf7da6bc3915093df622ebfcd39f44f6fd1cd /fs
parentb2dba1af3c4157040303a76d25216b1713d333d0 (diff)
vfs: more mnt_parent cleanups
a) mount --move is checking that ->mnt_parent is non-NULL before looking if that parent happens to be shared; ->mnt_parent is never NULL and it's not even an misspelled !mnt_has_parent() b) pivot_root open-codes is_path_reachable(), poorly. c) so does path_is_under(), while we are at it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/dcache.c25
-rw-r--r--fs/namespace.c42
-rw-r--r--fs/pnode.c15
-rw-r--r--fs/pnode.h2
4 files changed, 29 insertions, 55 deletions
diff --git a/fs/dcache.c b/fs/dcache.c
index 8a75e3b0f49d..64c8ce4c147f 100644
--- a/fs/dcache.c
+++ b/fs/dcache.c
@@ -2853,31 +2853,6 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
2853 return result; 2853 return result;
2854} 2854}
2855 2855
2856int path_is_under(struct path *path1, struct path *path2)
2857{
2858 struct vfsmount *mnt = path1->mnt;
2859 struct dentry *dentry = path1->dentry;
2860 int res;
2861
2862 br_read_lock(vfsmount_lock);
2863 if (mnt != path2->mnt) {
2864 for (;;) {
2865 if (!mnt_has_parent(mnt)) {
2866 br_read_unlock(vfsmount_lock);
2867 return 0;
2868 }
2869 if (mnt->mnt_parent == path2->mnt)
2870 break;
2871 mnt = mnt->mnt_parent;
2872 }
2873 dentry = mnt->mnt_mountpoint;
2874 }
2875 res = is_subdir(dentry, path2->dentry);
2876 br_read_unlock(vfsmount_lock);
2877 return res;
2878}
2879EXPORT_SYMBOL(path_is_under);
2880
2881void d_genocide(struct dentry *root) 2856void d_genocide(struct dentry *root)
2882{ 2857{
2883 struct dentry *this_parent; 2858 struct dentry *this_parent;
diff --git a/fs/namespace.c b/fs/namespace.c
index ec8512478b04..7aad258dcaf6 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -1876,8 +1876,7 @@ static int do_move_mount(struct path *path, char *old_name)
1876 /* 1876 /*
1877 * Don't move a mount residing in a shared parent. 1877 * Don't move a mount residing in a shared parent.
1878 */ 1878 */
1879 if (old_path.mnt->mnt_parent && 1879 if (IS_MNT_SHARED(old_path.mnt->mnt_parent))
1880 IS_MNT_SHARED(old_path.mnt->mnt_parent))
1881 goto out1; 1880 goto out1;
1882 /* 1881 /*
1883 * Don't move a mount tree containing unbindable mounts to a destination 1882 * Don't move a mount tree containing unbindable mounts to a destination
@@ -2534,6 +2533,31 @@ out_type:
2534} 2533}
2535 2534
2536/* 2535/*
2536 * Return true if path is reachable from root
2537 *
2538 * namespace_sem or vfsmount_lock is held
2539 */
2540bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
2541 const struct path *root)
2542{
2543 while (mnt != root->mnt && mnt_has_parent(mnt)) {
2544 dentry = mnt->mnt_mountpoint;
2545 mnt = mnt->mnt_parent;
2546 }
2547 return mnt == root->mnt && is_subdir(dentry, root->dentry);
2548}
2549
2550int path_is_under(struct path *path1, struct path *path2)
2551{
2552 int res;
2553 br_read_lock(vfsmount_lock);
2554 res = is_path_reachable(path1->mnt, path1->dentry, path2);
2555 br_read_unlock(vfsmount_lock);
2556 return res;
2557}
2558EXPORT_SYMBOL(path_is_under);
2559
2560/*
2537 * pivot_root Semantics: 2561 * pivot_root Semantics:
2538 * Moves the root file system of the current process to the directory put_old, 2562 * Moves the root file system of the current process to the directory put_old,
2539 * makes new_root as the new root file system of the current process, and sets 2563 * makes new_root as the new root file system of the current process, and sets
@@ -2561,7 +2585,6 @@ out_type:
2561SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, 2585SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2562 const char __user *, put_old) 2586 const char __user *, put_old)
2563{ 2587{
2564 struct vfsmount *tmp;
2565 struct path new, old, parent_path, root_parent, root; 2588 struct path new, old, parent_path, root_parent, root;
2566 int error; 2589 int error;
2567 2590
@@ -2611,18 +2634,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
2611 if (!mnt_has_parent(new.mnt)) 2634 if (!mnt_has_parent(new.mnt))
2612 goto out4; /* not attached */ 2635 goto out4; /* not attached */
2613 /* make sure we can reach put_old from new_root */ 2636 /* make sure we can reach put_old from new_root */
2614 tmp = old.mnt; 2637 if (!is_path_reachable(old.mnt, old.dentry, &new))
2615 if (tmp != new.mnt) {
2616 for (;;) {
2617 if (!mnt_has_parent(tmp))
2618 goto out4; /* already mounted on put_old */
2619 if (tmp->mnt_parent == new.mnt)
2620 break;
2621 tmp = tmp->mnt_parent;
2622 }
2623 if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
2624 goto out4;
2625 } else if (!is_subdir(old.dentry, new.dentry))
2626 goto out4; 2638 goto out4;
2627 br_write_lock(vfsmount_lock); 2639 br_write_lock(vfsmount_lock);
2628 detach_mnt(new.mnt, &parent_path); 2640 detach_mnt(new.mnt, &parent_path);
diff --git a/fs/pnode.c b/fs/pnode.c
index f1cd958b92e5..4d5a06ea57a2 100644
--- a/fs/pnode.c
+++ b/fs/pnode.c
@@ -28,21 +28,6 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
28 return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave); 28 return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
29} 29}
30 30
31/*
32 * Return true if path is reachable from root
33 *
34 * namespace_sem is held, and mnt is attached
35 */
36static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
37 const struct path *root)
38{
39 while (mnt != root->mnt && mnt_has_parent(mnt)) {
40 dentry = mnt->mnt_mountpoint;
41 mnt = mnt->mnt_parent;
42 }
43 return mnt == root->mnt && is_subdir(dentry, root->dentry);
44}
45
46static struct vfsmount *get_peer_under_root(struct vfsmount *mnt, 31static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
47 struct mnt_namespace *ns, 32 struct mnt_namespace *ns,
48 const struct path *root) 33 const struct path *root)
diff --git a/fs/pnode.h b/fs/pnode.h
index 7f0c13ae9484..723399e76134 100644
--- a/fs/pnode.h
+++ b/fs/pnode.h
@@ -42,4 +42,6 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
42void release_mounts(struct list_head *); 42void release_mounts(struct list_head *);
43void umount_tree(struct vfsmount *, int, struct list_head *); 43void umount_tree(struct vfsmount *, int, struct list_head *);
44struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); 44struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
45bool is_path_reachable(struct vfsmount *, struct dentry *,
46 const struct path *root);
45#endif /* _LINUX_PNODE_H */ 47#endif /* _LINUX_PNODE_H */