Skip to content

Commit

Permalink
sysctl: Make the header lists per directory.
Browse files Browse the repository at this point in the history
Slightly enhance efficiency and clarity of the code by making the
header list per directory instead of per set.

Benchmark before:
    make-dummies 0 999 -> 0.63s
    rmmod dummy        -> 0.12s
    make-dummies 0 9999 -> 2m35s
    rmmod dummy         -> 18s

Benchmark after:
    make-dummies 0 999 -> 0.32s
    rmmod dummy        -> 0.12s
    make-dummies 0 9999 -> 1m17s
    rmmod dummy         -> 17s

Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
  • Loading branch information
Eric W. Biederman committed Jan 25, 2012
1 parent e54012c commit 9e3d47d
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 18 deletions.
28 changes: 11 additions & 17 deletions fs/proc/proc_sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ static struct ctl_table root_table[] = {
{ }
};
static struct ctl_table_root sysctl_table_root = {
.default_set.list = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.header.ctl_entry),
.default_set.dir.list = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.list),
.default_set.dir.header = {
{{.count = 1,
.nreg = 1,
.ctl_table = root_table,
.ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}},
.ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.header.ctl_entry),}},
.ctl_table_arg = root_table,
.root = &sysctl_table_root,
.set = &sysctl_table_root.default_set,
Expand Down Expand Up @@ -79,15 +79,12 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2)
static struct ctl_table *find_entry(struct ctl_table_header **phead,
struct ctl_dir *dir, const char *name, int namelen)
{
struct ctl_table_set *set = dir->header.set;
struct ctl_table_header *head;
struct ctl_table *entry;

list_for_each_entry(head, &set->list, ctl_entry) {
list_for_each_entry(head, &dir->list, ctl_entry) {
if (head->unregistering)
continue;
if (head->parent != dir)
continue;
for (entry = head->ctl_table; entry->procname; entry++) {
const char *procname = entry->procname;
if (namecmp(procname, strlen(procname), name, namelen) == 0) {
Expand Down Expand Up @@ -133,7 +130,7 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header)
err = insert_links(header);
if (err)
goto fail_links;
list_add_tail(&header->ctl_entry, &header->set->list);
list_add_tail(&header->ctl_entry, &header->parent->list);
return 0;
fail_links:
header->parent = NULL;
Expand Down Expand Up @@ -247,14 +244,12 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
static struct ctl_table_header *next_usable_entry(struct ctl_dir *dir,
struct list_head *tmp)
{
struct ctl_table_set *set = dir->header.set;
struct ctl_table_header *head;

for (tmp = tmp->next; tmp != &set->list; tmp = tmp->next) {
for (tmp = tmp->next; tmp != &dir->list; tmp = tmp->next) {
head = list_entry(tmp, struct ctl_table_header, ctl_entry);

if (head->parent != dir ||
!head->ctl_table->procname ||
if (!head->ctl_table->procname ||
!use_table(head))
continue;

Expand All @@ -270,7 +265,7 @@ static void first_entry(struct ctl_dir *dir,
struct ctl_table *entry = NULL;

spin_lock(&sysctl_lock);
head = next_usable_entry(dir, &dir->header.set->list);
head = next_usable_entry(dir, &dir->list);
spin_unlock(&sysctl_lock);
if (head)
entry = head->ctl_table;
Expand Down Expand Up @@ -793,6 +788,7 @@ static struct ctl_dir *new_dir(struct ctl_table_set *set,
new_name = (char *)(table + 2);
memcpy(new_name, name, namelen);
new_name[namelen] = '\0';
INIT_LIST_HEAD(&new->list);
table[0].procname = new_name;
table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO;
init_header(&new->header, set->dir.header.root, set, table);
Expand Down Expand Up @@ -917,12 +913,10 @@ static int sysctl_check_table_dups(struct ctl_dir *dir, struct ctl_table *old,

static int sysctl_check_dups(struct ctl_dir *dir, struct ctl_table *table)
{
struct ctl_table_set *set;
struct ctl_table_header *head;
int error = 0;

set = dir->header.set;
list_for_each_entry(head, &set->list, ctl_entry) {
list_for_each_entry(head, &dir->list, ctl_entry) {
if (head->unregistering)
continue;
if (head->parent != dir)
Expand Down Expand Up @@ -1494,14 +1488,14 @@ void setup_sysctl_set(struct ctl_table_set *set,
int (*is_seen)(struct ctl_table_set *))
{
memset(set, sizeof(*set), 0);
INIT_LIST_HEAD(&set->list);
set->is_seen = is_seen;
INIT_LIST_HEAD(&set->dir.list);
init_header(&set->dir.header, root, set, root_table);
}

void retire_sysctl_set(struct ctl_table_set *set)
{
WARN_ON(!list_empty(&set->list));
WARN_ON(!list_empty(&set->dir.list));
}

int __init proc_sys_init(void)
Expand Down
2 changes: 1 addition & 1 deletion include/linux/sysctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1047,10 +1047,10 @@ struct ctl_table_header
struct ctl_dir {
/* Header must be at the start of ctl_dir */
struct ctl_table_header header;
struct list_head list;
};

struct ctl_table_set {
struct list_head list;
int (*is_seen)(struct ctl_table_set *);
struct ctl_dir dir;
};
Expand Down

0 comments on commit 9e3d47d

Please sign in to comment.