diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-11-25 05:55:08 +0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-04 07:57:01 +0400 |
commit | cb338d06e9716c92d5a7855e7c67b8f111ced722 (patch) | |
tree | 6315dfbd50fd6ba44ad468405dd4e7fe21b53618 | |
parent | 0f0afb1dcf01afc44581b3c0da251ac07dfb6e4a (diff) | |
download | linux-cb338d06e9716c92d5a7855e7c67b8f111ced722.tar.xz |
vfs: spread struct mount - clone_mnt/copy_tree result
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/namespace.c | 39 | ||||
-rw-r--r-- | fs/pnode.c | 15 | ||||
-rw-r--r-- | fs/pnode.h | 2 |
3 files changed, 30 insertions, 26 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index c7fa75f0fd92..6051a034db96 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -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 @@ Enomem: 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 @@ Enomem: 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); diff --git a/fs/pnode.c b/fs/pnode.c index 4bd3721867a7..916c8e87cf4e 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -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); diff --git a/fs/pnode.h b/fs/pnode.h index a2ad95435c48..ed8a84d6d78f 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -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 */ |