summary refs log tree commit diff
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-11-24 20:55:08 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-03 22:57:01 -0500
commitcb338d06e9716c92d5a7855e7c67b8f111ced722 (patch)
tree6315dfbd50fd6ba44ad468405dd4e7fe21b53618 /fs/namespace.c
parent0f0afb1dcf01afc44581b3c0da251ac07dfb6e4a (diff)
downloadlinux-cb338d06e9716c92d5a7855e7c67b8f111ced722.tar.gz
vfs: spread struct mount - clone_mnt/copy_tree result
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c39
1 files changed, 21 insertions, 18 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);