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

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

vfs: spread struct mount - clone_mnt/copy_tree result



Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 0f0afb1d
Loading
Loading
Loading
Loading
+21 −18
Original line number Diff line number Diff line
@@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
}
EXPORT_SYMBOL_GPL(vfs_kern_mount);

static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
					int flag)
{
	struct super_block *sb = old->mnt_sb;
@@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
				list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
		}
	}
	return &mnt->mnt;
	return mnt;

 out_free:
	free_vfsmnt(mnt);
@@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path)
#endif
}

struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
					int flag)
{
	struct vfsmount *res, *p, *q, *r;
	struct mount *res, *q;
	struct vfsmount *p, *r;
	struct path path;

	if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
@@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
	res = q = clone_mnt(mnt, dentry, flag);
	if (!q)
		goto Enomem;
	q->mnt_mountpoint = mnt->mnt_mountpoint;
	q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;

	p = mnt;
	list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
@@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
			}
			while (p != s->mnt.mnt_parent) {
				p = p->mnt_parent;
				q = q->mnt_parent;
				q = real_mount(q->mnt.mnt_parent);
			}
			p = &s->mnt;
			path.mnt = q;
			path.mnt = &q->mnt;
			path.dentry = p->mnt_mountpoint;
			q = clone_mnt(p, p->mnt_root, flag);
			if (!q)
				goto Enomem;
			br_write_lock(vfsmount_lock);
			list_add_tail(&q->mnt_list, &res->mnt_list);
			attach_mnt(real_mount(q), &path);
			list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list);
			attach_mnt(q, &path);
			br_write_unlock(vfsmount_lock);
		}
	}
@@ -1454,7 +1455,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
	if (res) {
		LIST_HEAD(umount_list);
		br_write_lock(vfsmount_lock);
		umount_tree(res, 0, &umount_list);
		umount_tree(&res->mnt, 0, &umount_list);
		br_write_unlock(vfsmount_lock);
		release_mounts(&umount_list);
	}
@@ -1463,11 +1464,11 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,

struct vfsmount *collect_mounts(struct path *path)
{
	struct vfsmount *tree;
	struct mount *tree;
	down_write(&namespace_sem);
	tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
	up_write(&namespace_sem);
	return tree;
	return tree ? &tree->mnt : NULL;
}

void drop_collected_mounts(struct vfsmount *mnt)
@@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name,
{
	LIST_HEAD(umount_list);
	struct path old_path;
	struct vfsmount *mnt = NULL;
	struct mount *mnt = NULL;
	int err = mount_is_safe(path);
	if (err)
		return err;
@@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name,
	if (!mnt)
		goto out2;

	err = graft_tree(mnt, path);
	err = graft_tree(&mnt->mnt, path);
	if (err) {
		br_write_lock(vfsmount_lock);
		umount_tree(mnt, 0, &umount_list);
		umount_tree(&mnt->mnt, 0, &umount_list);
		br_write_unlock(vfsmount_lock);
	}
out2:
@@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
	struct mnt_namespace *new_ns;
	struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
	struct mount *p, *q;
	struct mount *new;

	new_ns = alloc_mnt_ns();
	if (IS_ERR(new_ns))
@@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,

	down_write(&namespace_sem);
	/* First pass: copy the tree topology */
	new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
	new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
					CL_COPY_ALL | CL_EXPIRE);
	if (!new_ns->root) {
	if (!new) {
		up_write(&namespace_sem);
		kfree(new_ns);
		return ERR_PTR(-ENOMEM);
	}
	new_ns->root = &new->mnt;
	br_write_lock(vfsmount_lock);
	list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
	br_write_unlock(vfsmount_lock);
@@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
	 * fs_struct, so tsk->fs->lock is not needed.
	 */
	p = real_mount(mnt_ns->root);
	q = real_mount(new_ns->root);
	q = new;
	while (p) {
		q->mnt.mnt_ns = new_ns;
		__mnt_make_longterm(&q->mnt);
+8 −7
Original line number Diff line number Diff line
@@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest,
int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
		    struct vfsmount *source_mnt, struct list_head *tree_list)
{
	struct vfsmount *m, *child;
	struct vfsmount *m;
	struct mount *child;
	int ret = 0;
	struct vfsmount *prev_dest_mnt = dest_mnt;
	struct vfsmount *prev_src_mnt  = source_mnt;
@@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
		}

		if (is_subdir(dest_dentry, m->mnt_root)) {
			mnt_set_mountpoint(m, dest_dentry, child);
			list_add_tail(&child->mnt_hash, tree_list);
			mnt_set_mountpoint(m, dest_dentry, &child->mnt);
			list_add_tail(&child->mnt.mnt_hash, tree_list);
		} else {
			/*
			 * This can happen if the parent mount was bind mounted
			 * on some subdirectory of a shared/slave mount.
			 */
			list_add_tail(&child->mnt_hash, &tmp_list);
			list_add_tail(&child->mnt.mnt_hash, &tmp_list);
		}
		prev_dest_mnt = m;
		prev_src_mnt  = child;
		prev_src_mnt  = &child->mnt;
	}
out:
	br_write_lock(vfsmount_lock);
	while (!list_empty(&tmp_list)) {
		child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash);
		umount_tree(child, 0, &umount_list);
		child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash);
		umount_tree(&child->mnt, 0, &umount_list);
	}
	br_write_unlock(vfsmount_lock);
	release_mounts(&umount_list);
+1 −1
Original line number Diff line number Diff line
@@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
			struct vfsmount *);
void release_mounts(struct list_head *);
void umount_tree(struct vfsmount *, int, struct list_head *);
struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int);
struct mount *copy_tree(struct vfsmount *, struct dentry *, int);
bool is_path_reachable(struct vfsmount *, struct dentry *,
			 const struct path *root);
#endif /* _LINUX_PNODE_H */