Re-xmit: module_put_and_exit
Subsystems (3)
PATCH 1/1 Re-xmit: module_put_and_exit
Please apply. Neil wants this for safety of his kernel threads in modules (which hold a reference count).
Name: module_put_and_exit
Author: Neil Brown
Status: Booted on 2.5.74-bk1
D: Define module_put_and_exit() and use it for nfsd/lockd D:
D: Both nfsd and lockd have threads which expect to hold a reference
D: to the module while the thread is running. In order for the thread
D: to be able to put_module() the module before exiting, the
D: put_module code must be call from outside the module.
D:
D: This patch provides module_put_and_exit in non-modular code which a
D: thread-in-a-module can call. It also gets nfsd and lockd to use it
D: as appropriate.
D:
D: Note that in lockd, we can __get_module in the thread itself as the
D: creator of the thread is waiting for the thread to startup. D:
D: In nfsd and for the 'reclaimer' threaded started by locked, we
D: __get_module first and put_module if the thread failed to start. D:
D: ----------- Diffstat output ------------ D: ./fs/lockd/clntlock.c | 9 ++++----- D: ./fs/lockd/svc.c | 8 ++++++-- D: ./fs/nfsd/nfssvc.c | 8 +++++--- D: ./include/linux/module.h | 8 ++++++++ D: ./kernel/exit.c | 1 + D: ./kernel/module.c | 12 ++++++++++++ D: 6 files changed, 36 insertions(+), 10 deletions(-)
fs/lockd/clntlock.c +4 -5
@@ -187,8 +187,9 @@ nlmclnt_recovery(struct nlm_host *host, }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 ); }
fs/lockd/svc.c +6 -2
@@ -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 ); }/*
fs/nfsd/nfssvc.c +5 -3
@@ -115,9 +115,12 @@ nfsd_svc(unsigned short port, int nrserv 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) {
@@ -173,7 +176,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 ;
@@ -266,7 +268,7 @@ nfsd(struct svc_rqst *rqstp)svc_exit_thread (rqstp);/* Release module */ -MOD_DEC_USE_COUNT ; +module_put_and_exit (0 ); }int
include/linux/module.h +7 -1
@@ -276,8 +276,12 @@ struct module *module_get_kallsym(unsignchar *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)
@@ -445,6 +449,8 @@ static inline int unregister_module_noti return 0; } +#define module_put_and_exit (code) do_exit(code) +#endif /* CONFIG_MODULES */ #ifdef MODULE
kernel/module.c +11 -0
@@ -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,
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.