diff options
author | Timo Teräs <timo.teras@iki.fi> | 2015-11-05 18:54:55 +0100 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2015-11-05 18:54:55 +0100 |
commit | 48dc80bbba994eee24ed94ae4532a1cce76d7cb7 (patch) | |
tree | 051e7aacf5538ffc07310bb4261a693a047311d2 /modutils/modprobe.c | |
parent | 34adecc2b049f6941c5e075ffb58fe2183823da3 (diff) | |
download | busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.tar.gz busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.tar.bz2 busybox-w32-48dc80bbba994eee24ed94ae4532a1cce76d7cb7.zip |
modutils: merge module_entry and module_info to common
This merges the in-memory module info structures of modprobe
and depmod. This allows sharing hashing by modulename code
improving depmod runtime with almost factor of 2x.
function old new delta
get_or_add_modentry - 17 +17
do_modprobe 590 601 +11
moddb_get_or_create - 10 +10
load_modules_dep 195 205 +10
moddb_get - 7 +7
add_probe 81 78 -3
modprobe_main 721 714 -7
depmod_main 553 543 -10
config_file_action 434 421 -13
helper_get_module 160 144 -16
parse_module 343 320 -23
order_dep_list 105 82 -23
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 2/7 up/down: 55/-95) Total: -40 bytes
Signed-off-by: Timo Teräs <timo.teras@iki.fi>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'modutils/modprobe.c')
-rw-r--r-- | modutils/modprobe.c | 66 |
1 files changed, 7 insertions, 59 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 05bf02cf8..ec490b74d 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -150,19 +150,6 @@ static const char modprobe_longopts[] ALIGN1 = | |||
150 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 | 150 | #define MODULE_FLAG_FOUND_IN_MODDEP 0x0004 |
151 | #define MODULE_FLAG_BLACKLISTED 0x0008 | 151 | #define MODULE_FLAG_BLACKLISTED 0x0008 |
152 | 152 | ||
153 | struct module_entry { /* I'll call it ME. */ | ||
154 | unsigned flags; | ||
155 | char *modname; /* stripped of /path/, .ext and s/-/_/g */ | ||
156 | const char *probed_name; /* verbatim as seen on cmdline */ | ||
157 | char *options; /* options from config files */ | ||
158 | llist_t *realnames; /* strings. if this module is an alias, */ | ||
159 | /* real module name is one of these. */ | ||
160 | //Can there really be more than one? Example from real kernel? | ||
161 | llist_t *deps; /* strings. modules we depend on */ | ||
162 | }; | ||
163 | |||
164 | #define DB_HASH_SIZE 256 | ||
165 | |||
166 | struct globals { | 153 | struct globals { |
167 | llist_t *probes; /* MEs of module(s) requested on cmdline */ | 154 | llist_t *probes; /* MEs of module(s) requested on cmdline */ |
168 | char *cmdline_mopts; /* module options from cmdline */ | 155 | char *cmdline_mopts; /* module options from cmdline */ |
@@ -170,7 +157,7 @@ struct globals { | |||
170 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 157 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
171 | smallint need_symbols; | 158 | smallint need_symbols; |
172 | struct utsname uts; | 159 | struct utsname uts; |
173 | llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ | 160 | module_db db; |
174 | } FIX_ALIASING; | 161 | } FIX_ALIASING; |
175 | #define G (*ptr_to_globals) | 162 | #define G (*ptr_to_globals) |
176 | #define INIT_G() do { \ | 163 | #define INIT_G() do { \ |
@@ -195,51 +182,9 @@ static char *gather_options_str(char *opts, const char *append) | |||
195 | return opts; | 182 | return opts; |
196 | } | 183 | } |
197 | 184 | ||
198 | /* These three functions called many times, optimizing for speed. | 185 | static struct module_entry *get_or_add_modentry(const char *module) |
199 | * Users reported minute-long delays when they runn iptables repeatedly | ||
200 | * (iptables use modprobe to install needed kernel modules). | ||
201 | */ | ||
202 | static struct module_entry *helper_get_module(const char *module, int create) | ||
203 | { | ||
204 | char modname[MODULE_NAME_LEN]; | ||
205 | struct module_entry *e; | ||
206 | llist_t *l; | ||
207 | unsigned i; | ||
208 | unsigned hash; | ||
209 | |||
210 | filename2modname(module, modname); | ||
211 | |||
212 | hash = 0; | ||
213 | for (i = 0; modname[i]; i++) | ||
214 | hash = ((hash << 5) + hash) + modname[i]; | ||
215 | hash %= DB_HASH_SIZE; | ||
216 | |||
217 | for (l = G.db[hash]; l; l = l->link) { | ||
218 | e = (struct module_entry *) l->data; | ||
219 | if (strcmp(e->modname, modname) == 0) | ||
220 | return e; | ||
221 | } | ||
222 | if (!create) | ||
223 | return NULL; | ||
224 | |||
225 | e = xzalloc(sizeof(*e)); | ||
226 | e->modname = xstrdup(modname); | ||
227 | llist_add_to(&G.db[hash], e); | ||
228 | |||
229 | return e; | ||
230 | } | ||
231 | static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) | ||
232 | { | 186 | { |
233 | return helper_get_module(module, 1); | 187 | return moddb_get_or_create(&G.db, module); |
234 | } | ||
235 | /* So far this function always gets a module pathname, never an alias name. | ||
236 | * The crucial difference is that pathname needs dirname stripping, | ||
237 | * while alias name must NOT do it! | ||
238 | * Testcase where dirname stripping is likely to go wrong: "modprobe devname:snd/timer" | ||
239 | */ | ||
240 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *pathname) | ||
241 | { | ||
242 | return helper_get_module(bb_get_last_path_component_nostrip(pathname), 0); | ||
243 | } | 188 | } |
244 | 189 | ||
245 | static void add_probe(const char *name) | 190 | static void add_probe(const char *name) |
@@ -536,7 +481,7 @@ static void load_modules_dep(void) | |||
536 | continue; | 481 | continue; |
537 | *colon = '\0'; | 482 | *colon = '\0'; |
538 | 483 | ||
539 | m = get_modentry(tokens[0]); | 484 | m = moddb_get(&G.db, bb_get_last_path_component_nostrip(tokens[0])); |
540 | if (m == NULL) | 485 | if (m == NULL) |
541 | continue; | 486 | continue; |
542 | 487 | ||
@@ -697,5 +642,8 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv) | |||
697 | } while (me->realnames != NULL); | 642 | } while (me->realnames != NULL); |
698 | } | 643 | } |
699 | 644 | ||
645 | if (ENABLE_FEATURE_CLEAN_UP) | ||
646 | moddb_free(&G.db); | ||
647 | |||
700 | return (rc != 0); | 648 | return (rc != 0); |
701 | } | 649 | } |