aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-06-09 00:59:08 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-07-14 08:32:47 -0400
commitf7a99c5b7c8bd3d3f533c8b38274e33f3da9096e (patch)
tree5c326c0ddd1f40eacbe2fd7c888f26b089389f99
parentd187663ef24cd3d033f0cbf2867e70b36a3a90b8 (diff)
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>
-rw-r--r--fs/dcache.c2
-rw-r--r--fs/fs_struct.c32
-rw-r--r--fs/internal.h2
-rw-r--r--fs/mount.h9
-rw-r--r--fs/namespace.c53
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
9static inline void path_get_longterm(struct path *path)
10{
11 path_get(path);
12 mnt_make_longterm(path->mnt);
13}
14
15static 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
60static inline int replace_path(struct path *p, const struct path *old, const struct path *new) 48static 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
98void free_fs_struct(struct fs_struct *fs) 86void 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 **);
50extern struct vfsmount *lookup_mnt(struct path *); 50extern struct vfsmount *lookup_mnt(struct path *);
51extern int finish_automount(struct vfsmount *, struct path *); 51extern int finish_automount(struct vfsmount *, struct path *);
52 52
53extern void mnt_make_longterm(struct vfsmount *);
54extern void mnt_make_shortterm(struct vfsmount *);
55extern int sb_prepare_remount_readonly(struct super_block *); 53extern int sb_prepare_remount_readonly(struct super_block *);
56 54
57extern void __init mnt_init(void); 55extern 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
52static inline struct mount *real_mount(struct vfsmount *mnt) 53static 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
63static inline int is_mounted(struct vfsmount *mnt)
64{
65 /* neither detached nor internal? */
66 return !IS_ERR_OR_NULL(real_mount(mnt));
67}
68
62extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int); 69extern struct mount *__lookup_mnt(struct vfsmount *, struct dentry *, int);
63 70
64static inline void get_mnt_ns(struct mnt_namespace *ns) 71static 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
624static 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 */
632static 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)
804put_again: 787put_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
2212void mnt_make_longterm(struct vfsmount *mnt)
2213{
2214 __mnt_make_longterm(real_mount(mnt));
2215}
2216
2217void 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}