diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 39 |
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 | } |
688 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | 688 | EXPORT_SYMBOL_GPL(vfs_kern_mount); |
689 | 689 | ||
690 | static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | 690 | static 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 | ||
1411 | struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, | 1411 | struct 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 | ||
1464 | struct vfsmount *collect_mounts(struct path *path) | 1465 | struct 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 | ||
1473 | void drop_collected_mounts(struct vfsmount *mnt) | 1474 | void 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 | } |
1778 | out2: | 1779 | out2: |
@@ -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); |