Commit f7a99c5b7c8bd3d3f533c8b38274e33f3da9096e
1 parent
d187663ef2
Exists in
master
and in
20 other branches
get rid of ->mnt_longterm
it's enough to set ->mnt_ns of internal vfsmounts to something distinct from all struct mnt_namespace out there; then we can just use the check for ->mnt_ns != NULL in the fast path of mntput_no_expire() Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Showing 5 changed files with 26 additions and 72 deletions Side-by-side Diff
fs/dcache.c
fs/fs_struct.c
... | ... | @@ -6,18 +6,6 @@ |
6 | 6 | #include <linux/fs_struct.h> |
7 | 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 | 10 | * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values. |
23 | 11 | * It can block. |
... | ... | @@ -26,7 +14,7 @@ |
26 | 14 | { |
27 | 15 | struct path old_root; |
28 | 16 | |
29 | - path_get_longterm(path); | |
17 | + path_get(path); | |
30 | 18 | spin_lock(&fs->lock); |
31 | 19 | write_seqcount_begin(&fs->seq); |
32 | 20 | old_root = fs->root; |
... | ... | @@ -34,7 +22,7 @@ |
34 | 22 | write_seqcount_end(&fs->seq); |
35 | 23 | spin_unlock(&fs->lock); |
36 | 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 @@ |
45 | 33 | { |
46 | 34 | struct path old_pwd; |
47 | 35 | |
48 | - path_get_longterm(path); | |
36 | + path_get(path); | |
49 | 37 | spin_lock(&fs->lock); |
50 | 38 | write_seqcount_begin(&fs->seq); |
51 | 39 | old_pwd = fs->pwd; |
... | ... | @@ -54,7 +42,7 @@ |
54 | 42 | spin_unlock(&fs->lock); |
55 | 43 | |
56 | 44 | if (old_pwd.dentry) |
57 | - path_put_longterm(&old_pwd); | |
45 | + path_put(&old_pwd); | |
58 | 46 | } |
59 | 47 | |
60 | 48 | static inline int replace_path(struct path *p, const struct path *old, const struct path *new) |
... | ... | @@ -84,7 +72,7 @@ |
84 | 72 | write_seqcount_end(&fs->seq); |
85 | 73 | while (hits--) { |
86 | 74 | count++; |
87 | - path_get_longterm(new_root); | |
75 | + path_get(new_root); | |
88 | 76 | } |
89 | 77 | spin_unlock(&fs->lock); |
90 | 78 | } |
91 | 79 | |
... | ... | @@ -92,13 +80,13 @@ |
92 | 80 | } while_each_thread(g, p); |
93 | 81 | read_unlock(&tasklist_lock); |
94 | 82 | while (count--) |
95 | - path_put_longterm(old_root); | |
83 | + path_put(old_root); | |
96 | 84 | } |
97 | 85 | |
98 | 86 | void free_fs_struct(struct fs_struct *fs) |
99 | 87 | { |
100 | - path_put_longterm(&fs->root); | |
101 | - path_put_longterm(&fs->pwd); | |
88 | + path_put(&fs->root); | |
89 | + path_put(&fs->pwd); | |
102 | 90 | kmem_cache_free(fs_cachep, fs); |
103 | 91 | } |
104 | 92 | |
105 | 93 | |
... | ... | @@ -132,9 +120,9 @@ |
132 | 120 | |
133 | 121 | spin_lock(&old->lock); |
134 | 122 | fs->root = old->root; |
135 | - path_get_longterm(&fs->root); | |
123 | + path_get(&fs->root); | |
136 | 124 | fs->pwd = old->pwd; |
137 | - path_get_longterm(&fs->pwd); | |
125 | + path_get(&fs->pwd); | |
138 | 126 | spin_unlock(&old->lock); |
139 | 127 | } |
140 | 128 | return fs; |
fs/internal.h
... | ... | @@ -50,8 +50,6 @@ |
50 | 50 | extern struct vfsmount *lookup_mnt(struct path *); |
51 | 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 | 53 | extern int sb_prepare_remount_readonly(struct super_block *); |
56 | 54 | |
57 | 55 | extern void __init mnt_init(void); |
fs/mount.h
... | ... | @@ -22,7 +22,6 @@ |
22 | 22 | struct vfsmount mnt; |
23 | 23 | #ifdef CONFIG_SMP |
24 | 24 | struct mnt_pcp __percpu *mnt_pcp; |
25 | - atomic_t mnt_longterm; /* how many of the refs are longterm */ | |
26 | 25 | #else |
27 | 26 | int mnt_count; |
28 | 27 | int mnt_writers; |
... | ... | @@ -49,6 +48,8 @@ |
49 | 48 | int mnt_ghosts; |
50 | 49 | }; |
51 | 50 | |
51 | +#define MNT_NS_INTERNAL ERR_PTR(-EINVAL) /* distinct from any mnt_namespace */ | |
52 | + | |
52 | 53 | static inline struct mount *real_mount(struct vfsmount *mnt) |
53 | 54 | { |
54 | 55 | return container_of(mnt, struct mount, mnt); |
... | ... | @@ -57,6 +58,12 @@ |
57 | 58 | static inline int mnt_has_parent(struct mount *mnt) |
58 | 59 | { |
59 | 60 | return mnt != mnt->mnt_parent; |
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)); | |
60 | 67 | } |
61 | 68 | |
62 | 69 | extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); |
fs/namespace.c
... | ... | @@ -621,21 +621,6 @@ |
621 | 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 | 625 | * vfsmount lock must be held for write |
641 | 626 | */ |
642 | 627 | |
... | ... | @@ -649,10 +634,8 @@ |
649 | 634 | BUG_ON(parent == mnt); |
650 | 635 | |
651 | 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 | 638 | m->mnt_ns = n; |
654 | - __mnt_make_longterm(m); | |
655 | - } | |
656 | 639 | |
657 | 640 | list_splice(&head, n->list.prev); |
658 | 641 | |
... | ... | @@ -804,7 +787,8 @@ |
804 | 787 | put_again: |
805 | 788 | #ifdef CONFIG_SMP |
806 | 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 | 792 | mnt_add_count(mnt, -1); |
809 | 793 | br_read_unlock(&vfsmount_lock); |
810 | 794 | return; |
... | ... | @@ -1074,8 +1058,6 @@ |
1074 | 1058 | list_del_init(&p->mnt_expire); |
1075 | 1059 | list_del_init(&p->mnt_list); |
1076 | 1060 | __touch_mnt_namespace(p->mnt_ns); |
1077 | - if (p->mnt_ns) | |
1078 | - __mnt_make_shortterm(p); | |
1079 | 1061 | p->mnt_ns = NULL; |
1080 | 1062 | list_del_init(&p->mnt_child); |
1081 | 1063 | if (mnt_has_parent(p)) { |
... | ... | @@ -2209,23 +2191,6 @@ |
2209 | 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 | 2195 | * Allocate a new namespace structure and populate it with contents |
2231 | 2196 | * copied from the namespace of the passed in task structure. |
2232 | 2197 | |
2233 | 2198 | |
... | ... | @@ -2265,18 +2230,13 @@ |
2265 | 2230 | q = new; |
2266 | 2231 | while (p) { |
2267 | 2232 | q->mnt_ns = new_ns; |
2268 | - __mnt_make_longterm(q); | |
2269 | 2233 | if (fs) { |
2270 | 2234 | if (&p->mnt == fs->root.mnt) { |
2271 | 2235 | fs->root.mnt = mntget(&q->mnt); |
2272 | - __mnt_make_longterm(q); | |
2273 | - mnt_make_shortterm(&p->mnt); | |
2274 | 2236 | rootmnt = &p->mnt; |
2275 | 2237 | } |
2276 | 2238 | if (&p->mnt == fs->pwd.mnt) { |
2277 | 2239 | fs->pwd.mnt = mntget(&q->mnt); |
2278 | - __mnt_make_longterm(q); | |
2279 | - mnt_make_shortterm(&p->mnt); | |
2280 | 2240 | pwdmnt = &p->mnt; |
2281 | 2241 | } |
2282 | 2242 | } |
... | ... | @@ -2320,7 +2280,6 @@ |
2320 | 2280 | if (!IS_ERR(new_ns)) { |
2321 | 2281 | struct mount *mnt = real_mount(m); |
2322 | 2282 | mnt->mnt_ns = new_ns; |
2323 | - __mnt_make_longterm(mnt); | |
2324 | 2283 | new_ns->root = mnt; |
2325 | 2284 | list_add(&new_ns->list, &mnt->mnt_list); |
2326 | 2285 | } else { |
... | ... | @@ -2615,7 +2574,7 @@ |
2615 | 2574 | * it is a longterm mount, don't release mnt until |
2616 | 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 | 2579 | return mnt; |
2621 | 2580 | } |
... | ... | @@ -2625,7 +2584,9 @@ |
2625 | 2584 | { |
2626 | 2585 | /* release long term mount so mount point can be released */ |
2627 | 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 | 2590 | mntput(mnt); |
2630 | 2591 | } |
2631 | 2592 | } |