aboutsummaryrefslogtreecommitdiff
path: root/modutils/modprobe.c
diff options
context:
space:
mode:
Diffstat (limited to 'modutils/modprobe.c')
-rw-r--r--modutils/modprobe.c46
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
161struct globals { 162struct 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 { \
172struct 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
177static int read_config(const char *path); 177static 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 */
194static struct module_entry *helper_get_module(const char *module, int create) 198static 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}
215static struct module_entry *get_or_add_modentry(const char *module) 227static 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}
219static struct module_entry *get_modentry(const char *module) 231static 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
378static int do_modprobe(struct module_entry *m) 390static 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;