From: Tony Ambardar Date: Thu, 14 Dec 2023 07:18:30 +0000 (-0800) Subject: kmodloader: add basic support for builtin modules X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=4ffc29e4041ca1b5d6b0f007859394c23fba034e;p=project%2Fubox.git kmodloader: add basic support for builtin modules Enable parsing of 'modules.builtin' if present, for improved handling of loadable and builtin modules similar to most other distros. In particular, this allows 'modprobe' to return success whether a module is loadable or built-in, a useful feature for consistent presence-testing. For example: root@OpenWrt:/# rmmod sch_fq_codel module is builtin root@OpenWrt:/# modinfo sch_cake filename: /lib/modules/6.1.65/sch_cake.ko license: Dual BSD/GPL depends: intree: Y name: sch_cake vermagic: 6.1.65 SMP mod_unload MIPS32_R2 32BIT root@OpenWrt:/# modprobe sch_fq_codel && echo SUCCESS || echo FAIL SUCCESS root@OpenWrt:/# modprobe sch_cake && echo SUCCESS || echo FAIL SUCCESS Signed-off-by: Tony Ambardar --- diff --git a/kmodloader.c b/kmodloader.c index 8d06ff1..179517e 100644 --- a/kmodloader.c +++ b/kmodloader.c @@ -40,6 +40,7 @@ #include #define DEF_MOD_PATH "/modules/%s/" +#define MOD_BUILTIN "modules.builtin" /* duplicated from in-kernel include/linux/module.h */ #define MODULE_NAME_LEN (64 - sizeof(unsigned long)) @@ -51,6 +52,7 @@ struct param { }; enum { + BUILTIN, SCANNED, PROBE, LOADED, @@ -439,6 +441,57 @@ out: return m; } +static int scan_builtin_modules(void) +{ + char **p, path[350]; + size_t buf_len = 0; + char *buf = NULL; + struct stat st; + FILE *fp = NULL; + int rv = -1; + + if (!module_folders && init_module_folders()) + goto err; + for (p = module_folders; *p; p++) { + snprintf(path, sizeof(path), "%s%s", *p, MOD_BUILTIN); + if (!stat(path, &st) && S_ISREG(st.st_mode)) { + fp = fopen(path, "r"); + if (fp) + break; + } + } + if (!fp) + goto out; /* OK if modules.builtin unavailable */ + + while (getline(&buf, &buf_len, fp) > 0) { + struct module *m; + char *name; + + name = get_module_name(buf); + if (!name) + continue; + m = find_module(name); + if (m && !strcmp(m->name, name)) { + ULOG_WARN("found duplicate builtin module %s\n", name); + continue; + } + m = alloc_module(name, NULL, 0, NULL, 0); + if (!m) { + ULOG_ERR("failed to allocate memory for module\n"); + goto err; + } + + m->state = BUILTIN; + } +out: + rv = 0; +err: + free(buf); + fclose(fp); + + return rv; +} + static int scan_module_folder(const char *dir) { int gl_flags = GLOB_NOESCAPE | GLOB_MARK; @@ -856,12 +909,19 @@ static int main_rmmod(int argc, char **argv) if (scan_loaded_modules()) return -1; + if (scan_builtin_modules()) + return -1; + name = get_module_name(argv[1]); m = find_module(name); if (!m) { ULOG_ERR("module is not loaded\n"); return -1; } + if (m->state == BUILTIN) { + ULOG_ERR("module is builtin\n"); + return -1; + } ret = syscall(__NR_delete_module, m->name, 0); if (ret) @@ -975,6 +1035,9 @@ static int main_modprobe(int argc, char **argv) if (scan_loaded_modules()) return -1; + if (scan_builtin_modules()) + return -1; + do { char *name; @@ -987,6 +1050,9 @@ static int main_modprobe(int argc, char **argv) } else if (m && m->state == LOADED) { if (!quiet) ULOG_INFO("%s is already loaded\n", name); + } else if (m && m->state == BUILTIN) { + if (!quiet) + ULOG_INFO("%s is builtin\n", name); } else if (!m) { if (!quiet) ULOG_ERR("failed to find a module named %s\n", name);