OSDN Git Service

vfs: spread struct mount - clone_mnt/copy_tree result
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 25 Nov 2011 01:55:08 +0000 (20:55 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 4 Jan 2012 03:57:01 +0000 (22:57 -0500)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/namespace.c
fs/pnode.c
fs/pnode.h

index c7fa75f..6051a03 100644 (file)
@@ -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);
index 4bd3721..916c8e8 100644 (file)
@@ -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);
index a2ad954..ed8a84d 100644 (file)
@@ -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 */