Skip to content

Commit

Permalink
procfs: use faster rb_first_cached()
Browse files Browse the repository at this point in the history
...  such that we can avoid the tree walks to get the node with the
smallest key.  Semantically the same, as the previously used rb_first(),
but O(1).  The main overhead is the extra footprint for the cached rb_node
pointer, which should not matter for procfs.

Link: http://lkml.kernel.org/r/[email protected]
Signed-off-by: Davidlohr Bueso <[email protected]>
Acked-by: Peter Zijlstra (Intel) <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Davidlohr Bueso authored and torvalds committed Sep 9, 2017
1 parent f2686bb commit 410bd5e
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 15 deletions.
26 changes: 14 additions & 12 deletions fs/proc/generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ static int proc_match(unsigned int len, const char *name, struct proc_dir_entry

static struct proc_dir_entry *pde_subdir_first(struct proc_dir_entry *dir)
{
return rb_entry_safe(rb_first(&dir->subdir), struct proc_dir_entry,
subdir_node);
return rb_entry_safe(rb_first_cached(&dir->subdir),
struct proc_dir_entry, subdir_node);
}

static struct proc_dir_entry *pde_subdir_next(struct proc_dir_entry *dir)
Expand All @@ -54,7 +54,7 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
const char *name,
unsigned int len)
{
struct rb_node *node = dir->subdir.rb_node;
struct rb_node *node = dir->subdir.rb_root.rb_node;

while (node) {
struct proc_dir_entry *de = rb_entry(node,
Expand All @@ -75,8 +75,9 @@ static struct proc_dir_entry *pde_subdir_find(struct proc_dir_entry *dir,
static bool pde_subdir_insert(struct proc_dir_entry *dir,
struct proc_dir_entry *de)
{
struct rb_root *root = &dir->subdir;
struct rb_node **new = &root->rb_node, *parent = NULL;
struct rb_root_cached *root = &dir->subdir;
struct rb_node **new = &root->rb_root.rb_node, *parent = NULL;
bool leftmost = true;

/* Figure out where to put new node */
while (*new) {
Expand All @@ -88,15 +89,16 @@ static bool pde_subdir_insert(struct proc_dir_entry *dir,
parent = *new;
if (result < 0)
new = &(*new)->rb_left;
else if (result > 0)
else if (result > 0) {
new = &(*new)->rb_right;
else
leftmost = false;
} else
return false;
}

/* Add new node and rebalance tree. */
rb_link_node(&de->subdir_node, parent, new);
rb_insert_color(&de->subdir_node, root);
rb_insert_color_cached(&de->subdir_node, root, leftmost);
return true;
}

Expand Down Expand Up @@ -369,7 +371,7 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
ent->namelen = qstr.len;
ent->mode = mode;
ent->nlink = nlink;
ent->subdir = RB_ROOT;
ent->subdir = RB_ROOT_CACHED;
atomic_set(&ent->count, 1);
spin_lock_init(&ent->pde_unload_lock);
INIT_LIST_HEAD(&ent->pde_openers);
Expand Down Expand Up @@ -553,7 +555,7 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent)

de = pde_subdir_find(parent, fn, len);
if (de)
rb_erase(&de->subdir_node, &parent->subdir);
rb_erase_cached(&de->subdir_node, &parent->subdir);
write_unlock(&proc_subdir_lock);
if (!de) {
WARN(1, "name '%s'\n", name);
Expand Down Expand Up @@ -590,13 +592,13 @@ int remove_proc_subtree(const char *name, struct proc_dir_entry *parent)
write_unlock(&proc_subdir_lock);
return -ENOENT;
}
rb_erase(&root->subdir_node, &parent->subdir);
rb_erase_cached(&root->subdir_node, &parent->subdir);

de = root;
while (1) {
next = pde_subdir_first(de);
if (next) {
rb_erase(&next->subdir_node, &de->subdir);
rb_erase_cached(&next->subdir_node, &de->subdir);
de = next;
continue;
}
Expand Down
2 changes: 1 addition & 1 deletion fs/proc/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ struct proc_dir_entry {
const struct inode_operations *proc_iops;
const struct file_operations *proc_fops;
struct proc_dir_entry *parent;
struct rb_root subdir;
struct rb_root_cached subdir;
struct rb_node subdir_node;
void *data;
atomic_t count; /* use count */
Expand Down
2 changes: 1 addition & 1 deletion fs/proc/proc_net.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static __net_init int proc_net_ns_init(struct net *net)
if (!netd)
goto out;

netd->subdir = RB_ROOT;
netd->subdir = RB_ROOT_CACHED;
netd->data = net;
netd->nlink = 2;
netd->namelen = 3;
Expand Down
2 changes: 1 addition & 1 deletion fs/proc/root.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ struct proc_dir_entry proc_root = {
.proc_iops = &proc_root_inode_operations,
.proc_fops = &proc_root_operations,
.parent = &proc_root,
.subdir = RB_ROOT,
.subdir = RB_ROOT_CACHED,
.name = "/proc",
};

Expand Down

0 comments on commit 410bd5e

Please sign in to comment.