aboutsummaryrefslogtreecommitdiffstats
path: root/fs/namespace.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2011-11-24 21:24:27 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2012-01-03 22:57:03 -0500
commit87129cc0e3fcd89a1db3e99d62dc710e05749f77 (patch)
tree0855a81e51db9f4054d54952f974bc726730f39d /fs/namespace.c
parent692afc312b38c9367a1125927941d33ab2ce852a (diff)
vfs: spread struct mount - clone_mnt/copy_tree argument
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/namespace.c')
-rw-r--r--fs/namespace.c63
1 files changed, 33 insertions, 30 deletions
diff --git a/fs/namespace.c b/fs/namespace.c
index fa0f30d862c6..211455e2cd17 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -687,17 +687,17 @@ 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 mount *clone_mnt(struct vfsmount *old, struct dentry *root, 690static struct mount *clone_mnt(struct mount *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.mnt_sb;
694 struct mount *mnt = alloc_vfsmnt(old->mnt_devname); 694 struct mount *mnt = alloc_vfsmnt(old->mnt.mnt_devname);
695 695
696 if (mnt) { 696 if (mnt) {
697 if (flag & (CL_SLAVE | CL_PRIVATE)) 697 if (flag & (CL_SLAVE | CL_PRIVATE))
698 mnt->mnt.mnt_group_id = 0; /* not a peer of original */ 698 mnt->mnt.mnt_group_id = 0; /* not a peer of original */
699 else 699 else
700 mnt->mnt.mnt_group_id = old->mnt_group_id; 700 mnt->mnt.mnt_group_id = old->mnt.mnt_group_id;
701 701
702 if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) { 702 if ((flag & CL_MAKE_SHARED) && !mnt->mnt.mnt_group_id) {
703 int err = mnt_alloc_group_id(mnt); 703 int err = mnt_alloc_group_id(mnt);
@@ -705,7 +705,7 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
705 goto out_free; 705 goto out_free;
706 } 706 }
707 707
708 mnt->mnt.mnt_flags = old->mnt_flags & ~MNT_WRITE_HOLD; 708 mnt->mnt.mnt_flags = old->mnt.mnt_flags & ~MNT_WRITE_HOLD;
709 atomic_inc(&sb->s_active); 709 atomic_inc(&sb->s_active);
710 mnt->mnt.mnt_sb = sb; 710 mnt->mnt.mnt_sb = sb;
711 mnt->mnt.mnt_root = dget(root); 711 mnt->mnt.mnt_root = dget(root);
@@ -713,15 +713,15 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
713 mnt->mnt.mnt_parent = &mnt->mnt; 713 mnt->mnt.mnt_parent = &mnt->mnt;
714 714
715 if (flag & CL_SLAVE) { 715 if (flag & CL_SLAVE) {
716 list_add(&mnt->mnt.mnt_slave, &old->mnt_slave_list); 716 list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave_list);
717 mnt->mnt.mnt_master = old; 717 mnt->mnt.mnt_master = &old->mnt;
718 CLEAR_MNT_SHARED(&mnt->mnt); 718 CLEAR_MNT_SHARED(&mnt->mnt);
719 } else if (!(flag & CL_PRIVATE)) { 719 } else if (!(flag & CL_PRIVATE)) {
720 if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) 720 if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(&old->mnt))
721 list_add(&mnt->mnt.mnt_share, &old->mnt_share); 721 list_add(&mnt->mnt.mnt_share, &old->mnt.mnt_share);
722 if (IS_MNT_SLAVE(old)) 722 if (IS_MNT_SLAVE(&old->mnt))
723 list_add(&mnt->mnt.mnt_slave, &old->mnt_slave); 723 list_add(&mnt->mnt.mnt_slave, &old->mnt.mnt_slave);
724 mnt->mnt.mnt_master = old->mnt_master; 724 mnt->mnt.mnt_master = old->mnt.mnt_master;
725 } 725 }
726 if (flag & CL_MAKE_SHARED) 726 if (flag & CL_MAKE_SHARED)
727 set_mnt_shared(mnt); 727 set_mnt_shared(mnt);
@@ -729,8 +729,8 @@ static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root,
729 /* stick the duplicate mount on the same expiry list 729 /* stick the duplicate mount on the same expiry list
730 * as the original if that was on one */ 730 * as the original if that was on one */
731 if (flag & CL_EXPIRE) { 731 if (flag & CL_EXPIRE) {
732 if (!list_empty(&old->mnt_expire)) 732 if (!list_empty(&old->mnt.mnt_expire))
733 list_add(&mnt->mnt.mnt_expire, &old->mnt_expire); 733 list_add(&mnt->mnt.mnt_expire, &old->mnt.mnt_expire);
734 } 734 }
735 } 735 }
736 return mnt; 736 return mnt;
@@ -1408,23 +1408,23 @@ static int mount_is_safe(struct path *path)
1408#endif 1408#endif
1409} 1409}
1410 1410
1411struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, 1411struct mount *copy_tree(struct mount *mnt, struct dentry *dentry,
1412 int flag) 1412 int flag)
1413{ 1413{
1414 struct mount *res, *q; 1414 struct mount *res, *p, *q;
1415 struct vfsmount *p, *r; 1415 struct vfsmount *r;
1416 struct path path; 1416 struct path path;
1417 1417
1418 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) 1418 if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(&mnt->mnt))
1419 return NULL; 1419 return NULL;
1420 1420
1421 res = q = clone_mnt(mnt, dentry, flag); 1421 res = q = clone_mnt(mnt, dentry, flag);
1422 if (!q) 1422 if (!q)
1423 goto Enomem; 1423 goto Enomem;
1424 q->mnt.mnt_mountpoint = mnt->mnt_mountpoint; 1424 q->mnt.mnt_mountpoint = mnt->mnt.mnt_mountpoint;
1425 1425
1426 p = mnt; 1426 p = mnt;
1427 list_for_each_entry(r, &mnt->mnt_mounts, mnt_child) { 1427 list_for_each_entry(r, &mnt->mnt.mnt_mounts, mnt_child) {
1428 struct mount *s; 1428 struct mount *s;
1429 if (!is_subdir(r->mnt_mountpoint, dentry)) 1429 if (!is_subdir(r->mnt_mountpoint, dentry))
1430 continue; 1430 continue;
@@ -1434,14 +1434,14 @@ struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry,
1434 s = skip_mnt_tree(s); 1434 s = skip_mnt_tree(s);
1435 continue; 1435 continue;
1436 } 1436 }
1437 while (p != s->mnt.mnt_parent) { 1437 while (p != real_mount(s->mnt.mnt_parent)) {
1438 p = p->mnt_parent; 1438 p = real_mount(p->mnt.mnt_parent);
1439 q = real_mount(q->mnt.mnt_parent); 1439 q = real_mount(q->mnt.mnt_parent);
1440 } 1440 }
1441 p = &s->mnt; 1441 p = s;
1442 path.mnt = &q->mnt; 1442 path.mnt = &q->mnt;
1443 path.dentry = p->mnt_mountpoint; 1443 path.dentry = p->mnt.mnt_mountpoint;
1444 q = clone_mnt(p, p->mnt_root, flag); 1444 q = clone_mnt(p, p->mnt.mnt_root, flag);
1445 if (!q) 1445 if (!q)
1446 goto Enomem; 1446 goto Enomem;
1447 br_write_lock(vfsmount_lock); 1447 br_write_lock(vfsmount_lock);
@@ -1466,7 +1466,8 @@ struct vfsmount *collect_mounts(struct path *path)
1466{ 1466{
1467 struct mount *tree; 1467 struct mount *tree;
1468 down_write(&namespace_sem); 1468 down_write(&namespace_sem);
1469 tree = copy_tree(path->mnt, path->dentry, CL_COPY_ALL | CL_PRIVATE); 1469 tree = copy_tree(real_mount(path->mnt), path->dentry,
1470 CL_COPY_ALL | CL_PRIVATE);
1470 up_write(&namespace_sem); 1471 up_write(&namespace_sem);
1471 return tree ? &tree->mnt : NULL; 1472 return tree ? &tree->mnt : NULL;
1472} 1473}
@@ -1740,7 +1741,7 @@ static int do_loopback(struct path *path, char *old_name,
1740{ 1741{
1741 LIST_HEAD(umount_list); 1742 LIST_HEAD(umount_list);
1742 struct path old_path; 1743 struct path old_path;
1743 struct mount *mnt = NULL; 1744 struct mount *mnt = NULL, *old;
1744 int err = mount_is_safe(path); 1745 int err = mount_is_safe(path);
1745 if (err) 1746 if (err)
1746 return err; 1747 return err;
@@ -1754,6 +1755,8 @@ static int do_loopback(struct path *path, char *old_name,
1754 if (err) 1755 if (err)
1755 goto out; 1756 goto out;
1756 1757
1758 old = real_mount(old_path.mnt);
1759
1757 err = -EINVAL; 1760 err = -EINVAL;
1758 if (IS_MNT_UNBINDABLE(old_path.mnt)) 1761 if (IS_MNT_UNBINDABLE(old_path.mnt))
1759 goto out2; 1762 goto out2;
@@ -1763,9 +1766,9 @@ static int do_loopback(struct path *path, char *old_name,
1763 1766
1764 err = -ENOMEM; 1767 err = -ENOMEM;
1765 if (recurse) 1768 if (recurse)
1766 mnt = copy_tree(old_path.mnt, old_path.dentry, 0); 1769 mnt = copy_tree(old, old_path.dentry, 0);
1767 else 1770 else
1768 mnt = clone_mnt(old_path.mnt, old_path.dentry, 0); 1771 mnt = clone_mnt(old, old_path.dentry, 0);
1769 1772
1770 if (!mnt) 1773 if (!mnt)
1771 goto out2; 1774 goto out2;
@@ -2394,7 +2397,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns,
2394 2397
2395 down_write(&namespace_sem); 2398 down_write(&namespace_sem);
2396 /* First pass: copy the tree topology */ 2399 /* First pass: copy the tree topology */
2397 new = copy_tree(mnt_ns->root, mnt_ns->root->mnt_root, 2400 new = copy_tree(real_mount(mnt_ns->root), mnt_ns->root->mnt_root,
2398 CL_COPY_ALL | CL_EXPIRE); 2401 CL_COPY_ALL | CL_EXPIRE);
2399 if (!new) { 2402 if (!new) {
2400 up_write(&namespace_sem); 2403 up_write(&namespace_sem);