mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* Re: [PATCH] Add module_kernel_thread for threads that live in modules.
@ 2003-06-16  6:50 Rusty Russell
  2003-06-16  7:58 ` Martin Diehl
  2003-06-16 23:10 ` Neil Brown
  0 siblings, 2 replies; 14+ messages in thread
From: Rusty Russell @ 2003-06-16  6:50 UTC (permalink / raw)
  To: NeilBrown; +Cc: torvalds, linux-kernel

Hi Neil,

	There are several problems with this patch.  Ignoring the fact
that you use __module_get.  Firstly, you bump the module count
permentantly while the thread is running: how does it ever get
unloaded?  Secondly, modprobe becomes your parent.

	There have been ambitious attempts to do a nice "thread
creation and stopping" interface before.  Given the delicate logic
involved in shutting threads down, I think this makes sense.  Maybe
something like: 

/* Struct which identifies a kernel thread, handed to creator and
   thread. */
struct kthread
{
	int pid;
	int should_die; /* Thread should exit when this is set. */

	/* User supplied arg... */
	void *arg;
};

struct kthread *create_thread(int (*fn)(struct kthread*), void *arg, 
			      unsigned long flags,
			      const char *namefmt, ...);
void cleanup_thread(struct kthread *);

create_thread would use keventd to start the thread, and stop_thread
would tell keventd to set should_die, wmb(), wake it up, and
sys_wait() for it.

Thoughts?
Rusty.
--
  Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

