Symbols can be exported in namespaces and to make use of such symbols, the namespace has to be explicitly imported. Importing a namespace without actually using one of its symbols is likely a mistake. There are a few offenders for an x86_64 allmodconfig build, so the warning is (for now) only enabled for W=1 builds. Signed-off-by: Uwe Kleine-König <u.kleine-koenig@xxxxxxxxxxxx> --- Hello, one of the offenders is drivers/pwm/pwm-raspberrypi-poe.c ( WARNING: modpost: module pwm-raspberrypi-poe imports namespace PWM, but doesn't use it. ). The issue there is that on x86_64 CONFIG_RASPBERRYPI_FIRMWARE is always disabled and so devm_rpi_firmware_get() returns always NULL which makes raspberrypi_pwm_probe return an error before the pwm functions are used. So the compiler optimizes out all references to pwm functions and the warning triggers. I didn't look into the other problems to check if these are similar half-false positives. Still I think this is a useful check? Best regards Uwe scripts/mod/modpost.c | 60 +++++++++++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e18ae7dc8140..ef5a5e9718f3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -268,13 +268,28 @@ static struct symbol *find_symbol(const char *name) struct namespace_list { struct list_head list; + bool used; char namespace[]; }; +static struct namespace_list *find_namespace_entry(struct list_head *head, + const char *namespace) +{ + struct namespace_list *ns_entry; + + if (!namespace[0]) + return NULL; + + list_for_each_entry(ns_entry, head, list) { + if (!strcmp(ns_entry->namespace, namespace)) + return ns_entry; + } + + return NULL; +} + static bool contains_namespace(struct list_head *head, const char *namespace) { - struct namespace_list *list; - /* * The default namespace is null string "", which is always implicitly * contained. @@ -282,21 +297,20 @@ static bool contains_namespace(struct list_head *head, const char *namespace) if (!namespace[0]) return true; - list_for_each_entry(list, head, list) { - if (!strcmp(list->namespace, namespace)) - return true; - } + if (find_namespace_entry(head, namespace)) + return true; return false; } -static void add_namespace(struct list_head *head, const char *namespace) +static void add_namespace(struct list_head *head, const char *namespace, bool used) { struct namespace_list *ns_entry; if (!contains_namespace(head, namespace)) { ns_entry = xmalloc(sizeof(*ns_entry) + strlen(namespace) + 1); strcpy(ns_entry->namespace, namespace); + ns_entry->used = used; list_add_tail(&ns_entry->list, head); } } @@ -1580,7 +1594,7 @@ static void read_symbols(const char *modname) namespace = get_modinfo(&info, "import_ns"); while (namespace) { - add_namespace(&mod->imported_namespaces, namespace); + add_namespace(&mod->imported_namespaces, namespace, false); namespace = get_next_modinfo(&info, "import_ns", namespace); } @@ -1670,9 +1684,16 @@ void buf_write(struct buffer *buf, const char *s, int len) static void check_exports(struct module *mod) { struct symbol *s, *exp; + struct namespace_list *ns_entry; + const char *basename; + + basename = strrchr(mod->name, '/'); + if (basename) + basename++; + else + basename = mod->name; list_for_each_entry(s, &mod->unresolved_symbols, list) { - const char *basename; exp = find_symbol(s->name); if (!exp) { if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS) @@ -1692,23 +1713,30 @@ static void check_exports(struct module *mod) s->crc_valid = exp->crc_valid; s->crc = exp->crc; - basename = strrchr(mod->name, '/'); - if (basename) - basename++; - else - basename = mod->name; + ns_entry = find_namespace_entry(&mod->imported_namespaces, exp->namespace); - if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) { + if (exp->namespace[0] && !ns_entry) { modpost_log(!allow_missing_ns_imports, "module %s uses symbol %s from namespace %s, but does not import it.\n", basename, exp->name, exp->namespace); - add_namespace(&mod->missing_namespaces, exp->namespace); + add_namespace(&mod->missing_namespaces, exp->namespace, true); + } else if (ns_entry) { + ns_entry->used = true; } if (!mod->is_gpl_compatible && exp->is_gpl_only) error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", basename, exp->name); } + + if (extra_warn) { + list_for_each_entry(ns_entry, &mod->imported_namespaces, list) { + if (!ns_entry->used) + modpost_log(false, + "module %s imports namespace %s, but doesn't use it.\n", + basename, ns_entry->namespace); + } + } } static void handle_white_list_exports(const char *white_list) base-commit: 232f121837ad8b1c21cc80f2c8842a4090c5a2a0 -- 2.47.1