From: Brian Gerst This patch removes the default stubs for init_module and cleanup_module, and checks for NULL instead. It changes modpost to only create references to those functions if they actually exist. Signed-off-by: Andrew Morton --- 25-akpm/kernel/module.c | 30 ++++++++++-------------------- 25-akpm/scripts/mod/modpost.c | 29 +++++++++++++---------------- 25-akpm/scripts/mod/modpost.h | 2 ++ 3 files changed, 25 insertions(+), 36 deletions(-) diff -puN kernel/module.c~remove-in-kernel-init_module-cleanup_module-stubs kernel/module.c --- 25/kernel/module.c~remove-in-kernel-init_module-cleanup_module-stubs 2004-09-02 21:05:41.809844856 -0700 +++ 25-akpm/kernel/module.c 2004-09-02 21:05:41.818843488 -0700 @@ -89,13 +89,6 @@ static inline int strong_try_module_get( return try_module_get(mod); } -/* Stub function for modules which don't have an initfn */ -int init_module(void) -{ - return 0; -} -EXPORT_SYMBOL(init_module); - /* A thread that wants to hold a reference to a module only while it * is running can call ths to safely exit. * nfsd and lockd use this. @@ -529,12 +522,6 @@ EXPORT_SYMBOL(module_refcount); /* This exists whether we can unload or not */ static void free_module(struct module *mod); -/* Stub function for modules which don't have an exitfn */ -void cleanup_module(void) -{ -} -EXPORT_SYMBOL(cleanup_module); - static void wait_for_zero_refcount(struct module *mod) { /* Since we might sleep for some time, drop the semaphore first */ @@ -589,7 +576,7 @@ sys_delete_module(const char __user *nam } /* If it has an init func, it must have an exit func to unload */ - if ((mod->init != init_module && mod->exit == cleanup_module) + if ((mod->init != NULL && mod->exit == NULL) || mod->unsafe) { forced = try_force(flags); if (!forced) { @@ -610,9 +597,11 @@ sys_delete_module(const char __user *nam wait_for_zero_refcount(mod); /* Final destruction now noone is using it. */ - up(&module_mutex); - mod->exit(); - down(&module_mutex); + if (mod->exit != NULL) { + up(&module_mutex); + mod->exit(); + down(&module_mutex); + } free_module(mod); out: @@ -639,7 +628,7 @@ static void print_unload_info(struct seq seq_printf(m, "[unsafe],"); } - if (mod->init != init_module && mod->exit == cleanup_module) { + if (mod->init != NULL && mod->exit == NULL) { printed_something = 1; seq_printf(m, "[permanent],"); } @@ -1836,7 +1825,7 @@ sys_init_module(void __user *umod, const char __user *uargs) { struct module *mod; - int ret; + int ret = 0; /* Must have permission */ if (!capable(CAP_SYS_MODULE)) @@ -1875,7 +1864,8 @@ sys_init_module(void __user *umod, up(¬ify_mutex); /* Start the module */ - ret = mod->init(); + if (mod->init != NULL) + ret = mod->init(); if (ret < 0) { /* Init routine failed: abort. Try to protect us from buggy refcounters. */ diff -puN scripts/mod/modpost.c~remove-in-kernel-init_module-cleanup_module-stubs scripts/mod/modpost.c --- 25/scripts/mod/modpost.c~remove-in-kernel-init_module-cleanup_module-stubs 2004-09-02 21:05:41.810844704 -0700 +++ 25-akpm/scripts/mod/modpost.c 2004-09-02 21:05:41.820843184 -0700 @@ -376,6 +376,10 @@ handle_modversions(struct module *mod, s add_exported_symbol(symname + strlen(KSYMTAB_PFX), mod, NULL); } + if (strcmp(symname, MODULE_SYMBOL_PREFIX "init_module") == 0) + mod->has_init = 1; + if (strcmp(symname, MODULE_SYMBOL_PREFIX "cleanup_module") == 0) + mod->has_cleanup = 1; break; } } @@ -410,9 +414,6 @@ read_symbols(char *modname) if (is_vmlinux(modname)) { unsigned int fake_crc = 0; have_vmlinux = 1; - /* May not have this if !CONFIG_MODULE_UNLOAD: fake it. - If it appears, we'll get the real CRC. */ - add_exported_symbol("cleanup_module", mod, &fake_crc); add_exported_symbol("struct_module", mod, &fake_crc); mod->skip = 1; } @@ -431,14 +432,8 @@ read_symbols(char *modname) * never passed as an argument to an exported function, so * the automatic versioning doesn't pick it up, but it's really * important anyhow */ - if (modversions) { + if (modversions) mod->unres = alloc_symbol("struct_module", mod->unres); - - /* Always version init_module and cleanup_module, in - * case module doesn't have its own. */ - mod->unres = alloc_symbol("init_module", mod->unres); - mod->unres = alloc_symbol("cleanup_module", mod->unres); - } } #define SZ 500 @@ -479,7 +474,7 @@ buf_write(struct buffer *buf, const char /* Header for the generated file */ void -add_header(struct buffer *b) +add_header(struct buffer *b, struct module *mod) { buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); @@ -491,10 +486,12 @@ add_header(struct buffer *b) buf_printf(b, "struct module __this_module\n"); buf_printf(b, "__attribute__((section(\".gnu.linkonce.this_module\"))) = {\n"); buf_printf(b, " .name = __stringify(KBUILD_MODNAME),\n"); - buf_printf(b, " .init = init_module,\n"); - buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n"); - buf_printf(b, " .exit = cleanup_module,\n"); - buf_printf(b, "#endif\n"); + if (mod->has_init) + buf_printf(b, " .init = init_module,\n"); + if (mod->has_cleanup) + buf_printf(b, "#ifdef CONFIG_MODULE_UNLOAD\n" + " .exit = cleanup_module,\n" + "#endif\n"); buf_printf(b, "};\n"); } @@ -723,7 +720,7 @@ main(int argc, char **argv) buf.pos = 0; - add_header(&buf); + add_header(&buf, mod); add_versions(&buf, mod); add_depends(&buf, mod, modules); add_moddevtable(&buf, mod); diff -puN scripts/mod/modpost.h~remove-in-kernel-init_module-cleanup_module-stubs scripts/mod/modpost.h --- 25/scripts/mod/modpost.h~remove-in-kernel-init_module-cleanup_module-stubs 2004-09-02 21:05:41.812844400 -0700 +++ 25-akpm/scripts/mod/modpost.h 2004-09-02 21:05:41.820843184 -0700 @@ -74,6 +74,8 @@ struct module { struct symbol *unres; int seen; int skip; + int has_init; + int has_cleanup; struct buffer dev_table_buf; }; _