diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index e5e1c7d1839b..cfc6d4448aa5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -1048,15 +1048,12 @@ static int show_mountinfo(struct seq_file *m, void *v) | |||
1048 | if (err) | 1048 | if (err) |
1049 | goto out; | 1049 | goto out; |
1050 | seq_putc(m, ' '); | 1050 | seq_putc(m, ' '); |
1051 | seq_path_root(m, &mnt_path, &root, " \t\n\\"); | 1051 | |
1052 | if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { | 1052 | /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ |
1053 | /* | 1053 | err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); |
1054 | * Mountpoint is outside root, discard that one. Ugly, | 1054 | if (err) |
1055 | * but less so than trying to do that in iterator in a | 1055 | goto out; |
1056 | * race-free way (due to renames). | 1056 | |
1057 | */ | ||
1058 | return SEQ_SKIP; | ||
1059 | } | ||
1060 | seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); | 1057 | seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); |
1061 | show_mnt_opts(m, mnt); | 1058 | show_mnt_opts(m, mnt); |
1062 | 1059 | ||
@@ -2483,11 +2480,43 @@ struct mnt_namespace *create_mnt_ns(struct vfsmount *mnt) | |||
2483 | __mnt_make_longterm(mnt); | 2480 | __mnt_make_longterm(mnt); |
2484 | new_ns->root = mnt; | 2481 | new_ns->root = mnt; |
2485 | list_add(&new_ns->list, &new_ns->root->mnt_list); | 2482 | list_add(&new_ns->list, &new_ns->root->mnt_list); |
2483 | } else { | ||
2484 | mntput(mnt); | ||
2486 | } | 2485 | } |
2487 | return new_ns; | 2486 | return new_ns; |
2488 | } | 2487 | } |
2489 | EXPORT_SYMBOL(create_mnt_ns); | 2488 | EXPORT_SYMBOL(create_mnt_ns); |
2490 | 2489 | ||
2490 | struct dentry *mount_subtree(struct vfsmount *mnt, const char *name) | ||
2491 | { | ||
2492 | struct mnt_namespace *ns; | ||
2493 | struct super_block *s; | ||
2494 | struct path path; | ||
2495 | int err; | ||
2496 | |||
2497 | ns = create_mnt_ns(mnt); | ||
2498 | if (IS_ERR(ns)) | ||
2499 | return ERR_CAST(ns); | ||
2500 | |||
2501 | err = vfs_path_lookup(mnt->mnt_root, mnt, | ||
2502 | name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &path); | ||
2503 | |||
2504 | put_mnt_ns(ns); | ||
2505 | |||
2506 | if (err) | ||
2507 | return ERR_PTR(err); | ||
2508 | |||
2509 | /* trade a vfsmount reference for active sb one */ | ||
2510 | s = path.mnt->mnt_sb; | ||
2511 | atomic_inc(&s->s_active); | ||
2512 | mntput(path.mnt); | ||
2513 | /* lock the sucker */ | ||
2514 | down_write(&s->s_umount); | ||
2515 | /* ... and return the root of (sub)tree on it */ | ||
2516 | return path.dentry; | ||
2517 | } | ||
2518 | EXPORT_SYMBOL(mount_subtree); | ||
2519 | |||
2491 | SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, | 2520 | SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, |
2492 | char __user *, type, unsigned long, flags, void __user *, data) | 2521 | char __user *, type, unsigned long, flags, void __user *, data) |
2493 | { | 2522 | { |
@@ -2744,3 +2773,8 @@ void kern_unmount(struct vfsmount *mnt) | |||
2744 | } | 2773 | } |
2745 | } | 2774 | } |
2746 | EXPORT_SYMBOL(kern_unmount); | 2775 | EXPORT_SYMBOL(kern_unmount); |
2776 | |||
2777 | bool our_mnt(struct vfsmount *mnt) | ||
2778 | { | ||
2779 | return check_mnt(mnt); | ||
2780 | } | ||