diff options
-rw-r--r-- | fs/dcache.c | 2 | ||||
-rw-r--r-- | fs/fs_struct.c | 32 | ||||
-rw-r--r-- | fs/internal.h | 2 | ||||
-rw-r--r-- | fs/mount.h | 9 | ||||
-rw-r--r-- | fs/namespace.c | 53 |
5 files changed, 26 insertions, 72 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 40469044088d..44acb5b29ae4 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -2622,7 +2622,7 @@ global_root: | |||
2622 | if (!slash) | 2622 | if (!slash) |
2623 | error = prepend(buffer, buflen, "/", 1); | 2623 | error = prepend(buffer, buflen, "/", 1); |
2624 | if (!error) | 2624 | if (!error) |
2625 | error = real_mount(vfsmnt)->mnt_ns ? 1 : 2; | 2625 | error = is_mounted(vfsmnt) ? 1 : 2; |
2626 | goto out; | 2626 | goto out; |
2627 | } | 2627 | } |
2628 | 2628 | ||
diff --git a/fs/fs_struct.c b/fs/fs_struct.c index e159e682ad4c..5df4775fea03 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c | |||
@@ -6,18 +6,6 @@ | |||
6 | #include <linux/fs_struct.h> | 6 | #include <linux/fs_struct.h> |
7 | #include "internal.h" | 7 | #include "internal.h" |
8 | 8 | ||
9 | static inline void path_get_longterm(struct path *path) | ||
10 | { | ||
11 | path_get(path); | ||
12 | mnt_make_longterm(path->mnt); | ||
13 | } | ||
14 | |||
15 | static inline void path_put_longterm(struct path *path) | ||
16 | { | ||
17 | mnt_make_shortterm(path->mnt); | ||
18 | path_put(path); | ||
19 | } | ||
20 | |||
21 | /* | 9 | /* |
22 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. | 10 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. |
23 | * It can block. | 11 | * It can block. |
@@ -26,7 +14,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path) | |||
26 | { | 14 | { |
27 | struct path old_root; | 15 | struct path old_root; |
28 | 16 | ||
29 | path_get_longterm(path); | 17 | path_get(path); |
30 | spin_lock(&fs->lock); | 18 | spin_lock(&fs->lock); |
31 | write_seqcount_begin(&fs->seq); | 19 | write_seqcount_begin(&fs->seq); |
32 | old_root = fs->root; | 20 | old_root = fs->root; |
@@ -34,7 +22,7 @@ void set_fs_root(struct fs_struct *fs, struct path *path) | |||
34 | write_seqcount_end(&fs->seq); | 22 | write_seqcount_end(&fs->seq); |
35 | spin_unlock(&fs->lock); | 23 | spin_unlock(&fs->lock); |
36 | if (old_root.dentry) | 24 | if (old_root.dentry) |
37 | path_put_longterm(&old_root); | 25 | path_put(&old_root); |
38 | } | 26 | } |
39 | 27 | ||
40 | /* | 28 | /* |
@@ -45,7 +33,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
45 | { | 33 | { |
46 | struct path old_pwd; | 34 | struct path old_pwd; |
47 | 35 | ||
48 | path_get_longterm(path); | 36 | path_get(path); |
49 | spin_lock(&fs->lock); | 37 | spin_lock(&fs->lock); |
50 | write_seqcount_begin(&fs->seq); | 38 | write_seqcount_begin(&fs->seq); |
51 | old_pwd = fs->pwd; | 39 | old_pwd = fs->pwd; |
@@ -54,7 +42,7 @@ void set_fs_pwd(struct fs_struct *fs, struct path *path) | |||
54 | spin_unlock(&fs->lock); | 42 | spin_unlock(&fs->lock); |
55 | 43 | ||
56 | if (old_pwd.dentry) | 44 | if (old_pwd.dentry) |
57 | path_put_longterm(&old_pwd); | 45 | path_put(&old_pwd); |
58 | } | 46 | } |
59 | 47 | ||
60 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) | 48 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) |
@@ -84,7 +72,7 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) | |||
84 | write_seqcount_end(&fs->seq); | 72 | write_seqcount_end(&fs->seq); |
85 | while (hits--) { | 73 | while (hits--) { |
86 | count++; | 74 | count++; |
87 | path_get_longterm(new_root); | 75 | path_get(new_root); |
88 | } | 76 | } |
89 | spin_unlock(&fs->lock); | 77 | spin_unlock(&fs->lock); |
90 | } | 78 | } |
@@ -92,13 +80,13 @@ void chroot_fs_refs(struct path *old_root, struct path *new_root) | |||
92 | } while_each_thread(g, p); | 80 | } while_each_thread(g, p); |
93 | read_unlock(&tasklist_lock); | 81 | read_unlock(&tasklist_lock); |
94 | while (count--) | 82 | while (count--) |
95 | path_put_longterm(old_root); | 83 | path_put(old_root); |
96 | } | 84 | } |
97 | 85 | ||
98 | void free_fs_struct(struct fs_struct *fs) | 86 | void free_fs_struct(struct fs_struct *fs) |
99 | { | 87 | { |
100 | path_put_longterm(&fs->root); | 88 | path_put(&fs->root); |
101 | path_put_longterm(&fs->pwd); | 89 | path_put(&fs->pwd); |
102 | kmem_cache_free(fs_cachep, fs); | 90 | kmem_cache_free(fs_cachep, fs); |
103 | } | 91 | } |
104 | 92 | ||
@@ -132,9 +120,9 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) | |||
132 | 120 | ||
133 | spin_lock(&old->lock); | 121 | spin_lock(&old->lock); |
134 | fs->root = old->root; | 122 | fs->root = old->root; |
135 | path_get_longterm(&fs->root); | 123 | path_get(&fs->root); |
136 | fs->pwd = old->pwd; | 124 | fs->pwd = old->pwd; |
137 | path_get_longterm(&fs->pwd); | 125 | path_get(&fs->pwd); |
138 | spin_unlock(&old->lock); | 126 | spin_unlock(&old->lock); |
139 | } | 127 | } |
140 | return fs; | 128 | return fs; |
diff --git a/fs/internal.h b/fs/internal.h index 18bc216ea09d..d2a23ff61b40 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -50,8 +50,6 @@ extern int copy_mount_string(const void __user *, char **); | |||
50 | extern struct vfsmount *lookup_mnt(struct path *); | 50 | extern struct vfsmount *lookup_mnt(struct path *); |
51 | extern int finish_automount(struct vfsmount *, struct path *); | 51 | extern int finish_automount(struct vfsmount *, struct path *); |
52 | 52 | ||
53 | extern void mnt_make_longterm(struct vfsmount *); | ||
54 | extern void mnt_make_shortterm(struct vfsmount *); | ||
55 | extern int sb_prepare_remount_readonly(struct super_block *); | 53 | extern int sb_prepare_remount_readonly(struct super_block *); |
56 | 54 | ||
57 | extern void __init mnt_init(void); | 55 | extern void __init mnt_init(void); |
diff --git a/fs/mount.h b/fs/mount.h index 4ef36d93e5a2..05a2a1185efc 100644 --- a/fs/mount.h +++ b/fs/mount.h | |||
@@ -22,7 +22,6 @@ struct mount { | |||
22 | struct vfsmount mnt; | 22 | struct vfsmount mnt; |
23 | #ifdef CONFIG_SMP | 23 | #ifdef CONFIG_SMP |
24 | struct mnt_pcp __percpu *mnt_pcp; | 24 | struct mnt_pcp __percpu *mnt_pcp; |
25 | atomic_t mnt_longterm; /* how many of the refs are longterm */ | ||
26 | #else | 25 | #else |
27 | int mnt_count; | 26 | int mnt_count; |
28 | int mnt_writers; | 27 | int mnt_writers; |
@@ -49,6 +48,8 @@ struct mount { | |||
49 | int mnt_ghosts; | 48 | int mnt_ghosts; |
50 | }; | 49 | }; |
51 | 50 | ||
51 | #define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ | ||
52 | |||
52 | static inline struct mount *real_mount(struct vfsmount *mnt) | 53 | static inline struct mount *real_mount(struct vfsmount *mnt) |
53 | { | 54 | { |
54 | return container_of(mnt, struct mount, mnt); | 55 | return container_of(mnt, struct mount, mnt); |
@@ -59,6 +60,12 @@ static inline int mnt_has_parent(struct mount *mnt) | |||
59 | return mnt != mnt->mnt_parent; | 60 | return mnt != mnt->mnt_parent; |
60 | } | 61 | } |
61 | 62 | ||
63 | static inline int is_mounted(struct vfsmount *mnt) | ||
64 | { | ||
65 | /* neither detached nor internal? */ | ||
66 | return !IS_ERR_OR_NULL(real_mount(mnt)); | ||
67 | } | ||
68 | |||
62 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); | 69 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); |
63 | 70 | ||
64 | static inline void get_mnt_ns(struct mnt_namespace *ns) | 71 | static inline void get_mnt_ns(struct mnt_namespace *ns) |
diff --git a/fs/namespace.c b/fs/namespace.c index 1e4a5fe3d7b7..a524ea4dbd80 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -621,21 +621,6 @@ static void attach_mnt(struct mount *mnt, struct path *path) | |||
621 | list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); | 621 | list_add_tail(&mnt->mnt_child, &real_mount(path->mnt)->mnt_mounts); |
622 | } | 622 | } |
623 | 623 | ||
624 | static inline void __mnt_make_longterm(struct mount *mnt) | ||
625 | { | ||
626 | #ifdef CONFIG_SMP | ||
627 | atomic_inc(&mnt->mnt_longterm); | ||
628 | #endif | ||
629 | } | ||
630 | |||
631 | /* needs vfsmount lock for write */ | ||
632 | static inline void __mnt_make_shortterm(struct mount *mnt) | ||
633 | { | ||
634 | #ifdef CONFIG_SMP | ||
635 | atomic_dec(&mnt->mnt_longterm); | ||
636 | #endif | ||
637 | } | ||
638 | |||
639 | /* | 624 | /* |
640 | * vfsmount lock must be held for write | 625 | * vfsmount lock must be held for write |
641 | */ | 626 | */ |
@@ -649,10 +634,8 @@ static void commit_tree(struct mount *mnt) | |||
649 | BUG_ON(parent == mnt); | 634 | BUG_ON(parent == mnt); |
650 | 635 | ||
651 | list_add_tail(&head, &mnt->mnt_list); | 636 | list_add_tail(&head, &mnt->mnt_list); |
652 | list_for_each_entry(m, &head, mnt_list) { | 637 | list_for_each_entry(m, &head, mnt_list) |
653 | m->mnt_ns = n; | 638 | m->mnt_ns = n; |
654 | __mnt_make_longterm(m); | ||
655 | } | ||
656 | 639 | ||
657 | list_splice(&head, n->list.prev); | 640 | list_splice(&head, n->list.prev); |
658 | 641 | ||
@@ -804,7 +787,8 @@ static void mntput_no_expire(struct mount *mnt) | |||
804 | put_again: | 787 | put_again: |
805 | #ifdef CONFIG_SMP | 788 | #ifdef CONFIG_SMP |
806 | br_read_lock(&vfsmount_lock); | 789 | br_read_lock(&vfsmount_lock); |
807 | if (likely(atomic_read(&mnt->mnt_longterm))) { | 790 | if (likely(mnt->mnt_ns)) { |
791 | /* shouldn't be the last one */ | ||
808 | mnt_add_count(mnt, -1); | 792 | mnt_add_count(mnt, -1); |
809 | br_read_unlock(&vfsmount_lock); | 793 | br_read_unlock(&vfsmount_lock); |
810 | return; | 794 | return; |
@@ -1074,8 +1058,6 @@ void umount_tree(struct mount *mnt, int propagate, struct list_head *kill) | |||
1074 | list_del_init(&p->mnt_expire); | 1058 | list_del_init(&p->mnt_expire); |
1075 | list_del_init(&p->mnt_list); | 1059 | list_del_init(&p->mnt_list); |
1076 | __touch_mnt_namespace(p->mnt_ns); | 1060 | __touch_mnt_namespace(p->mnt_ns); |
1077 | if (p->mnt_ns) | ||
1078 | __mnt_make_shortterm(p); | ||
1079 | p->mnt_ns = NULL; | 1061 | p->mnt_ns = NULL; |
1080 | list_del_init(&p->mnt_child); | 1062 | list_del_init(&p->mnt_child); |
1081 | if (mnt_has_parent(p)) { | 1063 | if (mnt_has_parent(p)) { |
@@ -2209,23 +2191,6 @@ static struct mnt_namespace *alloc_mnt_ns(void) | |||
2209 | return new_ns; | 2191 | return new_ns; |
2210 | } | 2192 | } |
2211 | 2193 | ||
2212 | void mnt_make_longterm(struct vfsmount *mnt) | ||
2213 | { | ||
2214 | __mnt_make_longterm(real_mount(mnt)); | ||
2215 | } | ||
2216 | |||
2217 | void mnt_make_shortterm(struct vfsmount *m) | ||
2218 | { | ||
2219 | #ifdef CONFIG_SMP | ||
2220 | struct mount *mnt = real_mount(m); | ||
2221 | if (atomic_add_unless(&mnt->mnt_longterm, -1, 1)) | ||
2222 | return; | ||
2223 | br_write_lock(&vfsmount_lock); | ||
2224 | atomic_dec(&mnt->mnt_longterm); | ||
2225 | br_write_unlock(&vfsmount_lock); | ||
2226 | #endif | ||
2227 | } | ||
2228 | |||
2229 | /* | 2194 | /* |
2230 | * Allocate a new namespace structure and populate it with contents | 2195 | * Allocate a new namespace structure and populate it with contents |
2231 | * copied from the namespace of the passed in task structure. | 2196 | * copied from the namespace of the passed in task structure. |
@@ -2265,18 +2230,13 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
2265 | q = new; | 2230 | q = new; |
2266 | while (p) { | 2231 | while (p) { |
2267 | q->mnt_ns = new_ns; | 2232 | q->mnt_ns = new_ns; |
2268 | __mnt_make_longterm(q); | ||
2269 | if (fs) { | 2233 | if (fs) { |
2270 | if (&p->mnt == fs->root.mnt) { | 2234 | if (&p->mnt == fs->root.mnt) { |
2271 | fs->root.mnt = mntget(&q->mnt); | 2235 | fs->root.mnt = mntget(&q->mnt); |
2272 | __mnt_make_longterm(q); | ||
2273 | mnt_make_shortterm(&p->mnt); | ||
2274 | rootmnt = &p->mnt; | 2236 | rootmnt = &p->mnt; |
2275 | } | 2237 | } |
2276 | if (&p->mnt == fs->pwd.mnt) { | 2238 | if (&p->mnt == fs->pwd.mnt) { |
2277 | fs->pwd.mnt = mntget(&q->mnt); | 2239 | fs->pwd.mnt = mntget(&q->mnt); |
2278 | __mnt_make_longterm(q); | ||
2279 | mnt_make_shortterm(&p->mnt); | ||
2280 | pwdmnt = &p->mnt; | 2240 | pwdmnt = &p->mnt; |
2281 | } | 2241 | } |
2282 | } | 2242 | } |
@@ -2320,7 +2280,6 @@ static struct mnt_namespace *create_mnt_ns(struct vfsmount *m) | |||
2320 | if (!IS_ERR(new_ns)) { | 2280 | if (!IS_ERR(new_ns)) { |
2321 | struct mount *mnt = real_mount(m); | 2281 | struct mount *mnt = real_mount(m); |
2322 | mnt->mnt_ns = new_ns; | 2282 | mnt->mnt_ns = new_ns; |
2323 | __mnt_make_longterm(mnt); | ||
2324 | new_ns->root = mnt; | 2283 | new_ns->root = mnt; |
2325 | list_add(&new_ns->list, &mnt->mnt_list); | 2284 | list_add(&new_ns->list, &mnt->mnt_list); |
2326 | } else { | 2285 | } else { |
@@ -2615,7 +2574,7 @@ struct vfsmount *kern_mount_data(struct file_system_type *type, void *data) | |||
2615 | * it is a longterm mount, don't release mnt until | 2574 | * it is a longterm mount, don't release mnt until |
2616 | * we unmount before file sys is unregistered | 2575 | * we unmount before file sys is unregistered |
2617 | */ | 2576 | */ |
2618 | mnt_make_longterm(mnt); | 2577 | real_mount(mnt)->mnt_ns = MNT_NS_INTERNAL; |
2619 | } | 2578 | } |
2620 | return mnt; | 2579 | return mnt; |
2621 | } | 2580 | } |
@@ -2625,7 +2584,9 @@ void kern_unmount(struct vfsmount *mnt) | |||
2625 | { | 2584 | { |
2626 | /* release long term mount so mount point can be released */ | 2585 | /* release long term mount so mount point can be released */ |
2627 | if (!IS_ERR_OR_NULL(mnt)) { | 2586 | if (!IS_ERR_OR_NULL(mnt)) { |
2628 | mnt_make_shortterm(mnt); | 2587 | br_write_lock(&vfsmount_lock); |
2588 | real_mount(mnt)->mnt_ns = NULL; | ||
2589 | br_write_unlock(&vfsmount_lock); | ||
2629 | mntput(mnt); | 2590 | mntput(mnt); |
2630 | } | 2591 | } |
2631 | } | 2592 | } |