From 518538b3446367487ff8fc3e8de5fc22076b5b8a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 18 Jul 2003 05:23:14 -0700 Subject: [PATCH] Resolve module local_t conflict Uses local_t for module reference counts. --- include/linux/module.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/include/linux/module.h b/include/linux/module.h index 1d48f23a8a6a..d12463033162 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -171,7 +172,7 @@ void *__symbol_get_gpl(const char *symbol); struct module_ref { - atomic_t count; + local_t count; } ____cacheline_aligned; enum module_state @@ -283,12 +284,6 @@ void __symbol_put(const char *symbol); #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) void symbol_put_addr(void *addr); -/* We only need protection against local interrupts. */ -#ifndef __HAVE_ARCH_LOCAL_INC -#define local_inc(x) atomic_inc(x) -#define local_dec(x) atomic_dec(x) -#endif - /* Sometimes we know we already have a refcount, and it's easier not to handle the error case (which only happens with rmmod --wait). */ static inline void __module_get(struct module *module) -- cgit v1.2.3 From f965803d21981208b5d483414e3c6b797363f37a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 18 Jul 2003 05:23:37 -0700 Subject: [PATCH] module_put_and_exit Author: Neil Brown Define module_put_and_exit() and use it for nfsd/lockd Both nfsd and lockd have threads which expect to hold a reference to the module while the thread is running. In order for the thread to be able to put_module() the module before exiting, the put_module code must be call from outside the module. This patch provides module_put_and_exit in non-modular code which a thread-in-a-module can call. It also gets nfsd and lockd to use it as appropriate. Note that in lockd, we can __get_module in the thread itself as the creator of the thread is waiting for the thread to startup. In nfsd and for the 'reclaimer' threaded started by locked, we __get_module first and put_module if the thread failed to start. --- fs/lockd/clntlock.c | 9 ++++----- fs/lockd/svc.c | 8 ++++++-- fs/nfsd/nfssvc.c | 8 +++++--- include/linux/module.h | 8 +++++++- kernel/module.c | 11 +++++++++++ 5 files changed, 33 insertions(+), 11 deletions(-) (limited to 'include/linux') diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c index 6f3f77110ead..14f12cc1ad8f 100644 --- a/fs/lockd/clntlock.c +++ b/fs/lockd/clntlock.c @@ -187,8 +187,9 @@ nlmclnt_recovery(struct nlm_host *host, u32 newstate) } else { nlmclnt_prepare_reclaim(host, newstate); nlm_get_host(host); - MOD_INC_USE_COUNT; - kernel_thread(reclaimer, host, CLONE_KERNEL); + __module_get(THIS_MODULE); + if (kernel_thread(reclaimer, host, CLONE_KERNEL)) + module_put(THIS_MODULE); } } @@ -244,7 +245,5 @@ restart: nlm_release_host(host); lockd_down(); unlock_kernel(); - MOD_DEC_USE_COUNT; - - return 0; + module_put_and_exit(0); } diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index 0bf32fd74efc..63b8f1062092 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -88,7 +88,11 @@ lockd(struct svc_rqst *rqstp) unsigned long grace_period_expire; /* Lock module and set up kernel thread */ - MOD_INC_USE_COUNT; + /* lockd_up is waiting for us to startup, so will + * be holding a reference to this module, so it + * is safe to just claim another reference + */ + __module_get(THIS_MODULE); lock_kernel(); /* @@ -183,7 +187,7 @@ lockd(struct svc_rqst *rqstp) /* Release module */ unlock_kernel(); - MOD_DEC_USE_COUNT; + module_put_and_exit(0); } /* diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1ba9f02f63e6..b783620ff9dd 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -116,9 +116,12 @@ nfsd_svc(unsigned short port, int nrservs) nrservs -= (nfsd_serv->sv_nrthreads-1); while (nrservs > 0) { nrservs--; + __module_get(THIS_MODULE); error = svc_create_thread(nfsd, nfsd_serv); - if (error < 0) + if (error < 0) { + module_put(THIS_MODULE); break; + } } victim = nfsd_list.next; while (nrservs < 0 && victim != &nfsd_list) { @@ -175,7 +178,6 @@ nfsd(struct svc_rqst *rqstp) sigset_t shutdown_mask, allowed_mask; /* Lock module and set up kernel thread */ - MOD_INC_USE_COUNT; lock_kernel(); daemonize("nfsd"); current->rlim[RLIMIT_FSIZE].rlim_cur = RLIM_INFINITY; @@ -281,7 +283,7 @@ out: svc_exit_thread(rqstp); /* Release module */ - MOD_DEC_USE_COUNT; + module_put_and_exit(0); } int diff --git a/include/linux/module.h b/include/linux/module.h index d12463033162..13ff244afdbf 100644 --- a/include/linux/module.h +++ b/include/linux/module.h @@ -277,8 +277,12 @@ struct module *module_get_kallsym(unsigned int symnum, char *type, char namebuf[128]); int is_exported(const char *name, const struct module *mod); -#ifdef CONFIG_MODULE_UNLOAD +extern void __module_put_and_exit(struct module *mod, long code) + __attribute__((noreturn)); +#define module_put_and_exit(code) __module_put_and_exit(THIS_MODULE, code); + +#ifdef CONFIG_MODULE_UNLOAD unsigned int module_refcount(struct module *mod); void __symbol_put(const char *symbol); #define symbol_put(x) __symbol_put(MODULE_SYMBOL_PREFIX #x) @@ -440,6 +444,8 @@ static inline int unregister_module_notifier(struct notifier_block * nb) return 0; } +#define module_put_and_exit(code) do_exit(code) + #endif /* CONFIG_MODULES */ #ifdef MODULE diff --git a/kernel/module.c b/kernel/module.c index 3c0117a663b0..58d73701bbde 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -98,6 +98,17 @@ int init_module(void) } 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. + */ +void __module_put_and_exit(struct module *mod, long code) +{ + module_put(mod); + do_exit(code); +} +EXPORT_SYMBOL(__module_put_and_exit); + /* Find a module section: 0 means not found. */ static unsigned int find_sec(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, -- cgit v1.2.3