提交 cb338d06 编写于 作者: A Al Viro

vfs: spread struct mount - clone_mnt/copy_tree result

Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
上级 0f0afb1d
...@@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void ...@@ -687,7 +687,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void
} }
EXPORT_SYMBOL_GPL(vfs_kern_mount); 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) int flag)
{ {
struct super_block *sb = old->mnt_sb; struct super_block *sb = old->mnt_sb;
...@@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, ...@@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
} }
} }
return &mnt->mnt; return mnt;
out_free: out_free:
free_vfsmnt(mnt); free_vfsmnt(mnt);
...@@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path) ...@@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path)
#endif #endif
} }
struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
int flag) int flag)
{ {
struct vfsmount *res, *p, *q, *r; struct mount *res, *q;
struct vfsmount *p, *r;
struct path path; struct path path;
if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
...@@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
res = q = clone_mnt(mnt, dentry, flag); res = q = clone_mnt(mnt, dentry, flag);
if (!q) if (!q)
goto Enomem; goto Enomem;
q->mnt_mountpoint = mnt->mnt_mountpoint; q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;
p = mnt; p = mnt;
list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) {
...@@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1435,17 +1436,17 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
} }
while (p != s->mnt.mnt_parent) { while (p != s->mnt.mnt_parent) {
p = p->mnt_parent; p = p->mnt_parent;
q = q->mnt_parent; q = real_mount(q->mnt.mnt_parent);
} }
p = &s->mnt; p = &s->mnt;
path.mnt = q; path.mnt = &q->mnt;
path.dentry = p->mnt_mountpoint; path.dentry = p->mnt_mountpoint;
q = clone_mnt(p, p->mnt_root, flag); q = clone_mnt(p, p->mnt_root, flag);
if (!q) if (!q)
goto Enomem; goto Enomem;
br_write_lock(vfsmount_lock); br_write_lock(vfsmount_lock);
list_add_tail(&q->mnt_list, &res->mnt_list); list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list);
attach_mnt(real_mount(q), &path); attach_mnt(q, &path);
br_write_unlock(vfsmount_lock); br_write_unlock(vfsmount_lock);
} }
} }
...@@ -1454,7 +1455,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1454,7 +1455,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
if (res) { if (res) {
LIST_HEAD(umount_list); LIST_HEAD(umount_list);
br_write_lock(vfsmount_lock); br_write_lock(vfsmount_lock);
umount_tree(res, 0, &umount_list); umount_tree(&res->mnt, 0, &umount_list);
br_write_unlock(vfsmount_lock); br_write_unlock(vfsmount_lock);
release_mounts(&umount_list); release_mounts(&umount_list);
} }
...@@ -1463,11 +1464,11 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, ...@@ -1463,11 +1464,11 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
struct vfsmount *collect_mounts(struct path *path) struct vfsmount *collect_mounts(struct path *path)
{ {
struct vfsmount *tree; struct mount *tree;
down_write(&namespace_sem); down_write(&namespace_sem);
tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
up_write(&namespace_sem); up_write(&namespace_sem);
return tree; return tree ? &tree->mnt : NULL;
} }
void drop_collected_mounts(struct vfsmount *mnt) void drop_collected_mounts(struct vfsmount *mnt)
...@@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name, ...@@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name,
{ {
LIST_HEAD(umount_list); LIST_HEAD(umount_list);
struct path old_path; struct path old_path;
struct vfsmount *mnt = NULL; struct mount *mnt = NULL;
int err = mount_is_safe(path); int err = mount_is_safe(path);
if (err) if (err)
return err; return err;
...@@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name, ...@@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name,
if (!mnt) if (!mnt)
goto out2; goto out2;
err = graft_tree(mnt, path); err = graft_tree(&mnt->mnt, path);
if (err) { if (err) {
br_write_lock(vfsmount_lock); br_write_lock(vfsmount_lock);
umount_tree(mnt, 0, &umount_list); umount_tree(&mnt->mnt, 0, &umount_list);
br_write_unlock(vfsmount_lock); br_write_unlock(vfsmount_lock);
} }
out2: out2:
...@@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, ...@@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
struct mnt_namespace *new_ns; struct mnt_namespace *new_ns;
struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
struct mount *p, *q; struct mount *p, *q;
struct mount *new;
new_ns = alloc_mnt_ns(); new_ns = alloc_mnt_ns();
if (IS_ERR(new_ns)) if (IS_ERR(new_ns))
...@@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, ...@@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
down_write(&namespace_sem); down_write(&namespace_sem);
/* First pass: copy the tree topology */ /* 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); CL_COPY_ALL | CL_EXPIRE);
if (!new_ns->root) { if (!new) {
up_write(&namespace_sem); up_write(&namespace_sem);
kfree(new_ns); kfree(new_ns);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
new_ns->root = &new->mnt;
br_write_lock(vfsmount_lock); br_write_lock(vfsmount_lock);
list_add_tail(&new_ns->list, &new_ns->root->mnt_list); list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
br_write_unlock(vfsmount_lock); br_write_unlock(vfsmount_lock);
...@@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, ...@@ -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. * fs_struct, so tsk->fs->lock is not needed.
*/ */
p = real_mount(mnt_ns->root); p = real_mount(mnt_ns->root);
q = real_mount(new_ns->root); q = new;
while (p) { while (p) {
q->mnt.mnt_ns = new_ns; q->mnt.mnt_ns = new_ns;
__mnt_make_longterm(&q->mnt); __mnt_make_longterm(&q->mnt);
......
...@@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest, ...@@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest,
int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
struct vfsmount *source_mnt, struct list_head *tree_list) struct vfsmount *source_mnt, struct list_head *tree_list)
{ {
struct vfsmount *m, *child; struct vfsmount *m;
struct mount *child;
int ret = 0; int ret = 0;
struct vfsmount *prev_dest_mnt = dest_mnt; struct vfsmount *prev_dest_mnt = dest_mnt;
struct vfsmount *prev_src_mnt = source_mnt; struct vfsmount *prev_src_mnt = source_mnt;
...@@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, ...@@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry,
} }
if (is_subdir(dest_dentry, m->mnt_root)) { if (is_subdir(dest_dentry, m->mnt_root)) {
mnt_set_mountpoint(m, dest_dentry, child); mnt_set_mountpoint(m, dest_dentry, &child->mnt);
list_add_tail(&child->mnt_hash, tree_list); list_add_tail(&child->mnt.mnt_hash, tree_list);
} else { } else {
/* /*
* This can happen if the parent mount was bind mounted * This can happen if the parent mount was bind mounted
* on some subdirectory of a shared/slave mount. * 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_dest_mnt = m;
prev_src_mnt = child; prev_src_mnt = &child->mnt;
} }
out: out:
br_write_lock(vfsmount_lock); br_write_lock(vfsmount_lock);
while (!list_empty(&tmp_list)) { while (!list_empty(&tmp_list)) {
child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash); child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash);
umount_tree(child, 0, &umount_list); umount_tree(&child->mnt, 0, &umount_list);
} }
br_write_unlock(vfsmount_lock); br_write_unlock(vfsmount_lock);
release_mounts(&umount_list); release_mounts(&umount_list);
......
...@@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *, ...@@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *,
struct vfsmount *); struct vfsmount *);
void release_mounts(struct list_head *); void release_mounts(struct list_head *);
void umount_tree(struct vfsmount *, int, 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 *, bool is_path_reachable(struct vfsmount *, struct dentry *,
const struct path *root); const struct path *root);
#endif /* _LINUX_PNODE_H */ #endif /* _LINUX_PNODE_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册