[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[dm-devel] [PATCH] fix rmmod oops



I am running 2.6.0-test9-udm5. When I do a rmmod of dm-mirror and dm-mod
I get the following oops:

Nov 24 02:35:14 minna kernel: device-mapper: 4.0.0-ioctl (2003-06-04)
initialised: dm uk sistina com
Nov 24 02:35:59 minna kernel: device-mapper: cleaned up
Nov 24 02:35:59 minna kernel: Unable to handle kernel paging request at
virtual address d09bdca6
Nov 24 02:35:59 minna kernel:  printing eip:
Nov 24 02:35:59 minna kernel: d09bdca6
Nov 24 02:35:59 minna kernel: *pde = 013e0067
Nov 24 02:35:59 minna kernel: *pte = 00000000
Nov 24 02:35:59 minna kernel: Oops: 0000 [#1]
Nov 24 02:35:59 minna kernel: CPU:    0
Nov 24 02:35:59 minna kernel: EIP:    0060:[<d09bdca6>]    Not tainted
Nov 24 02:35:59 minna kernel: EFLAGS: 00010246
Nov 24 02:35:59 minna kernel: EIP is at 0xd09bdca6
Nov 24 02:35:59 minna kernel: eax: 00000000   ebx: c72fa000   ecx:
d09c2810   edx: d09c2834
Nov 24 02:35:59 minna kernel: esi: d09c27e0   edi: ffffe000   ebp:
c72fbfc0   esp: c72fbf98
Nov 24 02:35:59 minna kernel: ds: 007b   es: 007b   ss: 0068
Nov 24 02:35:59 minna kernel: Process kcopyd (pid: 1675,
threadinfo=c72fa000 task=c80e3330)
Nov 24 02:35:59 minna kernel: Stack: d09be011 00000077 00000000 c80e3330
c0121070 00000000 00000000 00000001
Nov 24 02:35:59 minna kernel:        c7bcfeec c0109a42 00000000 c80e3330
c0121070 00100100 00200200 00000000
Nov 24 02:35:59 minna kernel:        00000000 00000000 d09bd9d0 00000000
00000000 00000000 c0107349 d09c27e0
Nov 24 02:35:59 minna kernel: Call Trace:
Nov 24 02:35:59 minna kernel:  [<c0121070>] default_wake_function+0x0/0x30
Nov 24 02:35:59 minna kernel:  [<c0109a42>] ret_from_fork+0x6/0x14
Nov 24 02:35:59 minna kernel:  [<c0121070>] default_wake_function+0x0/0x30
Nov 24 02:35:59 minna kernel:  [<c0107349>] kernel_thread_helper+0x5/0xc
Nov 24 02:35:59 minna kernel:
Nov 24 02:35:59 minna kernel: Code:  Bad EIP value.


The attached patch (rmmod_daemon.patch) fixes this by replacing the
semaphores with completions, and uses complete_and_exit() to make
sure the daemon thread is completely broken down before exiting the module (complete() passes 1 for the sync variable to __wake_up_common() where up() passes zero).


The patch was built and tested against 2.6.0-test9-udm5.


Mike Christie mikenc us ibm com

diff -aup linux-2.6.0-test9/drivers/md/dm-daemon.c linux-2.6.0-test9-dm/drivers/md/dm-daemon.c
--- linux-2.6.0-test9/drivers/md/dm-daemon.c	2003-11-24 03:23:32.367176348 -0800
+++ linux-2.6.0-test9-dm/drivers/md/dm-daemon.c	2003-11-24 03:25:12.573082455 -0800
@@ -10,6 +10,7 @@
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/suspend.h>
+#include <linux/completion.h>
 
 static int daemon(void *arg)
 {
@@ -22,8 +23,7 @@ static int daemon(void *arg)
 
 	add_wait_queue(&dd->job_queue, &wq);
 
-	down(&dd->run_lock);
-	up(&dd->start_lock);
+	complete(&dd->start);
 
 	/*
 	 * dd->fn() could do anything, very likely it will
@@ -55,8 +55,7 @@ static int daemon(void *arg)
 
  out:
 	remove_wait_queue(&dd->job_queue, &wq);
-	up(&dd->run_lock);
-	return 0;
+	complete_and_exit(&dd->run, 0);
 }
 
 int dm_daemon_start(struct dm_daemon *dd, const char *name, void (*fn)(void))
@@ -68,14 +67,13 @@ int dm_daemon_start(struct dm_daemon *dd
 	 */
 	dd->fn = fn;
 	strncpy(dd->name, name, sizeof(dd->name) - 1);
-	sema_init(&dd->start_lock, 1);
-	sema_init(&dd->run_lock, 1);
+	init_completion(&dd->start);
+	init_completion(&dd->run);
 	init_waitqueue_head(&dd->job_queue);
 
 	/*
 	 * Start the new thread.
 	 */
-	down(&dd->start_lock);
 	pid = kernel_thread(daemon, dd, CLONE_KERNEL);
 	if (pid <= 0) {
 		DMERR("Failed to start %s thread", name);
@@ -85,8 +83,7 @@ int dm_daemon_start(struct dm_daemon *dd
 	/*
 	 * wait for the daemon to up this mutex.
 	 */
-	down(&dd->start_lock);
-	up(&dd->start_lock);
+	wait_for_completion(&dd->start);
 
 	return 0;
 }
@@ -95,8 +92,7 @@ void dm_daemon_stop(struct dm_daemon *dd
 {
 	atomic_set(&dd->please_die, 1);
 	dm_daemon_wake(dd);
-	down(&dd->run_lock);
-	up(&dd->run_lock);
+	wait_for_completion(&dd->run);
 }
 
 void dm_daemon_wake(struct dm_daemon *dd)
diff -aup linux-2.6.0-test9/drivers/md/dm-daemon.h linux-2.6.0-test9-dm/drivers/md/dm-daemon.h
--- linux-2.6.0-test9/drivers/md/dm-daemon.h	2003-11-24 03:23:32.367176348 -0800
+++ linux-2.6.0-test9-dm/drivers/md/dm-daemon.h	2003-11-24 03:20:10.641776035 -0800
@@ -8,14 +8,14 @@
 #define DM_DAEMON_H
 
 #include <asm/atomic.h>
-#include <asm/semaphore.h>
+#include <linux/completion.h>
 
 struct dm_daemon {
 	void (*fn)(void);
 	char name[16];
 	atomic_t please_die;
-	struct semaphore start_lock;
-	struct semaphore run_lock;
+	struct completion start;
+	struct completion run;
 
 	atomic_t woken;
 	wait_queue_head_t job_queue;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]