diff options
author | Robert Olsson <data.slu.se> | 2007-01-04 00:57:17 +0100 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2007-01-04 01:02:58 +0100 |
commit | e79366b5564af42aa2449042c75630c16edbdb4d (patch) | |
tree | 0d37b5395317e37e7d3d6e5efb140fdbdac3a4e2 | |
parent | 51b73a030955179f236959eaedaf03f405b878a6 (diff) | |
download | lwn-e79366b5564af42aa2449042c75630c16edbdb4d.tar.gz lwn-e79366b5564af42aa2449042c75630c16edbdb4d.zip |
[PKTGEN]: Fix module load/unload races.
Adrian Bunk:
Backported to 2.6.16.
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
-rw-r--r-- | net/core/pktgen.c | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 47d0c28ae390..6e972e489b6d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c @@ -139,6 +139,7 @@ #include <linux/proc_fs.h> #include <linux/seq_file.h> #include <linux/wait.h> +#include <linux/completion.h> #include <linux/etherdevice.h> #include <net/checksum.h> #include <net/ipv6.h> @@ -194,6 +195,11 @@ static struct proc_dir_entry *pg_proc_dir = NULL; #define MAX_CFLOWS 65536 +struct pktgen_thread_info { + struct pktgen_thread *t; + struct completion *c; +}; + struct flow_state { __u32 cur_daddr; @@ -2656,10 +2662,11 @@ retry_now: * Main loop of the thread goes here */ -static void pktgen_thread_worker(struct pktgen_thread *t) +static void pktgen_thread_worker(struct pktgen_thread_info *info) { DEFINE_WAIT(wait); struct pktgen_dev *pkt_dev = NULL; + struct pktgen_thread *t = info->t; int cpu = t->cpu; sigset_t tmpsig; u32 max_before_softirq; @@ -2700,6 +2707,8 @@ static void pktgen_thread_worker(struct pktgen_thread *t) __set_current_state(TASK_INTERRUPTIBLE); mb(); + complete(info->c); + while (1) { __set_current_state(TASK_RUNNING); @@ -2894,6 +2903,8 @@ static struct pktgen_thread * __init pktgen_find_thread(const char* name) static int __init pktgen_create_thread(const char* name, int cpu) { + struct pktgen_thread_info info; + struct completion started; struct pktgen_thread *t = NULL; struct proc_dir_entry *pe; @@ -2931,10 +2942,15 @@ static int __init pktgen_create_thread(const char* name, int cpu) t->next = pktgen_threads; pktgen_threads = t; - if (kernel_thread((void *) pktgen_thread_worker, (void *) t, + init_completion(&started); + info.t = t; + info.c = &started; + + if (kernel_thread((void *) pktgen_thread_worker, (void *)&info, CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) printk("pktgen: kernel_thread() failed for cpu %d\n", t->cpu); + wait_for_completion(&started); return 0; } |