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); | 
