diff options
author | Timo Teras <timo.teras@iki.fi> | 2011-06-20 09:38:13 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2011-06-20 09:38:13 +0200 |
commit | e12e0acb92329f95a77121f489b491d84b6a2c33 (patch) | |
tree | 60678cbeedfbe3b2df3dcbc36b3e921bb8a6cd64 | |
parent | 416e978ce80997088d3f0f2dd532554863d95ab5 (diff) | |
download | busybox-w32-e12e0acb92329f95a77121f489b491d84b6a2c33.tar.gz busybox-w32-e12e0acb92329f95a77121f489b491d84b6a2c33.tar.bz2 busybox-w32-e12e0acb92329f95a77121f489b491d84b6a2c33.zip |
modprobe: use hash table. speeds up significantly if modprobe.dep is large
function old new delta
helper_get_module 106 157 +51
config_file_action 413 431 +18
modprobe_main 690 706 +16
do_modprobe 580 588 +8
add_probe 81 83 +2
load_modules_dep 192 190 -2
get_or_add_modentry 10 - -10
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 5/1 up/down: 95/-12) Total: 83 bytes
Signed-off-by: Timo Teras <timo.teras@iki.fi>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | modutils/modprobe.c | 43 |
1 files changed, 29 insertions, 14 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 678f4bea5..c1a1828d7 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -157,20 +157,21 @@ struct module_entry { /* I'll call it ME. */ | |||
157 | llist_t *deps; /* strings. modules we depend on */ | 157 | llist_t *deps; /* strings. modules we depend on */ |
158 | }; | 158 | }; |
159 | 159 | ||
160 | #define DB_HASH_SIZE 256 | ||
161 | |||
160 | struct globals { | 162 | struct globals { |
161 | llist_t *db; /* MEs of all modules ever seen (caching for speed) */ | ||
162 | llist_t *probes; /* MEs of module(s) requested on cmdline */ | 163 | llist_t *probes; /* MEs of module(s) requested on cmdline */ |
163 | char *cmdline_mopts; /* module options from cmdline */ | 164 | char *cmdline_mopts; /* module options from cmdline */ |
164 | int num_unresolved_deps; | 165 | int num_unresolved_deps; |
165 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 166 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
166 | smallint need_symbols; | 167 | smallint need_symbols; |
167 | struct utsname uts; | 168 | struct utsname uts; |
169 | llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ | ||
168 | } FIX_ALIASING; | 170 | } FIX_ALIASING; |
169 | #define G (*(struct globals*)&bb_common_bufsiz1) | 171 | #define G (*ptr_to_globals) |
170 | #define INIT_G() do { } while (0) | 172 | #define INIT_G() do { \ |
171 | struct BUG_G_too_big { | 173 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
172 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | 174 | } while (0) |
173 | }; | ||
174 | 175 | ||
175 | 176 | ||
176 | static int read_config(const char *path); | 177 | static int read_config(const char *path); |
@@ -190,14 +191,26 @@ static char *gather_options_str(char *opts, const char *append) | |||
190 | return opts; | 191 | return opts; |
191 | } | 192 | } |
192 | 193 | ||
194 | /* These three functions called many times, optimizing for speed. | ||
195 | * Users reported minute-long delays when they runn iptables repeatedly | ||
196 | * (iptables use modprobe to install needed kernel modules). | ||
197 | */ | ||
193 | static struct module_entry *helper_get_module(const char *module, int create) | 198 | static struct module_entry *helper_get_module(const char *module, int create) |
194 | { | 199 | { |
195 | char modname[MODULE_NAME_LEN]; | 200 | char modname[MODULE_NAME_LEN]; |
196 | struct module_entry *e; | 201 | struct module_entry *e; |
197 | llist_t *l; | 202 | llist_t *l; |
203 | unsigned i; | ||
204 | unsigned hash; | ||
198 | 205 | ||
199 | filename2modname(module, modname); | 206 | filename2modname(module, modname); |
200 | for (l = G.db; l != NULL; l = l->link) { | 207 | |
208 | hash = 0; | ||
209 | for (i = 0; modname[i]; i++) | ||
210 | hash = ((hash << 5) + hash) + modname[i]; | ||
211 | hash %= DB_HASH_SIZE; | ||
212 | |||
213 | for (l = G.db[hash]; l; l = l->link) { | ||
201 | e = (struct module_entry *) l->data; | 214 | e = (struct module_entry *) l->data; |
202 | if (strcmp(e->modname, modname) == 0) | 215 | if (strcmp(e->modname, modname) == 0) |
203 | return e; | 216 | return e; |
@@ -207,15 +220,15 @@ static struct module_entry *helper_get_module(const char *module, int create) | |||
207 | 220 | ||
208 | e = xzalloc(sizeof(*e)); | 221 | e = xzalloc(sizeof(*e)); |
209 | e->modname = xstrdup(modname); | 222 | e->modname = xstrdup(modname); |
210 | llist_add_to(&G.db, e); | 223 | llist_add_to(&G.db[hash], e); |
211 | 224 | ||
212 | return e; | 225 | return e; |
213 | } | 226 | } |
214 | static struct module_entry *get_or_add_modentry(const char *module) | 227 | static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) |
215 | { | 228 | { |
216 | return helper_get_module(module, 1); | 229 | return helper_get_module(module, 1); |
217 | } | 230 | } |
218 | static struct module_entry *get_modentry(const char *module) | 231 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) |
219 | { | 232 | { |
220 | return helper_get_module(module, 0); | 233 | return helper_get_module(module, 0); |
221 | } | 234 | } |
@@ -275,7 +288,7 @@ static int FAST_FUNC config_file_action(const char *filename, | |||
275 | continue; | 288 | continue; |
276 | filename2modname(tokens[1], wildcard); | 289 | filename2modname(tokens[1], wildcard); |
277 | 290 | ||
278 | for (l = G.probes; l != NULL; l = l->link) { | 291 | for (l = G.probes; l; l = l->link) { |
279 | m = (struct module_entry *) l->data; | 292 | m = (struct module_entry *) l->data; |
280 | if (fnmatch(wildcard, m->modname, 0) != 0) | 293 | if (fnmatch(wildcard, m->modname, 0) != 0) |
281 | continue; | 294 | continue; |
@@ -377,7 +390,6 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |||
377 | static int do_modprobe(struct module_entry *m) | 390 | static int do_modprobe(struct module_entry *m) |
378 | { | 391 | { |
379 | int rc, first; | 392 | int rc, first; |
380 | llist_t *l; | ||
381 | 393 | ||
382 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { | 394 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { |
383 | if (!(option_mask32 & INSMOD_OPT_SILENT)) | 395 | if (!(option_mask32 & INSMOD_OPT_SILENT)) |
@@ -390,8 +402,11 @@ static int do_modprobe(struct module_entry *m) | |||
390 | if (!(option_mask32 & OPT_REMOVE)) | 402 | if (!(option_mask32 & OPT_REMOVE)) |
391 | m->deps = llist_rev(m->deps); | 403 | m->deps = llist_rev(m->deps); |
392 | 404 | ||
393 | for (l = m->deps; l != NULL; l = l->link) | 405 | if (0) { |
394 | DBG("dep: %s", l->data); | 406 | llist_t *l; |
407 | for (l = m->deps; l; l = l->link) | ||
408 | DBG("dep: %s", l->data); | ||
409 | } | ||
395 | 410 | ||
396 | first = 1; | 411 | first = 1; |
397 | rc = 0; | 412 | rc = 0; |