diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2012-01-08 02:45:12 -0500 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-01-24 19:40:30 -0500 |
commit | 9e3d47df35abd6430fed04fb40a76c7358b1e815 (patch) | |
tree | 8c7fe500d2cefdf99b1128e60178045a39f1a864 /fs/proc | |
parent | e54012cede6749528899f66a72312522a179d427 (diff) |
sysctl: Make the header lists per directory.
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>
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/proc_sysctl.c | 28 |
1 files changed, 11 insertions, 17 deletions
diff --git a/fs/proc/proc_sysctl.c b/fs/proc/proc_sysctl.c index 160d5781638e..e971ccccac4a 100644 --- a/fs/proc/proc_sysctl.c +++ b/fs/proc/proc_sysctl.c | |||
@@ -33,12 +33,12 @@ static struct ctl_table root_table[] = { | |||
33 | { } | 33 | { } |
34 | }; | 34 | }; |
35 | static struct ctl_table_root sysctl_table_root = { | 35 | static struct ctl_table_root sysctl_table_root = { |
36 | .default_set.list = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.header.ctl_entry), | 36 | .default_set.dir.list = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.list), |
37 | .default_set.dir.header = { | 37 | .default_set.dir.header = { |
38 | {{.count = 1, | 38 | {{.count = 1, |
39 | .nreg = 1, | 39 | .nreg = 1, |
40 | .ctl_table = root_table, | 40 | .ctl_table = root_table, |
41 | .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.list),}}, | 41 | .ctl_entry = LIST_HEAD_INIT(sysctl_table_root.default_set.dir.header.ctl_entry),}}, |
42 | .ctl_table_arg = root_table, | 42 | .ctl_table_arg = root_table, |
43 | .root = &sysctl_table_root, | 43 | .root = &sysctl_table_root, |
44 | .set = &sysctl_table_root.default_set, | 44 | .set = &sysctl_table_root.default_set, |
@@ -79,15 +79,12 @@ static int namecmp(const char *name1, int len1, const char *name2, int len2) | |||
79 | static struct ctl_table *find_entry(struct ctl_table_header **phead, | 79 | static struct ctl_table *find_entry(struct ctl_table_header **phead, |
80 | struct ctl_dir *dir, const char *name, int namelen) | 80 | struct ctl_dir *dir, const char *name, int namelen) |
81 | { | 81 | { |
82 | struct ctl_table_set *set = dir->header.set; | ||
83 | struct ctl_table_header *head; | 82 | struct ctl_table_header *head; |
84 | struct ctl_table *entry; | 83 | struct ctl_table *entry; |
85 | 84 | ||
86 | list_for_each_entry(head, &set->list, ctl_entry) { | 85 | list_for_each_entry(head, &dir->list, ctl_entry) { |
87 | if (head->unregistering) | 86 | if (head->unregistering) |
88 | continue; | 87 | continue; |
89 | if (head->parent != dir) | ||
90 | continue; | ||
91 | for (entry = head->ctl_table; entry->procname; entry++) { | 88 | for (entry = head->ctl_table; entry->procname; entry++) { |
92 | const char *procname = entry->procname; | 89 | const char *procname = entry->procname; |
93 | if (namecmp(procname, strlen(procname), name, namelen) == 0) { | 90 | if (namecmp(procname, strlen(procname), name, namelen) == 0) { |
@@ -133,7 +130,7 @@ static int insert_header(struct ctl_dir *dir, struct ctl_table_header *header) | |||
133 | err = insert_links(header); | 130 | err = insert_links(header); |
134 | if (err) | 131 | if (err) |
135 | goto fail_links; | 132 | goto fail_links; |
136 | list_add_tail(&header->ctl_entry, &header->set->list); | 133 | list_add_tail(&header->ctl_entry, &header->parent->list); |
137 | return 0; | 134 | return 0; |
138 | fail_links: | 135 | fail_links: |
139 | header->parent = NULL; | 136 | header->parent = NULL; |
@@ -247,14 +244,12 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead, | |||
247 | static struct ctl_table_header *next_usable_entry(struct ctl_dir *dir, | 244 | static struct ctl_table_header *next_usable_entry(struct ctl_dir *dir, |
248 | struct list_head *tmp) | 245 | struct list_head *tmp) |
249 | { | 246 | { |
250 | struct ctl_table_set *set = dir->header.set; | ||
251 | struct ctl_table_header *head; | 247 | struct ctl_table_header *head; |
252 | 248 | ||
253 | for (tmp = tmp->next; tmp != &set->list; tmp = tmp->next) { | 249 | for (tmp = tmp->next; tmp != &dir->list; tmp = tmp->next) { |
254 | head = list_entry(tmp, struct ctl_table_header, ctl_entry); | 250 | head = list_entry(tmp, struct ctl_table_header, ctl_entry); |
255 | 251 | ||
256 | if (head->parent != dir || | 252 | if (!head->ctl_table->procname || |
257 | !head->ctl_table->procname || | ||
258 | !use_table(head)) | 253 | !use_table(head)) |
259 | continue; | 254 | continue; |
260 | 255 | ||
@@ -270,7 +265,7 @@ static void first_entry(struct ctl_dir *dir, | |||
270 | struct ctl_table *entry = NULL; | 265 | struct ctl_table *entry = NULL; |
271 | 266 | ||
272 | spin_lock(&sysctl_lock); | 267 | spin_lock(&sysctl_lock); |
273 | head = next_usable_entry(dir, &dir->header.set->list); | 268 | head = next_usable_entry(dir, &dir->list); |
274 | spin_unlock(&sysctl_lock); | 269 | spin_unlock(&sysctl_lock); |
275 | if (head) | 270 | if (head) |
276 | entry = head->ctl_table; | 271 | entry = head->ctl_table; |
@@ -793,6 +788,7 @@ static struct ctl_dir *new_dir(struct ctl_table_set *set, | |||
793 | new_name = (char *)(table + 2); | 788 | new_name = (char *)(table + 2); |
794 | memcpy(new_name, name, namelen); | 789 | memcpy(new_name, name, namelen); |
795 | new_name[namelen] = '\0'; | 790 | new_name[namelen] = '\0'; |
791 | INIT_LIST_HEAD(&new->list); | ||
796 | table[0].procname = new_name; | 792 | table[0].procname = new_name; |
797 | table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO; | 793 | table[0].mode = S_IFDIR|S_IRUGO|S_IXUGO; |
798 | init_header(&new->header, set->dir.header.root, set, table); | 794 | init_header(&new->header, set->dir.header.root, set, table); |
@@ -917,12 +913,10 @@ static int sysctl_check_table_dups(struct ctl_dir *dir, struct ctl_table *old, | |||
917 | 913 | ||
918 | static int sysctl_check_dups(struct ctl_dir *dir, struct ctl_table *table) | 914 | static int sysctl_check_dups(struct ctl_dir *dir, struct ctl_table *table) |
919 | { | 915 | { |
920 | struct ctl_table_set *set; | ||
921 | struct ctl_table_header *head; | 916 | struct ctl_table_header *head; |
922 | int error = 0; | 917 | int error = 0; |
923 | 918 | ||
924 | set = dir->header.set; | 919 | list_for_each_entry(head, &dir->list, ctl_entry) { |
925 | list_for_each_entry(head, &set->list, ctl_entry) { | ||
926 | if (head->unregistering) | 920 | if (head->unregistering) |
927 | continue; | 921 | continue; |
928 | if (head->parent != dir) | 922 | if (head->parent != dir) |
@@ -1494,14 +1488,14 @@ void setup_sysctl_set(struct ctl_table_set *set, | |||
1494 | int (*is_seen)(struct ctl_table_set *)) | 1488 | int (*is_seen)(struct ctl_table_set *)) |
1495 | { | 1489 | { |
1496 | memset(set, sizeof(*set), 0); | 1490 | memset(set, sizeof(*set), 0); |
1497 | INIT_LIST_HEAD(&set->list); | ||
1498 | set->is_seen = is_seen; | 1491 | set->is_seen = is_seen; |
1492 | INIT_LIST_HEAD(&set->dir.list); | ||
1499 | init_header(&set->dir.header, root, set, root_table); | 1493 | init_header(&set->dir.header, root, set, root_table); |
1500 | } | 1494 | } |
1501 | 1495 | ||
1502 | void retire_sysctl_set(struct ctl_table_set *set) | 1496 | void retire_sysctl_set(struct ctl_table_set *set) |
1503 | { | 1497 | { |
1504 | WARN_ON(!list_empty(&set->list)); | 1498 | WARN_ON(!list_empty(&set->dir.list)); |
1505 | } | 1499 | } |
1506 | 1500 | ||
1507 | int __init proc_sys_init(void) | 1501 | int __init proc_sys_init(void) |