diff options
Diffstat (limited to 'modutils/modprobe.c')
-rw-r--r-- | modutils/modprobe.c | 46 |
1 files changed, 30 insertions, 16 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 7ae459826..c1a1828d7 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -89,8 +89,7 @@ | |||
89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" | 89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" |
90 | //usage: " MODULE [symbol=value]..." | 90 | //usage: " MODULE [symbol=value]..." |
91 | //usage:#define modprobe_full_usage "\n\n" | 91 | //usage:#define modprobe_full_usage "\n\n" |
92 | //usage: "Options:" | 92 | //usage: " -a Load multiple MODULEs" |
93 | //usage: "\n -a Load multiple MODULEs" | ||
94 | //usage: "\n -l List (MODULE is a pattern)" | 93 | //usage: "\n -l List (MODULE is a pattern)" |
95 | //usage: "\n -r Remove MODULE (stacks) or do autoclean" | 94 | //usage: "\n -r Remove MODULE (stacks) or do autoclean" |
96 | //usage: "\n -q Quiet" | 95 | //usage: "\n -q Quiet" |
@@ -158,20 +157,21 @@ struct module_entry { /* I'll call it ME. */ | |||
158 | llist_t *deps; /* strings. modules we depend on */ | 157 | llist_t *deps; /* strings. modules we depend on */ |
159 | }; | 158 | }; |
160 | 159 | ||
160 | #define DB_HASH_SIZE 256 | ||
161 | |||
161 | struct globals { | 162 | struct globals { |
162 | llist_t *db; /* MEs of all modules ever seen (caching for speed) */ | ||
163 | llist_t *probes; /* MEs of module(s) requested on cmdline */ | 163 | llist_t *probes; /* MEs of module(s) requested on cmdline */ |
164 | char *cmdline_mopts; /* module options from cmdline */ | 164 | char *cmdline_mopts; /* module options from cmdline */ |
165 | int num_unresolved_deps; | 165 | int num_unresolved_deps; |
166 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | 166 | /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ |
167 | smallint need_symbols; | 167 | smallint need_symbols; |
168 | struct utsname uts; | 168 | struct utsname uts; |
169 | llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ | ||
169 | } FIX_ALIASING; | 170 | } FIX_ALIASING; |
170 | #define G (*(struct globals*)&bb_common_bufsiz1) | 171 | #define G (*ptr_to_globals) |
171 | #define INIT_G() do { } while (0) | 172 | #define INIT_G() do { \ |
172 | struct BUG_G_too_big { | 173 | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
173 | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; | 174 | } while (0) |
174 | }; | ||
175 | 175 | ||
176 | 176 | ||
177 | static int read_config(const char *path); | 177 | static int read_config(const char *path); |
@@ -191,14 +191,26 @@ static char *gather_options_str(char *opts, const char *append) | |||
191 | return opts; | 191 | return opts; |
192 | } | 192 | } |
193 | 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 | */ | ||
194 | 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) |
195 | { | 199 | { |
196 | char modname[MODULE_NAME_LEN]; | 200 | char modname[MODULE_NAME_LEN]; |
197 | struct module_entry *e; | 201 | struct module_entry *e; |
198 | llist_t *l; | 202 | llist_t *l; |
203 | unsigned i; | ||
204 | unsigned hash; | ||
199 | 205 | ||
200 | filename2modname(module, modname); | 206 | filename2modname(module, modname); |
201 | 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) { | ||
202 | e = (struct module_entry *) l->data; | 214 | e = (struct module_entry *) l->data; |
203 | if (strcmp(e->modname, modname) == 0) | 215 | if (strcmp(e->modname, modname) == 0) |
204 | return e; | 216 | return e; |
@@ -208,15 +220,15 @@ static struct module_entry *helper_get_module(const char *module, int create) | |||
208 | 220 | ||
209 | e = xzalloc(sizeof(*e)); | 221 | e = xzalloc(sizeof(*e)); |
210 | e->modname = xstrdup(modname); | 222 | e->modname = xstrdup(modname); |
211 | llist_add_to(&G.db, e); | 223 | llist_add_to(&G.db[hash], e); |
212 | 224 | ||
213 | return e; | 225 | return e; |
214 | } | 226 | } |
215 | 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) |
216 | { | 228 | { |
217 | return helper_get_module(module, 1); | 229 | return helper_get_module(module, 1); |
218 | } | 230 | } |
219 | static struct module_entry *get_modentry(const char *module) | 231 | static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) |
220 | { | 232 | { |
221 | return helper_get_module(module, 0); | 233 | return helper_get_module(module, 0); |
222 | } | 234 | } |
@@ -276,7 +288,7 @@ static int FAST_FUNC config_file_action(const char *filename, | |||
276 | continue; | 288 | continue; |
277 | filename2modname(tokens[1], wildcard); | 289 | filename2modname(tokens[1], wildcard); |
278 | 290 | ||
279 | for (l = G.probes; l != NULL; l = l->link) { | 291 | for (l = G.probes; l; l = l->link) { |
280 | m = (struct module_entry *) l->data; | 292 | m = (struct module_entry *) l->data; |
281 | if (fnmatch(wildcard, m->modname, 0) != 0) | 293 | if (fnmatch(wildcard, m->modname, 0) != 0) |
282 | continue; | 294 | continue; |
@@ -378,7 +390,6 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |||
378 | static int do_modprobe(struct module_entry *m) | 390 | static int do_modprobe(struct module_entry *m) |
379 | { | 391 | { |
380 | int rc, first; | 392 | int rc, first; |
381 | llist_t *l; | ||
382 | 393 | ||
383 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { | 394 | if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { |
384 | if (!(option_mask32 & INSMOD_OPT_SILENT)) | 395 | if (!(option_mask32 & INSMOD_OPT_SILENT)) |
@@ -391,8 +402,11 @@ static int do_modprobe(struct module_entry *m) | |||
391 | if (!(option_mask32 & OPT_REMOVE)) | 402 | if (!(option_mask32 & OPT_REMOVE)) |
392 | m->deps = llist_rev(m->deps); | 403 | m->deps = llist_rev(m->deps); |
393 | 404 | ||
394 | for (l = m->deps; l != NULL; l = l->link) | 405 | if (0) { |
395 | 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 | } | ||
396 | 410 | ||
397 | first = 1; | 411 | first = 1; |
398 | rc = 0; | 412 | rc = 0; |