diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2018-04-10 19:32:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-04-11 13:28:34 -0400 |
commit | 4f1134370a29a5f2d0f4b4be4c5e2fddd38f0f9d (patch) | |
tree | 0fcae1f568cf1c2870f615e214f3e92a77afcd30 | |
parent | 05c3f29283af9e3da0ab7414f666cb37f530950a (diff) |
proc: use slower rb_first()
In a typical for /proc "open+read+close" usecase, dentry is looked up
successfully on open only to be killed in dput() on close. In fact
dentries which aren't /proc/*/... and /proc/sys/* were almost NEVER
CACHED. Simple printk in proc_lookup_de() shows that.
Now that ->delete hook intelligently picks which dentries should live in
dcache and which should not, rbtree caching is not necessary as dcache
does it job, at last!
As a side effect, struct proc_dir_entry shrinks by one pointer which can
go into inline name.
Link: http://lkml.kernel.org/r/20180314231032.GA15854@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Acked-by: Davidlohr Bueso <dbueso@suse.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | fs/proc/generic.c | 26 | ||||
-rw-r--r-- | fs/proc/internal.h | 6 | ||||
-rw-r--r-- | fs/proc/proc_net.c | 2 | ||||
-rw-r--r-- | fs/proc/root.c | 2 |
4 files changed, 17 insertions, 19 deletions
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index fc0333fd5676..04c4804cbdef 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
@@ -52,8 +52,8 @@ static int proc_match(const char *name, struct proc_dir_entry *de, unsigned int | |||
52 | 52 | ||
53 | static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir) | 53 | static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir) |
54 | { | 54 | { |
55 | return rb_entry_safe(rb_first_cached(&dir->subdir), | 55 | return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry, |
56 | struct proc_dir_entry, subdir_node); | 56 | subdir_node); |
57 | } | 57 | } |
58 | 58 | ||
59 | static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir) | 59 | static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir) |
@@ -66,7 +66,7 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir, | |||
66 | const char *name, | 66 | const char *name, |
67 | unsigned int len) | 67 | unsigned int len) |
68 | { | 68 | { |
69 | struct rb_node *node = dir->subdir.rb_root.rb_node; | 69 | struct rb_node *node = dir->subdir.rb_node; |
70 | 70 | ||
71 | while (node) { | 71 | while (node) { |
72 | struct proc_dir_entry *de = rb_entry(node, | 72 | struct proc_dir_entry *de = rb_entry(node, |
@@ -87,9 +87,8 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir, | |||
87 | static bool pde_subdir_insert(struct proc_dir_entry *dir, | 87 | static bool pde_subdir_insert(struct proc_dir_entry *dir, |
88 | struct proc_dir_entry *de) | 88 | struct proc_dir_entry *de) |
89 | { | 89 | { |
90 | struct rb_root_cached *root = &dir->subdir; | 90 | struct rb_root *root = &dir->subdir; |
91 | struct rb_node **new = &root->rb_root.rb_node, *parent = NULL; | 91 | struct rb_node **new = &root->rb_node, *parent = NULL; |
92 | bool leftmost = true; | ||
93 | 92 | ||
94 | /* Figure out where to put new node */ | 93 | /* Figure out where to put new node */ |
95 | while (*new) { | 94 | while (*new) { |
@@ -101,16 +100,15 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir, | |||
101 | parent = *new; | 100 | parent = *new; |
102 | if (result < 0) | 101 | if (result < 0) |
103 | new = &(*new)->rb_left; | 102 | new = &(*new)->rb_left; |
104 | else if (result > 0) { | 103 | else if (result > 0) |
105 | new = &(*new)->rb_right; | 104 | new = &(*new)->rb_right; |
106 | leftmost = false; | 105 | else |
107 | } else | ||
108 | return false; | 106 | return false; |
109 | } | 107 | } |
110 | 108 | ||
111 | /* Add new node and rebalance tree. */ | 109 | /* Add new node and rebalance tree. */ |
112 | rb_link_node(&de->subdir_node, parent, new); | 110 | rb_link_node(&de->subdir_node, parent, new); |
113 | rb_insert_color_cached(&de->subdir_node, root, leftmost); | 111 | rb_insert_color(&de->subdir_node, root); |
114 | return true; | 112 | return true; |
115 | } | 113 | } |
116 | 114 | ||
@@ -401,7 +399,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent, | |||
401 | ent->namelen = qstr.len; | 399 | ent->namelen = qstr.len; |
402 | ent->mode = mode; | 400 | ent->mode = mode; |
403 | ent->nlink = nlink; | 401 | ent->nlink = nlink; |
404 | ent->subdir = RB_ROOT_CACHED; | 402 | ent->subdir = RB_ROOT; |
405 | refcount_set(&ent->refcnt, 1); | 403 | refcount_set(&ent->refcnt, 1); |
406 | spin_lock_init(&ent->pde_unload_lock); | 404 | spin_lock_init(&ent->pde_unload_lock); |
407 | INIT_LIST_HEAD(&ent->pde_openers); | 405 | INIT_LIST_HEAD(&ent->pde_openers); |
@@ -577,7 +575,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
577 | 575 | ||
578 | de = pde_subdir_find(parent, fn, len); | 576 | de = pde_subdir_find(parent, fn, len); |
579 | if (de) | 577 | if (de) |
580 | rb_erase_cached(&de->subdir_node, &parent->subdir); | 578 | rb_erase(&de->subdir_node, &parent->subdir); |
581 | write_unlock(&proc_subdir_lock); | 579 | write_unlock(&proc_subdir_lock); |
582 | if (!de) { | 580 | if (!de) { |
583 | WARN(1, "name '%s'\n", name); | 581 | WARN(1, "name '%s'\n", name); |
@@ -614,13 +612,13 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent) | |||
614 | write_unlock(&proc_subdir_lock); | 612 | write_unlock(&proc_subdir_lock); |
615 | return -ENOENT; | 613 | return -ENOENT; |
616 | } | 614 | } |
617 | rb_erase_cached(&root->subdir_node, &parent->subdir); | 615 | rb_erase(&root->subdir_node, &parent->subdir); |
618 | 616 | ||
619 | de = root; | 617 | de = root; |
620 | while (1) { | 618 | while (1) { |
621 | next = pde_subdir_first(de); | 619 | next = pde_subdir_first(de); |
622 | if (next) { | 620 | if (next) { |
623 | rb_erase_cached(&next->subdir_node, &de->subdir); | 621 | rb_erase(&next->subdir_node, &de->subdir); |
624 | de = next; | 622 | de = next; |
625 | continue; | 623 | continue; |
626 | } | 624 | } |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index b7024f174778..0f1692e63cb6 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -51,15 +51,15 @@ struct proc_dir_entry { | |||
51 | kgid_t gid; | 51 | kgid_t gid; |
52 | loff_t size; | 52 | loff_t size; |
53 | struct proc_dir_entry *parent; | 53 | struct proc_dir_entry *parent; |
54 | struct rb_root_cached subdir; | 54 | struct rb_root subdir; |
55 | struct rb_node subdir_node; | 55 | struct rb_node subdir_node; |
56 | char *name; | 56 | char *name; |
57 | umode_t mode; | 57 | umode_t mode; |
58 | u8 namelen; | 58 | u8 namelen; |
59 | #ifdef CONFIG_64BIT | 59 | #ifdef CONFIG_64BIT |
60 | #define SIZEOF_PDE_INLINE_NAME (192-147) | 60 | #define SIZEOF_PDE_INLINE_NAME (192-139) |
61 | #else | 61 | #else |
62 | #define SIZEOF_PDE_INLINE_NAME (128-91) | 62 | #define SIZEOF_PDE_INLINE_NAME (128-87) |
63 | #endif | 63 | #endif |
64 | char inline_name[SIZEOF_PDE_INLINE_NAME]; | 64 | char inline_name[SIZEOF_PDE_INLINE_NAME]; |
65 | } __randomize_layout; | 65 | } __randomize_layout; |
diff --git a/fs/proc/proc_net.c b/fs/proc/proc_net.c index e5fe3d400737..1763f370489d 100644 --- a/fs/proc/proc_net.c +++ b/fs/proc/proc_net.c | |||
@@ -196,7 +196,7 @@ static __net_init int proc_net_ns_init(struct net *net) | |||
196 | if (!netd) | 196 | if (!netd) |
197 | goto out; | 197 | goto out; |
198 | 198 | ||
199 | netd->subdir = RB_ROOT_CACHED; | 199 | netd->subdir = RB_ROOT; |
200 | netd->data = net; | 200 | netd->data = net; |
201 | netd->nlink = 2; | 201 | netd->nlink = 2; |
202 | netd->namelen = 3; | 202 | netd->namelen = 3; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index 76c996457ff9..61b7340b357a 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -203,7 +203,7 @@ struct proc_dir_entry proc_root = { | |||
203 | .proc_iops = &proc_root_inode_operations, | 203 | .proc_iops = &proc_root_inode_operations, |
204 | .proc_fops = &proc_root_operations, | 204 | .proc_fops = &proc_root_operations, |
205 | .parent = &proc_root, | 205 | .parent = &proc_root, |
206 | .subdir = RB_ROOT_CACHED, | 206 | .subdir = RB_ROOT, |
207 | .name = proc_root.inline_name, | 207 | .name = proc_root.inline_name, |
208 | .inline_name = "/proc", | 208 | .inline_name = "/proc", |
209 | }; | 209 | }; |