Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit afac7cba authored by Al Viro's avatar Al Viro
Browse files

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent b2dba1af
Loading
Loading
Loading
Loading
+0 −25
Original line number Diff line number Diff line
@@ -2853,31 +2853,6 @@ int is_subdir(struct dentry *new_dentry, struct dentry *old_dentry)
	return result;
}

int path_is_under(struct path *path1, struct path *path2)
{
	struct vfsmount *mnt = path1->mnt;
	struct dentry *dentry = path1->dentry;
	int res;

	br_read_lock(vfsmount_lock);
	if (mnt != path2->mnt) {
		for (;;) {
			if (!mnt_has_parent(mnt)) {
				br_read_unlock(vfsmount_lock);
				return 0;
			}
			if (mnt->mnt_parent == path2->mnt)
				break;
			mnt = mnt->mnt_parent;
		}
		dentry = mnt->mnt_mountpoint;
	}
	res = is_subdir(dentry, path2->dentry);
	br_read_unlock(vfsmount_lock);
	return res;
}
EXPORT_SYMBOL(path_is_under);

void d_genocide(struct dentry *root)
{
	struct dentry *this_parent;
+27 −15
Original line number Diff line number Diff line
@@ -1876,8 +1876,7 @@ static int do_move_mount(struct path *path, char *old_name)
	/*
	 * Don't move a mount residing in a shared parent.
	 */
	if (old_path.mnt->mnt_parent &&
	    IS_MNT_SHARED(old_path.mnt->mnt_parent))
	if (IS_MNT_SHARED(old_path.mnt->mnt_parent))
		goto out1;
	/*
	 * Don't move a mount tree containing unbindable mounts to a destination
@@ -2533,6 +2532,31 @@ out_type:
	return ret;
}

/*
 * Return true if path is reachable from root
 *
 * namespace_sem or vfsmount_lock is held
 */
bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
			 const struct path *root)
{
	while (mnt != root->mnt && mnt_has_parent(mnt)) {
		dentry = mnt->mnt_mountpoint;
		mnt = mnt->mnt_parent;
	}
	return mnt == root->mnt && is_subdir(dentry, root->dentry);
}

int path_is_under(struct path *path1, struct path *path2)
{
	int res;
	br_read_lock(vfsmount_lock);
	res = is_path_reachable(path1->mnt, path1->dentry, path2);
	br_read_unlock(vfsmount_lock);
	return res;
}
EXPORT_SYMBOL(path_is_under);

/*
 * pivot_root Semantics:
 * Moves the root file system of the current process to the directory put_old,
@@ -2561,7 +2585,6 @@ out_type:
SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
		const char __user *, put_old)
{
	struct vfsmount *tmp;
	struct path new, old, parent_path, root_parent, root;
	int error;

@@ -2611,18 +2634,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root,
	if (!mnt_has_parent(new.mnt))
		goto out4; /* not attached */
	/* make sure we can reach put_old from new_root */
	tmp = old.mnt;
	if (tmp != new.mnt) {
		for (;;) {
			if (!mnt_has_parent(tmp))
				goto out4; /* already mounted on put_old */
			if (tmp->mnt_parent == new.mnt)
				break;
			tmp = tmp->mnt_parent;
		}
		if (!is_subdir(tmp->mnt_mountpoint, new.dentry))
			goto out4;
	} else if (!is_subdir(old.dentry, new.dentry))
	if (!is_path_reachable(old.mnt, old.dentry, &new))
		goto out4;
	br_write_lock(vfsmount_lock);
	detach_mnt(new.mnt, &parent_path);
+0 −15
Original line number Diff line number Diff line
@@ -28,21 +28,6 @@ static inline struct vfsmount *next_slave(struct vfsmount *p)
	return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave);
}

/*
 * Return true if path is reachable from root
 *
 * namespace_sem is held, and mnt is attached
 */
static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry,
			 const struct path *root)
{
	while (mnt != root->mnt && mnt_has_parent(mnt)) {
		dentry = mnt->mnt_mountpoint;
		mnt = mnt->mnt_parent;
	}
	return mnt == root->mnt && is_subdir(dentry, root->dentry);
}

static struct vfsmount *get_peer_under_root(struct vfsmount *mnt,
					    struct mnt_namespace *ns,
					    const struct path *root)
+2 −0
Original line number Diff line number Diff line
@@ -42,4 +42,6 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
void release_mounts(struct list_head *);
void umount_tree(struct vfsmount *, int, struct list_head *);
struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
bool is_path_reachable(struct vfsmount *, struct dentry *,
			 const struct path *root);
#endif /* _LINUX_PNODE_H */