modprobe: use hash table. speeds up significantly if modprobe.dep is large
No binary (build failed)
—
(log yok)
| @@ -157,20 +157,21 @@ struct module_entry { /* I'll call it ME. */ | |
| llist_t *deps; /* strings. modules we depend on */ | |
| }; | |
| + | #define DB_HASH_SIZE 256 |
| + | |
| struct globals { | |
| - | llist_t *db; /* MEs of all modules ever seen (caching for speed) */ |
| llist_t *probes; /* MEs of module(s) requested on cmdline */ | |
| char *cmdline_mopts; /* module options from cmdline */ | |
| int num_unresolved_deps; | |
| /* bool. "Did we have 'symbol:FOO' requested on cmdline?" */ | |
| smallint need_symbols; | |
| struct utsname uts; | |
| + | llist_t *db[DB_HASH_SIZE]; /* MEs of all modules ever seen (caching for speed) */ |
| } FIX_ALIASING; | |
| - | #define G (*(struct globals*)&bb_common_bufsiz1) |
| - | #define INIT_G() do { } while (0) |
| - | struct BUG_G_too_big { |
| - | char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1]; |
| - | }; |
| + | #define G (*ptr_to_globals) |
| + | #define INIT_G() do { \ |
| + | SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ |
| + | } while (0) |
| static int read_config(const char *path); | |
| @@ -190,14 +191,26 @@ static char *gather_options_str(char *opts, const char *append) | |
| return opts; | |
| } | |
| + | /* These three functions called many times, optimizing for speed. |
| + | * Users reported minute-long delays when they runn iptables repeatedly |
| + | * (iptables use modprobe to install needed kernel modules). |
| + | */ |
| static struct module_entry *helper_get_module(const char *module, int create) | |
| { | |
| char modname[MODULE_NAME_LEN]; | |
| struct module_entry *e; | |
| llist_t *l; | |
| + | unsigned i; |
| + | unsigned hash; |
| filename2modname(module, modname); | |
| - | for (l = G.db; l != NULL; l = l->link) { |
| + | |
| + | hash = 0; |
| + | for (i = 0; modname[i]; i++) |
| + | hash = ((hash << 5) + hash) + modname[i]; |
| + | hash %= DB_HASH_SIZE; |
| + | |
| + | for (l = G.db[hash]; l; l = l->link) { |
| e = (struct module_entry *) l->data; | |
| if (strcmp(e->modname, modname) == 0) | |
| return e; | |
| @@ -207,15 +220,15 @@ static struct module_entry *helper_get_module(const char *module, int create) | |
| e = xzalloc(sizeof(*e)); | |
| e->modname = xstrdup(modname); | |
| - | llist_add_to(&G.db, e); |
| + | llist_add_to(&G.db[hash], e); |
| return e; | |
| } | |
| - | static struct module_entry *get_or_add_modentry(const char *module) |
| + | static ALWAYS_INLINE struct module_entry *get_or_add_modentry(const char *module) |
| { | |
| return helper_get_module(module, 1); | |
| } | |
| - | static struct module_entry *get_modentry(const char *module) |
| + | static ALWAYS_INLINE struct module_entry *get_modentry(const char *module) |
| { | |
| return helper_get_module(module, 0); | |
| } | |
| @@ -275,7 +288,7 @@ static int FAST_FUNC config_file_action(const char *filename, | |
| continue; | |
| filename2modname(tokens[1], wildcard); | |
| - | for (l = G.probes; l != NULL; l = l->link) { |
| + | for (l = G.probes; l; l = l->link) { |
| m = (struct module_entry *) l->data; | |
| if (fnmatch(wildcard, m->modname, 0) != 0) | |
| continue; | |
| @@ -377,7 +390,6 @@ static char *parse_and_add_kcmdline_module_options(char *options, const char *mo | |
| static int do_modprobe(struct module_entry *m) | |
| { | |
| int rc, first; | |
| - | llist_t *l; |
| if (!(m->flags & MODULE_FLAG_FOUND_IN_MODDEP)) { | |
| if (!(option_mask32 & INSMOD_OPT_SILENT)) | |
| @@ -390,8 +402,11 @@ static int do_modprobe(struct module_entry *m) | |
| if (!(option_mask32 & OPT_REMOVE)) | |
| m->deps = llist_rev(m->deps); | |
| - | for (l = m->deps; l != NULL; l = l->link) |
| - | DBG("dep: %s", l->data); |
| + | if (0) { |
| + | llist_t *l; |
| + | for (l = m->deps; l; l = l->link) |
| + | DBG("dep: %s", l->data); |
| + | } |
| first = 1; | |
| rc = 0; | |