diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2011-11-24 21:24:27 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-01-03 22:57:03 -0500 |
commit | 87129cc0e3fcd89a1db3e99d62dc710e05749f77 (patch) | |
tree | 0855a81e51db9f4054d54952f974bc726730f39d /fs/namespace.c | |
parent | 692afc312b38c9367a1125927941d33ab2ce852a (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.c | 63 |
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 | } |
688 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 688 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
689 | 689 | ||
690 | static struct mount *clone_mnt(struct vfsmount *old, struct dentry *root, | 690 | static 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 | ||
1411 | struct mount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | 1411 | struct 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); |