diff options
-rw-r--r-- | fs/namespace.c | 39 | ||||
-rw-r--r-- | fs/pnode.c | 15 | ||||
-rw-r--r-- | fs/pnode.h | 2 |
3 files changed, 30 insertions, 26 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); |
diff --git a/fs/pnode.c b/fs/pnode.c index 4bd3721867a7..916c8e87cf4e 100644 --- a/fs/pnode.c +++ b/fs/pnode.c | |||
@@ -221,7 +221,8 @@ static struct vfsmount *get_source(struct vfsmount *dest, | |||
221 | int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, | 221 | int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, |
222 | struct vfsmount *source_mnt, struct list_head *tree_list) | 222 | struct vfsmount *source_mnt, struct list_head *tree_list) |
223 | { | 223 | { |
224 | struct vfsmount *m, *child; | 224 | struct vfsmount *m; |
225 | struct mount *child; | ||
225 | int ret = 0; | 226 | int ret = 0; |
226 | struct vfsmount *prev_dest_mnt = dest_mnt; | 227 | struct vfsmount *prev_dest_mnt = dest_mnt; |
227 | struct vfsmount *prev_src_mnt = source_mnt; | 228 | struct vfsmount *prev_src_mnt = source_mnt; |
@@ -245,23 +246,23 @@ int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, | |||
245 | } | 246 | } |
246 | 247 | ||
247 | if (is_subdir(dest_dentry, m->mnt_root)) { | 248 | if (is_subdir(dest_dentry, m->mnt_root)) { |
248 | mnt_set_mountpoint(m, dest_dentry, child); | 249 | mnt_set_mountpoint(m, dest_dentry, &child->mnt); |
249 | list_add_tail(&child->mnt_hash, tree_list); | 250 | list_add_tail(&child->mnt.mnt_hash, tree_list); |
250 | } else { | 251 | } else { |
251 | /* | 252 | /* |
252 | * This can happen if the parent mount was bind mounted | 253 | * This can happen if the parent mount was bind mounted |
253 | * on some subdirectory of a shared/slave mount. | 254 | * on some subdirectory of a shared/slave mount. |
254 | */ | 255 | */ |
255 | list_add_tail(&child->mnt_hash, &tmp_list); | 256 | list_add_tail(&child->mnt.mnt_hash, &tmp_list); |
256 | } | 257 | } |
257 | prev_dest_mnt = m; | 258 | prev_dest_mnt = m; |
258 | prev_src_mnt = child; | 259 | prev_src_mnt = &child->mnt; |
259 | } | 260 | } |
260 | out: | 261 | out: |
261 | br_write_lock(vfsmount_lock); | 262 | br_write_lock(vfsmount_lock); |
262 | while (!list_empty(&tmp_list)) { | 263 | while (!list_empty(&tmp_list)) { |
263 | child = list_first_entry(&tmp_list, struct vfsmount, mnt_hash); | 264 | child = list_first_entry(&tmp_list, struct mount, mnt.mnt_hash); |
264 | umount_tree(child, 0, &umount_list); | 265 | umount_tree(&child->mnt, 0, &umount_list); |
265 | } | 266 | } |
266 | br_write_unlock(vfsmount_lock); | 267 | br_write_unlock(vfsmount_lock); |
267 | release_mounts(&umount_list); | 268 | release_mounts(&umount_list); |
diff --git a/fs/pnode.h b/fs/pnode.h index a2ad95435c48..ed8a84d6d78f 100644 --- a/fs/pnode.h +++ b/fs/pnode.h | |||
@@ -41,7 +41,7 @@ void mnt_set_mountpoint(struct vfsmount *, struct dentry *, | |||
41 | struct vfsmount *); | 41 | struct vfsmount *); |
42 | void release_mounts(struct list_head *); | 42 | void release_mounts(struct list_head *); |
43 | void umount_tree(struct vfsmount *, int, struct list_head *); | 43 | void umount_tree(struct vfsmount *, int, struct list_head *); |
44 | struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); | 44 | struct mount *copy_tree(struct vfsmount *, struct dentry *, int); |
45 | bool is_path_reachable(struct vfsmount *, struct dentry *, | 45 | bool is_path_reachable(struct vfsmount *, struct dentry *, |
46 | const struct path *root); | 46 | const struct path *root); |
47 | #endif /* _LINUX_PNODE_H */ | 47 | #endif /* _LINUX_PNODE_H */ |