diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 53 |
1 files changed, 43 insertions, 10 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index c768f733c8d6..8174c8ab5c70 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -573,7 +573,7 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, | |||
573 | mnt->mnt_master = old; | 573 | mnt->mnt_master = old; |
574 | CLEAR_MNT_SHARED(mnt); | 574 | CLEAR_MNT_SHARED(mnt); |
575 | } else if (!(flag & CL_PRIVATE)) { | 575 | } else if (!(flag & CL_PRIVATE)) { |
576 | if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) | 576 | if ((flag & CL_MAKE_SHARED) || IS_MNT_SHARED(old)) |
577 | list_add(&mnt->mnt_share, &old->mnt_share); | 577 | list_add(&mnt->mnt_share, &old->mnt_share); |
578 | if (IS_MNT_SLAVE(old)) | 578 | if (IS_MNT_SLAVE(old)) |
579 | list_add(&mnt->mnt_slave, &old->mnt_slave); | 579 | list_add(&mnt->mnt_slave, &old->mnt_slave); |
@@ -737,6 +737,21 @@ static void m_stop(struct seq_file *m, void *v) | |||
737 | up_read(&namespace_sem); | 737 | up_read(&namespace_sem); |
738 | } | 738 | } |
739 | 739 | ||
740 | int mnt_had_events(struct proc_mounts *p) | ||
741 | { | ||
742 | struct mnt_namespace *ns = p->ns; | ||
743 | int res = 0; | ||
744 | |||
745 | spin_lock(&vfsmount_lock); | ||
746 | if (p->event != ns->event) { | ||
747 | p->event = ns->event; | ||
748 | res = 1; | ||
749 | } | ||
750 | spin_unlock(&vfsmount_lock); | ||
751 | |||
752 | return res; | ||
753 | } | ||
754 | |||
740 | struct proc_fs_info { | 755 | struct proc_fs_info { |
741 | int flag; | 756 | int flag; |
742 | const char *str; | 757 | const char *str; |
@@ -1121,8 +1136,15 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) | |||
1121 | { | 1136 | { |
1122 | struct path path; | 1137 | struct path path; |
1123 | int retval; | 1138 | int retval; |
1139 | int lookup_flags = 0; | ||
1124 | 1140 | ||
1125 | retval = user_path(name, &path); | 1141 | if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) |
1142 | return -EINVAL; | ||
1143 | |||
1144 | if (!(flags & UMOUNT_NOFOLLOW)) | ||
1145 | lookup_flags |= LOOKUP_FOLLOW; | ||
1146 | |||
1147 | retval = user_path_at(AT_FDCWD, name, lookup_flags, &path); | ||
1126 | if (retval) | 1148 | if (retval) |
1127 | goto out; | 1149 | goto out; |
1128 | retval = -EINVAL; | 1150 | retval = -EINVAL; |
@@ -1246,6 +1268,21 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
1246 | release_mounts(&umount_list); | 1268 | release_mounts(&umount_list); |
1247 | } | 1269 | } |
1248 | 1270 | ||
1271 | int iterate_mounts(int (*f)(struct vfsmount *, void *), void *arg, | ||
1272 | struct vfsmount *root) | ||
1273 | { | ||
1274 | struct vfsmount *mnt; | ||
1275 | int res = f(root, arg); | ||
1276 | if (res) | ||
1277 | return res; | ||
1278 | list_for_each_entry(mnt, &root->mnt_list, mnt_list) { | ||
1279 | res = f(mnt, arg); | ||
1280 | if (res) | ||
1281 | return res; | ||
1282 | } | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1249 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) | 1286 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) |
1250 | { | 1287 | { |
1251 | struct vfsmount *p; | 1288 | struct vfsmount *p; |
@@ -1538,7 +1575,7 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1538 | err = do_remount_sb(sb, flags, data, 0); | 1575 | err = do_remount_sb(sb, flags, data, 0); |
1539 | if (!err) { | 1576 | if (!err) { |
1540 | spin_lock(&vfsmount_lock); | 1577 | spin_lock(&vfsmount_lock); |
1541 | mnt_flags |= path->mnt->mnt_flags & MNT_PNODE_MASK; | 1578 | mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK; |
1542 | path->mnt->mnt_flags = mnt_flags; | 1579 | path->mnt->mnt_flags = mnt_flags; |
1543 | spin_unlock(&vfsmount_lock); | 1580 | spin_unlock(&vfsmount_lock); |
1544 | } | 1581 | } |
@@ -1671,7 +1708,7 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
1671 | { | 1708 | { |
1672 | int err; | 1709 | int err; |
1673 | 1710 | ||
1674 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD); | 1711 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); |
1675 | 1712 | ||
1676 | down_write(&namespace_sem); | 1713 | down_write(&namespace_sem); |
1677 | /* Something was mounted here while we slept */ | 1714 | /* Something was mounted here while we slept */ |
@@ -2314,17 +2351,13 @@ void __init mnt_init(void) | |||
2314 | 2351 | ||
2315 | void put_mnt_ns(struct mnt_namespace *ns) | 2352 | void put_mnt_ns(struct mnt_namespace *ns) |
2316 | { | 2353 | { |
2317 | struct vfsmount *root; | ||
2318 | LIST_HEAD(umount_list); | 2354 | LIST_HEAD(umount_list); |
2319 | 2355 | ||
2320 | if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock)) | 2356 | if (!atomic_dec_and_test(&ns->count)) |
2321 | return; | 2357 | return; |
2322 | root = ns->root; | ||
2323 | ns->root = NULL; | ||
2324 | spin_unlock(&vfsmount_lock); | ||
2325 | down_write(&namespace_sem); | 2358 | down_write(&namespace_sem); |
2326 | spin_lock(&vfsmount_lock); | 2359 | spin_lock(&vfsmount_lock); |
2327 | umount_tree(root, 0, &umount_list); | 2360 | umount_tree(ns->root, 0, &umount_list); |
2328 | spin_unlock(&vfsmount_lock); | 2361 | spin_unlock(&vfsmount_lock); |
2329 | up_write(&namespace_sem); | 2362 | up_write(&namespace_sem); |
2330 | release_mounts(&umount_list); | 2363 | release_mounts(&umount_list); |