diff options
Diffstat (limited to 'fs/namespace.c')
-rw-r--r-- | fs/namespace.c | 83 |
1 files changed, 62 insertions, 21 deletions
diff --git a/fs/namespace.c b/fs/namespace.c index bdc3cb4fd222..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; |
@@ -965,10 +980,12 @@ EXPORT_SYMBOL(may_umount_tree); | |||
965 | int may_umount(struct vfsmount *mnt) | 980 | int may_umount(struct vfsmount *mnt) |
966 | { | 981 | { |
967 | int ret = 1; | 982 | int ret = 1; |
983 | down_read(&namespace_sem); | ||
968 | spin_lock(&vfsmount_lock); | 984 | spin_lock(&vfsmount_lock); |
969 | if (propagate_mount_busy(mnt, 2)) | 985 | if (propagate_mount_busy(mnt, 2)) |
970 | ret = 0; | 986 | ret = 0; |
971 | spin_unlock(&vfsmount_lock); | 987 | spin_unlock(&vfsmount_lock); |
988 | up_read(&namespace_sem); | ||
972 | return ret; | 989 | return ret; |
973 | } | 990 | } |
974 | 991 | ||
@@ -1119,8 +1136,15 @@ SYSCALL_DEFINE2(umount, char __user *, name, int, flags) | |||
1119 | { | 1136 | { |
1120 | struct path path; | 1137 | struct path path; |
1121 | int retval; | 1138 | int retval; |
1139 | int lookup_flags = 0; | ||
1140 | |||
1141 | if (flags & ~(MNT_FORCE | MNT_DETACH | MNT_EXPIRE | UMOUNT_NOFOLLOW)) | ||
1142 | return -EINVAL; | ||
1122 | 1143 | ||
1123 | retval = user_path(name, &path); | 1144 | if (!(flags & UMOUNT_NOFOLLOW)) |
1145 | lookup_flags |= LOOKUP_FOLLOW; | ||
1146 | |||
1147 | retval = user_path_at(AT_FDCWD, name, lookup_flags, &path); | ||
1124 | if (retval) | 1148 | if (retval) |
1125 | goto out; | 1149 | goto out; |
1126 | retval = -EINVAL; | 1150 | retval = -EINVAL; |
@@ -1244,6 +1268,21 @@ void drop_collected_mounts(struct vfsmount *mnt) | |||
1244 | release_mounts(&umount_list); | 1268 | release_mounts(&umount_list); |
1245 | } | 1269 | } |
1246 | 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 | |||
1247 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) | 1286 | static void cleanup_group_ids(struct vfsmount *mnt, struct vfsmount *end) |
1248 | { | 1287 | { |
1249 | struct vfsmount *p; | 1288 | struct vfsmount *p; |
@@ -1352,12 +1391,12 @@ static int attach_recursive_mnt(struct vfsmount *source_mnt, | |||
1352 | if (err) | 1391 | if (err) |
1353 | goto out_cleanup_ids; | 1392 | goto out_cleanup_ids; |
1354 | 1393 | ||
1394 | spin_lock(&vfsmount_lock); | ||
1395 | |||
1355 | if (IS_MNT_SHARED(dest_mnt)) { | 1396 | if (IS_MNT_SHARED(dest_mnt)) { |
1356 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) | 1397 | for (p = source_mnt; p; p = next_mnt(p, source_mnt)) |
1357 | set_mnt_shared(p); | 1398 | set_mnt_shared(p); |
1358 | } | 1399 | } |
1359 | |||
1360 | spin_lock(&vfsmount_lock); | ||
1361 | if (parent_path) { | 1400 | if (parent_path) { |
1362 | detach_mnt(source_mnt, parent_path); | 1401 | detach_mnt(source_mnt, parent_path); |
1363 | attach_mnt(source_mnt, path); | 1402 | attach_mnt(source_mnt, path); |
@@ -1534,8 +1573,12 @@ static int do_remount(struct path *path, int flags, int mnt_flags, | |||
1534 | err = change_mount_flags(path->mnt, flags); | 1573 | err = change_mount_flags(path->mnt, flags); |
1535 | else | 1574 | else |
1536 | err = do_remount_sb(sb, flags, data, 0); | 1575 | err = do_remount_sb(sb, flags, data, 0); |
1537 | if (!err) | 1576 | if (!err) { |
1577 | spin_lock(&vfsmount_lock); | ||
1578 | mnt_flags |= path->mnt->mnt_flags & MNT_PROPAGATION_MASK; | ||
1538 | path->mnt->mnt_flags = mnt_flags; | 1579 | path->mnt->mnt_flags = mnt_flags; |
1580 | spin_unlock(&vfsmount_lock); | ||
1581 | } | ||
1539 | up_write(&sb->s_umount); | 1582 | up_write(&sb->s_umount); |
1540 | if (!err) { | 1583 | if (!err) { |
1541 | security_sb_post_remount(path->mnt, flags, data); | 1584 | security_sb_post_remount(path->mnt, flags, data); |
@@ -1665,6 +1708,8 @@ int do_add_mount(struct vfsmount *newmnt, struct path *path, | |||
1665 | { | 1708 | { |
1666 | int err; | 1709 | int err; |
1667 | 1710 | ||
1711 | mnt_flags &= ~(MNT_SHARED | MNT_WRITE_HOLD | MNT_INTERNAL); | ||
1712 | |||
1668 | down_write(&namespace_sem); | 1713 | down_write(&namespace_sem); |
1669 | /* Something was mounted here while we slept */ | 1714 | /* Something was mounted here while we slept */ |
1670 | while (d_mountpoint(path->dentry) && | 1715 | while (d_mountpoint(path->dentry) && |
@@ -1921,6 +1966,16 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1921 | if (data_page) | 1966 | if (data_page) |
1922 | ((char *)data_page)[PAGE_SIZE - 1] = 0; | 1967 | ((char *)data_page)[PAGE_SIZE - 1] = 0; |
1923 | 1968 | ||
1969 | /* ... and get the mountpoint */ | ||
1970 | retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); | ||
1971 | if (retval) | ||
1972 | return retval; | ||
1973 | |||
1974 | retval = security_sb_mount(dev_name, &path, | ||
1975 | type_page, flags, data_page); | ||
1976 | if (retval) | ||
1977 | goto dput_out; | ||
1978 | |||
1924 | /* Default to relatime unless overriden */ | 1979 | /* Default to relatime unless overriden */ |
1925 | if (!(flags & MS_NOATIME)) | 1980 | if (!(flags & MS_NOATIME)) |
1926 | mnt_flags |= MNT_RELATIME; | 1981 | mnt_flags |= MNT_RELATIME; |
@@ -1945,16 +2000,6 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, | |||
1945 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | | 2000 | MS_NOATIME | MS_NODIRATIME | MS_RELATIME| MS_KERNMOUNT | |
1946 | MS_STRICTATIME); | 2001 | MS_STRICTATIME); |
1947 | 2002 | ||
1948 | /* ... and get the mountpoint */ | ||
1949 | retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); | ||
1950 | if (retval) | ||
1951 | return retval; | ||
1952 | |||
1953 | retval = security_sb_mount(dev_name, &path, | ||
1954 | type_page, flags, data_page); | ||
1955 | if (retval) | ||
1956 | goto dput_out; | ||
1957 | |||
1958 | if (flags & MS_REMOUNT) | 2003 | if (flags & MS_REMOUNT) |
1959 | retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, | 2004 | retval = do_remount(&path, flags & ~MS_REMOUNT, mnt_flags, |
1960 | data_page); | 2005 | data_page); |
@@ -2306,17 +2351,13 @@ void __init mnt_init(void) | |||
2306 | 2351 | ||
2307 | void put_mnt_ns(struct mnt_namespace *ns) | 2352 | void put_mnt_ns(struct mnt_namespace *ns) |
2308 | { | 2353 | { |
2309 | struct vfsmount *root; | ||
2310 | LIST_HEAD(umount_list); | 2354 | LIST_HEAD(umount_list); |
2311 | 2355 | ||
2312 | if (!atomic_dec_and_lock(&ns->count, &vfsmount_lock)) | 2356 | if (!atomic_dec_and_test(&ns->count)) |
2313 | return; | 2357 | return; |
2314 | root = ns->root; | ||
2315 | ns->root = NULL; | ||
2316 | spin_unlock(&vfsmount_lock); | ||
2317 | down_write(&namespace_sem); | 2358 | down_write(&namespace_sem); |
2318 | spin_lock(&vfsmount_lock); | 2359 | spin_lock(&vfsmount_lock); |
2319 | umount_tree(root, 0, &umount_list); | 2360 | umount_tree(ns->root, 0, &umount_list); |
2320 | spin_unlock(&vfsmount_lock); | 2361 | spin_unlock(&vfsmount_lock); |
2321 | up_write(&namespace_sem); | 2362 | up_write(&namespace_sem); |
2322 | release_mounts(&umount_list); | 2363 | release_mounts(&umount_list); |