From 34b3831457b38bcff7562d26ce4d21cc83c4771e Mon Sep 17 00:00:00 2001 From: Timo Teras Date: Wed, 25 Feb 2009 11:04:38 +0200 Subject: core/busybox: speed up modprobe -a experimental patch to speed up bootup time. --- core/busybox/APKBUILD | 4 +- core/busybox/busybox-1.13.2-modprobe-speedup.patch | 369 +++++++++++++++++++++ 2 files changed, 372 insertions(+), 1 deletion(-) create mode 100644 core/busybox/busybox-1.13.2-modprobe-speedup.patch (limited to 'core/busybox') diff --git a/core/busybox/APKBUILD b/core/busybox/APKBUILD index e3080b64..dc3a816d 100644 --- a/core/busybox/APKBUILD +++ b/core/busybox/APKBUILD @@ -1,6 +1,6 @@ pkgname=busybox pkgver=1.13.2 -pkgrel=2 +pkgrel=3 pkgdesc="Size optimized toolbox of many common UNIX utilities" url=http://busybox.net license=GPL-2 @@ -12,6 +12,7 @@ source="http://busybox.net/downloads/$pkgname-$pkgver.tar.bz2 busybox-1.13.2-init.patch busybox-1.13.2-mdev.patch busybox-1.13.2-modprobe.patch + busybox-1.13.2-modprobe-speedup.patch busybox-1.13.2-tar.patch busyboxconfig" @@ -40,5 +41,6 @@ f5a8ae3145aa249868c1a1abc319c228 busybox-1.12.1-vi-path.patch 7afb3a1b474742bc198b3c8450ab9a7e busybox-1.13.2-init.patch a72d169e9545e26257032e0e367feb95 busybox-1.13.2-mdev.patch 6eeb6efcd71e57082d6654a9a6a368eb busybox-1.13.2-modprobe.patch +1ef5811b3f60d61c3c5fdc05996c8824 busybox-1.13.2-modprobe-speedup.patch 90d093817855bc63ad16fbb8524f80df busybox-1.13.2-tar.patch 7da47c98607834ca9c47a22bf3fe4b6e busyboxconfig" diff --git a/core/busybox/busybox-1.13.2-modprobe-speedup.patch b/core/busybox/busybox-1.13.2-modprobe-speedup.patch new file mode 100644 index 00000000..f94a97ee --- /dev/null +++ b/core/busybox/busybox-1.13.2-modprobe-speedup.patch @@ -0,0 +1,369 @@ +Index: modutils/modprobe.c +=================================================================== +--- a/modutils/modprobe.c (revision 25448) ++++ b/modutils/modprobe.c (working copy) +@@ -13,23 +13,23 @@ + #include + #include + +-struct modprobe_option { ++#define MODULE_FLAG_LOADED 0x0001 ++#define MODULE_FLAG_EXISTS 0x0002 ++#define MODULE_FLAG_BLACKLISTED 0x0004 ++ ++struct module_entry { + char *module; +- char *option; ++ const char *probe; ++ unsigned int flags; ++ llist_t *aliases; ++ llist_t *options; ++ llist_t *deps; + }; + + struct modprobe_conf { +- char probename[MODULE_NAME_LEN]; ++ llist_t *db; ++ llist_t *probes; + llist_t *options; +- llist_t *aliases; +-#if ENABLE_FEATURE_MODPROBE_BLACKLIST +-#define add_to_blacklist(conf, name) llist_add_to(&conf->blacklist, name) +-#define check_blacklist(conf, name) (llist_find(conf->blacklist, name) == NULL) +- llist_t *blacklist; +-#else +-#define add_to_blacklist(conf, name) do {} while (0) +-#define check_blacklist(conf, name) (1) +-#endif + }; + + #define MODPROBE_OPTS "acdlnrt:VC:" USE_FEATURE_MODPROBE_BLACKLIST("b") +@@ -46,21 +46,40 @@ + MODPROBE_OPT_BLACKLIST = (INSMOD_OPT_UNUSED << 9) * ENABLE_FEATURE_MODPROBE_BLACKLIST, + }; + +-static llist_t *loaded; +- + static int read_config(struct modprobe_conf *conf, const char *path); + +-static void add_option(llist_t **all_opts, const char *module, const char *opts) ++static struct module_entry *get_module(llist_t **db, const char *module) + { +- struct modprobe_option *o; ++ char modname[MODULE_NAME_LEN]; ++ struct module_entry *e; ++ llist_t *l; + +- o = xzalloc(sizeof(struct modprobe_option)); +- if (module) +- o->module = filename2modname(module, NULL); +- o->option = xstrdup(opts); +- llist_add_to(all_opts, o); ++ filename2modname(module, modname); ++ for (l = *db; l != NULL; l = l->link) { ++ e = (struct module_entry *) l->data; ++ if (strcmp(e->module, modname) == 0) ++ return e; ++ } ++ ++ e = xzalloc(sizeof(*e)); ++ e->module = xstrdup(modname); ++ llist_add_to(db, e); ++ ++ return e; + } + ++static struct module_entry *add_probe(struct modprobe_conf *conf, ++ const char *name) ++{ ++ struct module_entry *m; ++ ++ m = get_module(&conf->db, name); ++ m->probe = name; ++ llist_add_to(&conf->probes, m); ++ ++ return m; ++} ++ + static int FAST_FUNC config_file_action(const char *filename, + struct stat *statbuf UNUSED_PARAM, + void *userdata, +@@ -70,6 +89,8 @@ + RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN); + char *tokens[3]; + parser_t *p; ++ llist_t *l; ++ struct module_entry *m; + int rc = TRUE; + + if (bb_basename(filename)[0] == '.') +@@ -84,18 +105,27 @@ + while (config_read(p, tokens, 3, 2, "# \t", PARSE_NORMAL)) { + if (strcmp(tokens[0], "alias") == 0) { + filename2modname(tokens[1], modname); +- if (tokens[2] && +- fnmatch(modname, conf->probename, 0) == 0) +- llist_add_to(&conf->aliases, +- filename2modname(tokens[2], NULL)); ++ if (tokens[2] == NULL) ++ continue; ++ ++ for (l = conf->probes; l != NULL; l = l->link) { ++ m = (struct module_entry *) l->data; ++ if (fnmatch(modname, m->module, 0) != 0) ++ continue; ++ llist_add_to(&m->aliases, ++ filename2modname(tokens[2], NULL)); ++ } + } else if (strcmp(tokens[0], "options") == 0) { +- if (tokens[2]) +- add_option(&conf->options, tokens[1], tokens[2]); ++ if (tokens[2] == NULL) ++ continue; ++ m = get_module(&conf->db, tokens[1]); ++ llist_add_to(&m->options, xstrdup(tokens[2])); + } else if (strcmp(tokens[0], "include") == 0) { + read_config(conf, tokens[1]); + } else if (ENABLE_FEATURE_MODPROBE_BLACKLIST && + strcmp(tokens[0], "blacklist") == 0) { +- add_to_blacklist(conf, xstrdup(tokens[1])); ++ get_module(&conf->db, tokens[1])->flags ++ |= MODULE_FLAG_BLACKLISTED; + } + } + config_close(p); +@@ -111,74 +141,48 @@ + config_file_action, NULL, conf, 1); + } + +-static char *gather_options(llist_t *first, const char *module, int usecmdline) ++static char *gather_options(char *opts, llist_t *o) + { +- struct modprobe_option *opt; +- llist_t *n; +- char *opts = xstrdup(""); +- int optlen = 0; ++ int optlen; + +- for (n = first; n != NULL; n = n->link) { +- opt = (struct modprobe_option *) n->data; ++ if (opts == NULL) ++ opts = xstrdup(""); ++ optlen = strlen(opts); + +- if (opt->module == NULL && !usecmdline) +- continue; +- if (opt->module != NULL && strcmp(opt->module, module) != 0) +- continue; +- +- opts = xrealloc(opts, optlen + strlen(opt->option) + 2); +- optlen += sprintf(opts + optlen, "%s ", opt->option); ++ for (; o != NULL; o = o->link) { ++ opts = xrealloc(opts, optlen + strlen(o->data) + 2); ++ optlen += sprintf(opts + optlen, "%s ", o->data); + } + return opts; + } + +-static int do_modprobe(struct modprobe_conf *conf, const char *module) ++static int do_modprobe(struct modprobe_conf *conf, struct module_entry *m) + { +- RESERVE_CONFIG_BUFFER(modname, MODULE_NAME_LEN); +- llist_t *deps = NULL; +- char *fn, *options, *colon = NULL, *tokens[2]; +- parser_t *p; ++ struct module_entry *m2; ++ char *fn, *options; + int rc = -1; + +- p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, fopen_for_read); +- if (p == NULL) +- goto error; ++ if (!(m->flags & MODULE_FLAG_EXISTS)) ++ return -ENOENT; + +- while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) { +- colon = last_char_is(tokens[0], ':'); +- if (colon == NULL) +- continue; +- +- filename2modname(tokens[0], modname); +- if (strcmp(modname, module) == 0) +- break; +- +- colon = NULL; +- } +- if (colon == NULL) +- goto error_not_found; +- +- colon[0] = '\0'; +- llist_add_to(&deps, xstrdup(tokens[0])); +- if (tokens[1]) +- string_to_llist(tokens[1], &deps, " "); +- + if (!(option_mask32 & MODPROBE_OPT_REMOVE)) +- deps = llist_rev(deps); ++ m->deps = llist_rev(m->deps); + + rc = 0; +- while (deps && rc == 0) { +- fn = llist_pop(&deps); +- filename2modname(fn, modname); ++ while (m->deps && rc == 0) { ++ fn = llist_pop(&m->deps); ++ m2 = get_module(&conf->db, fn); + if (option_mask32 & MODPROBE_OPT_REMOVE) { +- if (bb_delete_module(modname, O_EXCL) != 0) ++ if (bb_delete_module(m->module, O_EXCL) != 0) + rc = errno; +- } else if (llist_find(loaded, modname) == NULL) { +- options = gather_options(conf->options, modname, +- strcmp(modname, module) == 0); ++ } else if (!(m2->flags & MODULE_FLAG_LOADED)) { ++ options = gather_options(NULL, m2->options); ++ if (m == m2) ++ options = gather_options(options, ++ conf->options); + rc = bb_init_module(fn, options); + if (rc == 0) +- llist_add_to(&loaded, xstrdup(modname)); ++ m2->flags |= MODULE_FLAG_LOADED; + if (ENABLE_FEATURE_CLEAN_UP) + free(options); + } +@@ -187,15 +191,10 @@ + free(fn); + } + +-error_not_found: +- config_close(p); +-error: +- if (ENABLE_FEATURE_CLEAN_UP) +- RELEASE_CONFIG_BUFFER(modname); + if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT)) + bb_error_msg("Failed to %sload module %s: %s.", + (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "", +- module, moderror(rc)); ++ m->probe ? m->probe : m->module, moderror(rc)); + return rc; + } + +@@ -205,7 +204,8 @@ + struct utsname uts; + int rc; + unsigned opt; +- llist_t *options = NULL; ++ struct modprobe_conf conf; ++ struct module_entry *m, *m2; + + opt_complementary = "q-v:v-q"; + opt = getopt32(argv, INSMOD_OPTS MODPROBE_OPTS INSMOD_ARGS, +@@ -228,11 +228,17 @@ + } + return EXIT_SUCCESS; + } +- if (!(opt & MODPROBE_OPT_INSERT_ALL)) { +- /* If not -a, we have only one module name, +- * the rest of parameters are options */ +- add_option(&options, NULL, parse_cmdline_module_options(argv)); +- argv[1] = NULL; ++ ++ memset(&conf, 0, sizeof(conf)); ++ if (opt & MODPROBE_OPT_INSERT_ALL) { ++ /* Each argument is a module name */ ++ for (; *argv != NULL; argv++) ++ add_probe(&conf, *argv); ++ conf.probes = llist_rev(conf.probes); ++ } else { ++ /* First argument is module name, rest are parameters */ ++ m = add_probe(&conf, argv[0]); ++ llist_add_to(&conf.options, parse_cmdline_module_options(argv)); + } + + /* cache modules */ +@@ -240,49 +246,59 @@ + char *s; + parser_t *parser = config_open2("/proc/modules", fopen_for_read); + while (config_read(parser, &s, 1, 1, "# \t", PARSE_NORMAL & ~PARSE_GREEDY)) +- llist_add_to(&loaded, xstrdup(s)); ++ get_module(&conf.db, s)->flags |= MODULE_FLAG_LOADED; + config_close(parser); + } + +- while (*argv) { +- const char *arg = *argv; +- struct modprobe_conf *conf; ++ read_config(&conf, "/etc/modprobe.conf"); ++ read_config(&conf, "/etc/modprobe.d"); ++ if (ENABLE_FEATURE_MODUTILS_SYMBOLS) ++ read_config(&conf, "modules.symbols"); ++ if (ENABLE_FEATURE_MODUTILS_ALIAS) ++ read_config(&conf, "modules.alias"); + +- conf = xzalloc(sizeof(*conf)); +- conf->options = options; +- filename2modname(arg, conf->probename); +- read_config(conf, "/etc/modprobe.conf"); +- read_config(conf, "/etc/modprobe.d"); +- if (ENABLE_FEATURE_MODUTILS_SYMBOLS +- && conf->aliases == NULL +- && strncmp(arg, "symbol:", 7) == 0 +- ) { +- read_config(conf, "modules.symbols"); ++ { ++ parser_t *p; ++ char *colon, *tokens[2]; ++ ++ p = config_open2(CONFIG_DEFAULT_DEPMOD_FILE, xfopen_for_read); ++ while (config_read(p, tokens, 2, 1, "# \t", PARSE_NORMAL)) { ++ colon = last_char_is(tokens[0], ':'); ++ if (colon == NULL) ++ continue; ++ *colon = 0; ++ ++ m = get_module(&conf.db, tokens[0]); ++ m->flags |= MODULE_FLAG_EXISTS; ++ llist_add_to(&m->deps, xstrdup(tokens[0])); ++ if (tokens[1]) ++ string_to_llist(tokens[1], &m->deps, " "); + } ++ config_close(p); ++ } + +- if (ENABLE_FEATURE_MODUTILS_ALIAS && conf->aliases == NULL) +- read_config(conf, "modules.alias"); +- +- if (conf->aliases == NULL) { ++ while ((m = llist_pop(&conf.probes)) != NULL) { ++ if (m->aliases == NULL) { + /* Try if module by literal name is found; literal + * names are blacklist only if '-b' is given. */ + if (!(opt & MODPROBE_OPT_BLACKLIST) || +- check_blacklist(conf, conf->probename)) { +- rc = do_modprobe(conf, conf->probename); ++ !(m->flags & MODULE_FLAG_BLACKLISTED)) { ++ rc = do_modprobe(&conf, m); + if (rc < 0 && !(opt & INSMOD_OPT_SILENT)) +- bb_error_msg("Module %s not found.", arg); ++ bb_error_msg("module %s not found", ++ m->probe); + } + } else { + /* Probe all aliases */ +- while (conf->aliases != NULL) { +- char *realname = llist_pop(&conf->aliases); +- if (check_blacklist(conf, realname)) +- do_modprobe(conf, realname); ++ while (m->aliases != NULL) { ++ char *realname = llist_pop(&m->aliases); ++ m2 = get_module(&conf.db, realname); ++ if (!(m2->flags & MODULE_FLAG_BLACKLISTED)) ++ do_modprobe(&conf, m2); + if (ENABLE_FEATURE_CLEAN_UP) + free(realname); + } + } +- argv++; + } + + return EXIT_SUCCESS; -- cgit v1.2.3