Since the addition of modules.aliases.bin, depmod has to open that index multiple times and parse it over and over again: $ sudo strace -e openat ./tools/depmod 2>&1 | grep modules.builtin.modinfo | wc -l 299 $ time sudo ./tools/depmod real 0m7.814s user 0m7.571s sys 0m0.237s Rework the logic in depmod so it does everything: open, read and parse. The format is very straightforward and we don't need to keep it in a data structure since we only want to add the result to a index. New output: $ sudo strace -e openat ./tools/depmod 2>&1 | grep modules.builtin.modinfo | wc -l 1 $ time sudo ./tools/depmod real 0m7.663s user 0m7.516s sys 0m0.139s Indexes still match: $ cmp /tmp/modules.builtin.alias.bin.new /tmp/modules.builtin.alias.bin.old; echo $? 0 Fix: https://github.com/kmod-project/kmod/issues/11 --- tools/depmod.c | 158 ++++++++++++++++++++++++++++++------------------- 1 file changed, 96 insertions(+), 62 deletions(-) diff --git a/tools/depmod.c b/tools/depmod.c index ac6ead8..07a35ba 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -2346,6 +2346,102 @@ static int output_builtin_bin(struct depmod *depmod, FILE *out) return 0; } +static int flush_stream(FILE *in, int endchar) +{ + size_t i = 0; + int c; + + for (c = fgetc(in); + c != EOF && c != endchar && c != '\0'; + c = fgetc(in)) + ; + + return c == endchar ? i : 0; +} + +static int flush_stream_to(FILE *in, int endchar, char *dst, size_t dst_sz) +{ + size_t i = 0; + int c; + + for (c = fgetc(in); + c != EOF && c != endchar && c != '\0' && i < dst_sz; + c = fgetc(in)) + dst[i++] = c; + + if (i == dst_sz) { + WRN("Could not flush stream: %d. Partial content: %.*s\n", + ENOSPC, (int) dst_sz, dst); + } + + return c == endchar ? i : 0; +} + +static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) +{ + FILE *in; + struct index_node *idx; + int ret; + + if (out == stdout) + return 0; + + in = dfdopen(depmod->cfg->dirname, "modules.builtin.modinfo", O_RDONLY, "r"); + if (in == NULL) + return 0; + + idx = index_create(); + if (idx == NULL) { + fclose(in); + return -ENOMEM; + } + + /* format: modname.key=value\0 */ + while (!feof(in) && !ferror(in)) { + char alias[PATH_MAX]; + char modname[PATH_MAX]; + char value[PATH_MAX]; + size_t len; + + len = flush_stream_to(in, '.', modname, sizeof(modname)); + modname[len] = '\0'; + if (!len) + continue; + + len = flush_stream_to(in, '=', value, sizeof(value)); + value[len] = '\0'; + if (!streq(value, "alias")) { + flush_stream(in, '\0'); + continue; + } + + len = flush_stream_to(in, '\0', value, sizeof(value)); + value[len] = '\0'; + if (!len) + continue; + + alias[0] = '\0'; + if (alias_normalize(value, alias, NULL) < 0) { + WRN("Unmatched bracket in %s\n", value); + continue; + } + + index_insert(idx, alias, modname, 0); + } + + if (ferror(in)) { + ret = -EINVAL; + } else { + index_write(idx, out); + ret = 0; + } + + index_destroy(idx); + fclose(in); + + return ret; +} + static int output_devname(struct depmod *depmod, FILE *out) { size_t i; @@ -2403,68 +2499,6 @@ static int output_devname(struct depmod *depmod, FILE *out) return 0; } -static int output_builtin_alias_bin(struct depmod *depmod, FILE *out) -{ - int ret = 0; - struct index_node *idx; - struct kmod_list *l, *builtin = NULL; - - if (out == stdout) - return 0; - - idx = index_create(); - if (idx == NULL) - return -ENOMEM; - - ret = kmod_module_get_builtin(depmod->ctx, &builtin); - if (ret < 0) { - if (ret == -ENOENT) - ret = 0; - goto out; - } - - kmod_list_foreach(l, builtin) { - struct kmod_list *ll, *info_list = NULL; - struct kmod_module *mod = l->data; - const char *modname = kmod_module_get_name(mod); - - ret = kmod_module_get_info(mod, &info_list); - if (ret < 0) - goto out; - - kmod_list_foreach(ll, info_list) { - char alias[PATH_MAX]; - const char *key = kmod_module_info_get_key(ll); - const char *value = kmod_module_info_get_value(ll); - - if (!streq(key, "alias")) - continue; - - alias[0] = '\0'; - if (alias_normalize(value, alias, NULL) < 0) { - WRN("Unmatched bracket in %s\n", value); - continue; - } - - index_insert(idx, alias, modname, 0); - } - - kmod_module_info_free_list(info_list); - } - -out: - /* do not bother writing the index if we are going to discard it */ - if (ret > 0) - index_write(idx, out); - - if (builtin) - kmod_module_unref_list(builtin); - - index_destroy(idx); - - return ret; -} - static int depmod_output(struct depmod *depmod, FILE *out) { static const struct depfile { -- 2.35.1