diff options
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/kernel/module.c b/kernel/module.c index dcb8a2cbf75e..1bb4c5e0d56e 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -496,6 +496,8 @@ static struct module_attribute modinfo_##field = { \ | |||
496 | MODINFO_ATTR(version); | 496 | MODINFO_ATTR(version); |
497 | MODINFO_ATTR(srcversion); | 497 | MODINFO_ATTR(srcversion); |
498 | 498 | ||
499 | static char last_unloaded_module[MODULE_NAME_LEN+1]; | ||
500 | |||
499 | #ifdef CONFIG_MODULE_UNLOAD | 501 | #ifdef CONFIG_MODULE_UNLOAD |
500 | /* Init the unload section of the module. */ | 502 | /* Init the unload section of the module. */ |
501 | static void module_unload_init(struct module *mod) | 503 | static void module_unload_init(struct module *mod) |
@@ -719,6 +721,8 @@ sys_delete_module(const char __user *name_user, unsigned int flags) | |||
719 | mod->exit(); | 721 | mod->exit(); |
720 | mutex_lock(&module_mutex); | 722 | mutex_lock(&module_mutex); |
721 | } | 723 | } |
724 | /* Store the name of the last unloaded module for diagnostic purposes */ | ||
725 | sprintf(last_unloaded_module, mod->name); | ||
722 | free_module(mod); | 726 | free_module(mod); |
723 | 727 | ||
724 | out: | 728 | out: |
@@ -2357,21 +2361,30 @@ static void m_stop(struct seq_file *m, void *p) | |||
2357 | mutex_unlock(&module_mutex); | 2361 | mutex_unlock(&module_mutex); |
2358 | } | 2362 | } |
2359 | 2363 | ||
2360 | static char *taint_flags(unsigned int taints, char *buf) | 2364 | static char *module_flags(struct module *mod, char *buf) |
2361 | { | 2365 | { |
2362 | int bx = 0; | 2366 | int bx = 0; |
2363 | 2367 | ||
2364 | if (taints) { | 2368 | if (mod->taints || |
2369 | mod->state == MODULE_STATE_GOING || | ||
2370 | mod->state == MODULE_STATE_COMING) { | ||
2365 | buf[bx++] = '('; | 2371 | buf[bx++] = '('; |
2366 | if (taints & TAINT_PROPRIETARY_MODULE) | 2372 | if (mod->taints & TAINT_PROPRIETARY_MODULE) |
2367 | buf[bx++] = 'P'; | 2373 | buf[bx++] = 'P'; |
2368 | if (taints & TAINT_FORCED_MODULE) | 2374 | if (mod->taints & TAINT_FORCED_MODULE) |
2369 | buf[bx++] = 'F'; | 2375 | buf[bx++] = 'F'; |
2370 | /* | 2376 | /* |
2371 | * TAINT_FORCED_RMMOD: could be added. | 2377 | * TAINT_FORCED_RMMOD: could be added. |
2372 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't | 2378 | * TAINT_UNSAFE_SMP, TAINT_MACHINE_CHECK, TAINT_BAD_PAGE don't |
2373 | * apply to modules. | 2379 | * apply to modules. |
2374 | */ | 2380 | */ |
2381 | |||
2382 | /* Show a - for module-is-being-unloaded */ | ||
2383 | if (mod->state == MODULE_STATE_GOING) | ||
2384 | buf[bx++] = '-'; | ||
2385 | /* Show a + for module-is-being-loaded */ | ||
2386 | if (mod->state == MODULE_STATE_COMING) | ||
2387 | buf[bx++] = '+'; | ||
2375 | buf[bx++] = ')'; | 2388 | buf[bx++] = ')'; |
2376 | } | 2389 | } |
2377 | buf[bx] = '\0'; | 2390 | buf[bx] = '\0'; |
@@ -2398,7 +2411,7 @@ static int m_show(struct seq_file *m, void *p) | |||
2398 | 2411 | ||
2399 | /* Taints info */ | 2412 | /* Taints info */ |
2400 | if (mod->taints) | 2413 | if (mod->taints) |
2401 | seq_printf(m, " %s", taint_flags(mod->taints, buf)); | 2414 | seq_printf(m, " %s", module_flags(mod, buf)); |
2402 | 2415 | ||
2403 | seq_printf(m, "\n"); | 2416 | seq_printf(m, "\n"); |
2404 | return 0; | 2417 | return 0; |
@@ -2493,7 +2506,9 @@ void print_modules(void) | |||
2493 | 2506 | ||
2494 | printk("Modules linked in:"); | 2507 | printk("Modules linked in:"); |
2495 | list_for_each_entry(mod, &modules, list) | 2508 | list_for_each_entry(mod, &modules, list) |
2496 | printk(" %s%s", mod->name, taint_flags(mod->taints, buf)); | 2509 | printk(" %s%s", mod->name, module_flags(mod, buf)); |
2510 | if (last_unloaded_module[0]) | ||
2511 | printk(" [last unloaded: %s]", last_unloaded_module); | ||
2497 | printk("\n"); | 2512 | printk("\n"); |
2498 | } | 2513 | } |
2499 | 2514 | ||