aboutsummaryrefslogtreecommitdiffstats
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)
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
687} 687}
688EXPORT_SYMBOL_GPL(vfs_kern_mount); 688EXPORT_SYMBOL_GPL(vfs_kern_mount);
689 689
690static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, 690static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
691 int flag) 691 int flag)
692{ 692{
693 struct super_block *sb = old->mnt_sb; 693 struct super_block *sb = old->mnt_sb;
@@ -733,7 +733,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root,
733 list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); 733 list_add(&mnt->mnt.mnt_expire, &old->mnt_expire);
734 } 734 }
735 } 735 }
736 return &mnt->mnt; 736 return mnt;
737 737
738 out_free: 738 out_free:
739 free_vfsmnt(mnt); 739 free_vfsmnt(mnt);
@@ -1408,10 +1408,11 @@ static int mount_is_safe(struct path *path)
1408#endif 1408#endif
1409} 1409}
1410 1410
1411struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, 1411struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
1412 int flag) 1412 int flag)
1413{ 1413{
1414 struct vfsmount *res, *p, *q, *r; 1414 struct mount *res, *q;
1415 struct vfsmount *p, *r;
1415 struct path path; 1416 struct path path;
1416 1417
1417 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) 1418 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt))
@@ -1420,7 +1421,7 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
1420 res = q = clone_mnt(mnt, dentry, flag); 1421 res = q = clone_mnt(mnt, dentry, flag);
1421 if (!q) 1422 if (!q)
1422 goto Enomem; 1423 goto Enomem;
1423 q->mnt_mountpoint = mnt->mnt_mountpoint; 1424 q->mnt.mnt_mountpoint = mnt->mnt_mountpoint;
1424 1425
1425 p = mnt; 1426 p = mnt;
1426 list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { 1427 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 } 1436 }
1436 while (p != s->mnt.mnt_parent) { 1437 while (p != s->mnt.mnt_parent) {
1437 p = p->mnt_parent; 1438 p = p->mnt_parent;
1438 q = q->mnt_parent; 1439 q = real_mount(q->mnt.mnt_parent);
1439 } 1440 }
1440 p = &s->mnt; 1441 p = &s->mnt;
1441 path.mnt = q; 1442 path.mnt = &q->mnt;
1442 path.dentry = p->mnt_mountpoint; 1443 path.dentry = p->mnt_mountpoint;
1443 q = clone_mnt(p, p->mnt_root, flag); 1444 q = clone_mnt(p, p->mnt_root, flag);
1444 if (!q) 1445 if (!q)
1445 goto Enomem; 1446 goto Enomem;
1446 br_write_lock(vfsmount_lock); 1447 br_write_lock(vfsmount_lock);
1447 list_add_tail(&q->mnt_list, &res->mnt_list); 1448 list_add_tail(&q->mnt.mnt_list, &res->mnt.mnt_list);
1448 attach_mnt(real_mount(q), &path); 1449 attach_mnt(q, &path);
1449 br_write_unlock(vfsmount_lock); 1450 br_write_unlock(vfsmount_lock);
1450 } 1451 }
1451 } 1452 }
@@ -1454,7 +1455,7 @@ Enomem:
1454 if (res) { 1455 if (res) {
1455 LIST_HEAD(umount_list); 1456 LIST_HEAD(umount_list);
1456 br_write_lock(vfsmount_lock); 1457 br_write_lock(vfsmount_lock);
1457 umount_tree(res, 0, &umount_list); 1458 umount_tree(&res->mnt, 0, &umount_list);
1458 br_write_unlock(vfsmount_lock); 1459 br_write_unlock(vfsmount_lock);
1459 release_mounts(&umount_list); 1460 release_mounts(&umount_list);
1460 } 1461 }
@@ -1463,11 +1464,11 @@ Enomem:
1463 1464
1464struct vfsmount *collect_mounts(struct path *path) 1465struct vfsmount *collect_mounts(struct path *path)
1465{ 1466{
1466 struct vfsmount *tree; 1467 struct mount *tree;
1467 down_write(&namespace_sem); 1468 down_write(&namespace_sem);
1468 tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); 1469 tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE);
1469 up_write(&namespace_sem); 1470 up_write(&namespace_sem);
1470 return tree; 1471 return tree ? &tree->mnt : NULL;
1471} 1472}
1472 1473
1473void drop_collected_mounts(struct vfsmount *mnt) 1474void drop_collected_mounts(struct vfsmount *mnt)
@@ -1739,7 +1740,7 @@ static int do_loopback(struct path *path, char *old_name,
1739{ 1740{
1740 LIST_HEAD(umount_list); 1741 LIST_HEAD(umount_list);
1741 struct path old_path; 1742 struct path old_path;
1742 struct vfsmount *mnt = NULL; 1743 struct mount *mnt = NULL;
1743 int err = mount_is_safe(path); 1744 int err = mount_is_safe(path);
1744 if (err) 1745 if (err)
1745 return err; 1746 return err;
@@ -1769,10 +1770,10 @@ static int do_loopback(struct path *path, char *old_name,
1769 if (!mnt) 1770 if (!mnt)
1770 goto out2; 1771 goto out2;
1771 1772
1772 err = graft_tree(mnt, path); 1773 err = graft_tree(&mnt->mnt, path);
1773 if (err) { 1774 if (err) {
1774 br_write_lock(vfsmount_lock); 1775 br_write_lock(vfsmount_lock);
1775 umount_tree(mnt, 0, &umount_list); 1776 umount_tree(&mnt->mnt, 0, &umount_list);
1776 br_write_unlock(vfsmount_lock); 1777 br_write_unlock(vfsmount_lock);
1777 } 1778 }
1778out2: 1779out2:
@@ -2385,6 +2386,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2385 struct mnt_namespace *new_ns; 2386 struct mnt_namespace *new_ns;
2386 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL; 2387 struct vfsmount *rootmnt = NULL, *pwdmnt = NULL;
2387 struct mount *p, *q; 2388 struct mount *p, *q;
2389 struct mount *new;
2388 2390
2389 new_ns = alloc_mnt_ns(); 2391 new_ns = alloc_mnt_ns();
2390 if (IS_ERR(new_ns)) 2392 if (IS_ERR(new_ns))
@@ -2392,13 +2394,14 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2392 2394
2393 down_write(&namespace_sem); 2395 down_write(&namespace_sem);
2394 /* First pass: copy the tree topology */ 2396 /* First pass: copy the tree topology */
2395 new_ns->root = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, 2397 new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root,
2396 CL_COPY_ALL | CL_EXPIRE); 2398 CL_COPY_ALL | CL_EXPIRE);
2397 if (!new_ns->root) { 2399 if (!new) {
2398 up_write(&namespace_sem); 2400 up_write(&namespace_sem);
2399 kfree(new_ns); 2401 kfree(new_ns);
2400 return ERR_PTR(-ENOMEM); 2402 return ERR_PTR(-ENOMEM);
2401 } 2403 }
2404 new_ns->root = &new->mnt;
2402 br_write_lock(vfsmount_lock); 2405 br_write_lock(vfsmount_lock);
2403 list_add_tail(&new_ns->list, &new_ns->root->mnt_list); 2406 list_add_tail(&new_ns->list, &new_ns->root->mnt_list);
2404 br_write_unlock(vfsmount_lock); 2407 br_write_unlock(vfsmount_lock);
@@ -2409,7 +2412,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2409 * fs_struct, so tsk->fs->lock is not needed. 2412 * fs_struct, so tsk->fs->lock is not needed.
2410 */ 2413 */
2411 p = real_mount(mnt_ns->root); 2414 p = real_mount(mnt_ns->root);
2412 q = real_mount(new_ns->root); 2415 q = new;
2413 while (p) { 2416 while (p) {
2414 q->mnt.mnt_ns = new_ns; 2417 q->mnt.mnt_ns = new_ns;
2415 __mnt_make_longterm(&q->mnt); 2418 __mnt_make_longterm(&q->mnt);