^ permalink raw reply	[flat|nested] 14+ messages in thread
* [PATCH]  Add module_kernel_thread for threads that live in modules.
@ 2003-06-05  2:30 NeilBrown
  2003-06-05 14:50 ` Andrey Klochko
  0 siblings, 1 reply; 14+ messages in thread
From: NeilBrown @ 2003-06-05  2:30 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linux-kernel

Nfsd (and lockd) run kernel threads that currently use
MOD_{INC,DEC}_USE_COUNT to manage references to the module on
behalf of those threads.  This is deprecated and unsafe.

This patch introduces module_kernel_thread which ensures that
references counts are taken and dropped as appropriate for kernel
threads, and uses it for nfsd and lockd.

NeilBrown

### Comments for ChangeSet

If a kernel thread runs code that is in a module, it can be started
with module_kernel_thread, and this will safely managed the reference
counts on the module implied by the existance of the thread.

This is then used for nfsd and lockd.

 ----------- Diffstat output ------------
 ./fs/lockd/svc.c             |    9 ++------
 ./fs/nfsd/nfssvc.c           |   11 +++-------
 ./include/linux/module.h     |   15 +++++++++++++
 ./include/linux/sunrpc/svc.h |    4 +--
 ./kernel/module.c            |   47 +++++++++++++++++++++++++++++++++++++++++++
 ./net/sunrpc/svc.c           |    7 ++++--
 6 files changed, 76 insertions(+), 17 deletions(-)

diff ./fs/lockd/svc.c~current~ ./fs/lockd/svc.c
--- ./fs/lockd/svc.c~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./fs/lockd/svc.c	2003-06-05 12:04:51.000000000 +1000
@@ -80,7 +80,7 @@ static inline void clear_grace_period(vo
 /*
  * This is the lockd kernel thread
  */
-static void
+static int
 lockd(struct svc_rqst *rqstp)
 {
 	struct svc_serv	*serv = rqstp->rq_server;
@@ -88,7 +88,6 @@ lockd(struct svc_rqst *rqstp)
 	unsigned long grace_period_expire;
 
 	/* Lock module and set up kernel thread */
-	MOD_INC_USE_COUNT;
 	lock_kernel();
 
 	/*
@@ -181,9 +180,7 @@ lockd(struct svc_rqst *rqstp)
 	/* release rpciod */
 	rpciod_down();
 
-	/* Release module */
-	unlock_kernel();
-	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 /*
@@ -238,7 +235,7 @@ lockd_up(void)
 	/*
 	 * Create the kernel thread and wait for it to start.
 	 */
-	error = svc_create_thread(lockd, serv);
+	error = svc_create_thread(lockd, serv, THIS_MODULE);
 	if (error) {
 		printk(KERN_WARNING
 			"lockd_up: create thread failed, error=%d\n", error);

diff ./fs/nfsd/nfssvc.c~current~ ./fs/nfsd/nfssvc.c
--- ./fs/nfsd/nfssvc.c~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./fs/nfsd/nfssvc.c	2003-06-05 12:04:51.000000000 +1000
@@ -48,7 +48,7 @@
 #define	SIG_NOCLEAN	SIGHUP
 
 extern struct svc_program	nfsd_program;
-static void			nfsd(struct svc_rqst *rqstp);
+static int			nfsd(struct svc_rqst *rqstp);
 struct timeval			nfssvc_boot;
 static struct svc_serv 		*nfsd_serv;
 static atomic_t			nfsd_busy;
@@ -114,7 +114,7 @@ nfsd_svc(unsigned short port, int nrserv
 	nrservs -= (nfsd_serv->sv_nrthreads-1);
 	while (nrservs > 0) {
 		nrservs--;
-		error = svc_create_thread(nfsd, nfsd_serv);
+		error = svc_create_thread(nfsd, nfsd_serv, THIS_MODULE);
 		if (error < 0)
 			break;
 	}
@@ -163,7 +163,7 @@ update_thread_usage(int busy_threads)
 /*
  * This is the NFS server kernel thread
  */
-static void
+static int
 nfsd(struct svc_rqst *rqstp)
 {
 	struct svc_serv	*serv = rqstp->rq_server;
@@ -172,7 +172,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;
@@ -255,9 +254,7 @@ nfsd(struct svc_rqst *rqstp)
 
 	/* Release the thread */
 	svc_exit_thread(rqstp);
-
-	/* Release module */
-	MOD_DEC_USE_COUNT;
+	return 0;
 }
 
 int

diff ./include/linux/module.h~current~ ./include/linux/module.h
--- ./include/linux/module.h~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./include/linux/module.h	2003-06-05 11:34:24.000000000 +1000
@@ -314,6 +314,9 @@ static inline void module_put(struct mod
 	}
 }
 
+extern int module_kernel_thread(int (*fn)(void*), void *arg, 
+				unsigned long flags, struct module *owner);
+
 #else /*!CONFIG_MODULE_UNLOAD*/
 static inline int try_module_get(struct module *module)
 {
@@ -328,6 +331,12 @@ static inline void __module_get(struct m
 #define symbol_put(x) do { } while(0)
 #define symbol_put_addr(p) do { } while(0)
 
+static inline int module_kernel_thread(int (*fn)(void*), void *arg, 
+				       unsigned long flags, struct module *owner)
+{
+	return kernel_thread(fn, arg, flags);
+}
+	       
 #endif /* CONFIG_MODULE_UNLOAD */
 
 /* This is a #define so the string doesn't get put in every .o file */
@@ -419,6 +428,12 @@ static inline int unregister_module_noti
 	return 0;
 }
 
+static inline int module_kernel_thread(int (*fn)(void*), void *arg,
+				       unsigned long flags, struct module *owner)
+{
+	return kernel_thread(fn, arg, flags);
+}
+
 #endif /* CONFIG_MODULES */
 
 #ifdef MODULE

diff ./include/linux/sunrpc/svc.h~current~ ./include/linux/sunrpc/svc.h
--- ./include/linux/sunrpc/svc.h~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./include/linux/sunrpc/svc.h	2003-06-05 12:04:51.000000000 +1000
@@ -276,13 +276,13 @@ struct svc_procedure {
 /*
  * This is the RPC server thread function prototype
  */
-typedef void		(*svc_thread_fn)(struct svc_rqst *);
+typedef int		(*svc_thread_fn)(struct svc_rqst *);
 
 /*
  * Function prototypes.
  */
 struct svc_serv *  svc_create(struct svc_program *, unsigned int);
-int		   svc_create_thread(svc_thread_fn, struct svc_serv *);
+int		   svc_create_thread(svc_thread_fn, struct svc_serv *, struct module *);
 void		   svc_exit_thread(struct svc_rqst *);
 void		   svc_destroy(struct svc_serv *);
 int		   svc_process(struct svc_serv *, struct svc_rqst *);

diff ./kernel/module.c~current~ ./kernel/module.c
--- ./kernel/module.c~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./kernel/module.c	2003-06-05 11:34:24.000000000 +1000
@@ -616,6 +616,53 @@ void symbol_put_addr(void *addr)
 }
 EXPORT_SYMBOL_GPL(symbol_put_addr);
 
+
+/*
+ * If a kernel_thread runs in a module, we might want to
+ * module to be refcounted by the threads.  This code
+ * allows that to happen.
+ * When module_kernel_thread completes, the module will
+ * have been ref-counted iif the thread started.
+ */
+struct kern_thread_info {
+	int (*fn)(void*);
+	void *arg;
+	struct module *owner;
+};
+static int module_kernel_thread_helper(void *arg)
+{
+	struct kern_thread_info *kti = arg;
+	int rv;
+
+	rv = kti->fn(kti->arg);
+	module_put(kti->owner);
+	kfree(kti);
+	return rv;
+}
+int module_kernel_thread(int (*fn)(void*), void *arg, 
+			 unsigned long flags, struct module *owner)
+{
+	struct kern_thread_info *kti;
+	int err;
+
+	if (!owner)
+		return kernel_thread(fn, arg, flags);
+	kti = kmalloc(sizeof(*kti), GFP_KERNEL);
+	if (!kti)
+		return -ENOMEM;
+	kti->fn = fn;
+	kti->arg = arg;
+	kti->owner = owner;
+	__module_get(owner);
+	err = kernel_thread(module_kernel_thread_helper, kti, flags);
+	if (err < 0) {
+		module_put(owner);
+		kfree(kti);
+	}
+	return err;
+}
+EXPORT_SYMBOL(module_kernel_thread);
+
 #else /* !CONFIG_MODULE_UNLOAD */
 static void print_unload_info(struct seq_file *m, struct module *mod)
 {

diff ./net/sunrpc/svc.c~current~ ./net/sunrpc/svc.c
--- ./net/sunrpc/svc.c~current~	2003-06-05 12:04:57.000000000 +1000
+++ ./net/sunrpc/svc.c	2003-06-05 12:06:13.000000000 +1000
@@ -14,6 +14,7 @@
 #include <linux/in.h>
 #include <linux/unistd.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 
 #include <linux/sunrpc/types.h>
 #include <linux/sunrpc/xdr.h>
@@ -150,7 +151,8 @@ svc_release_buffer(struct svc_rqst *rqst
  * Create a server thread
  */
 int
-svc_create_thread(svc_thread_fn func, struct svc_serv *serv)
+svc_create_thread(svc_thread_fn func, struct svc_serv *serv,
+		  struct module *owner)
 {
 	struct svc_rqst	*rqstp;
 	int		error = -ENOMEM;
@@ -169,7 +171,8 @@ svc_create_thread(svc_thread_fn func, st
 
 	serv->sv_nrthreads++;
 	rqstp->rq_server = serv;
-	error = kernel_thread((int (*)(void *)) func, rqstp, 0);
+	error = module_kernel_thread((int(*)(void*))func, rqstp,
+				     0, owner);
 	if (error < 0)
 		goto out_thread;
 	svc_sock_update_bufs(serv);

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2003-06-17  4:22 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-16  6:50 [PATCH] Add module_kernel_thread for threads that live in modules Rusty Russell
2003-06-16  7:58 ` Martin Diehl
2003-06-16  8:09   ` Rusty Russell
2003-06-16  8:57     ` Martin Diehl
2003-06-16  9:22       ` Rusty Russell
2003-06-16 10:27         ` Martin Diehl
2003-06-17  1:11           ` Rusty Russell
2003-06-16  8:19   ` Andrew Morton
2003-06-16 23:10 ` Neil Brown
2003-06-17  4:25   ` Rusty Russell
  -- strict thread matches above, loose matches on Subject: below --
2003-06-05  2:30 NeilBrown
2003-06-05 14:50 ` Andrey Klochko
2003-06-07  5:33   ` Neil Brown
2003-06-09 16:20     ` Andrey Klochko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®