aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2012-01-08 02:45:12 -0500
committerEric W. Biederman <ebiederm@xmission.com>2012-01-24 19:40:30 -0500
commit9e3d47df35abd6430fed04fb40a76c7358b1e815 (patch)
tree8c7fe500d2cefdf99b1128e60178045a39f1a864 /fs/proc
parente54012cede6749528899f66a72312522a179d427 (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.c28
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};
35static struct ctl_table_root sysctl_table_root = { 35static 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)
79static struct ctl_table *find_entry(struct ctl_table_header **phead, 79static 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;
138fail_links: 135fail_links:
139 header->parent = NULL; 136 header->parent = NULL;
@@ -247,14 +244,12 @@ static struct ctl_table *lookup_entry(struct ctl_table_header **phead,
247static struct ctl_table_header *next_usable_entry(struct ctl_dir *dir, 244static 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
918static int sysctl_check_dups(struct ctl_dir *dir, struct ctl_table *table) 914static 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
1502void retire_sysctl_set(struct ctl_table_set *set) 1496void 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
1507int __init proc_sys_init(void) 1501int __init proc_sys_init(void)