speedtch usbatm.h,1.4,1.5 usbatm2.c,1.13,1.14

Duncan Sands duncan at infradead.org
Fri Jan 28 07:11:08 EST 2005


Update of /home/cvs/speedtch
In directory phoenix.infradead.org:/tmp/cvs-serv16893

Modified Files:
	usbatm.h usbatm2.c 
Log Message:
(1) Fix the race in which we might send a signal to the kernel thread before it
called allow_signal by waiting for it to start (struct completion thread_started).
(2) Fix the problem with maybe sending a signal after the kernel thread has exited
and shooting down the wrong process by having the kernel thread clear thread_pid
just before it exits.
(3) Shoot down the kernel thread before trying to shut down the ATM device.  That
way we can get rid of instance->bound.

There is maybe a module unloading race: between the kernel thread dropping the semaphore
and actually exiting the module could be unloaded, causing the code the kernel thread is
executing (i.e. the return instruction) to be freed.  I don't think this can happen because
the thread won't sleep before returning, and the module unloader waits for all threads
to schedule before unloading.  To be confirmed.


Index: usbatm.h
===================================================================
RCS file: /home/cvs/speedtch/usbatm.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -r1.4 -r1.5
--- usbatm.h	28 Jan 2005 11:03:43 -0000	1.4
+++ usbatm.h	28 Jan 2005 12:11:04 -0000	1.5
@@ -158,13 +158,13 @@
 
 	/* heavy init part */
 	int thread_pid;
+	struct completion thread_started;
 	struct completion thread_exited;
 
 	/* USB device part */
 	struct usb_device *usb_dev;
 	struct usb_interface *usb_intf;
 	char description[64];
-	int bound;
 	int tx_endpoint;
 	int rx_endpoint;
 	int tx_padding;

Index: usbatm2.c
===================================================================
RCS file: /home/cvs/speedtch/usbatm2.c,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -r1.13 -r1.14
--- usbatm2.c	28 Jan 2005 11:03:43 -0000	1.13
+++ usbatm2.c	28 Jan 2005 12:11:04 -0000	1.14
@@ -825,11 +825,6 @@
 			break;
 		}
 
-		if (instance->bound)
-			strcat(page, ", ready\n");
-		else
-			strcat(page, ", disconnected\n");
-
 		return strlen(page);
 	}
 
@@ -961,20 +956,11 @@
 	struct atm_dev *atm_dev;
 	int ret;
 
-	down(&instance->serialize);
-
-	if (!instance->bound) {
-		dbg("usbatm_atm_init: device disconnected!");
-		ret = -ENODEV;
-		goto fail;
-	}
-
 	/* ATM init */
 	atm_dev = atm_dev_register(instance->driver->driver_name, &udsl_atm_devops, -1, NULL);
 	if (!atm_dev) {
 		dbg("usbatm_atm_init: failed to register ATM device!");
-		ret = -1;
-		goto fail;
+		return -1;
 	}
 
 	instance->atm_dev = atm_dev;
@@ -987,24 +973,18 @@
 	atm_dev->link_rate = 128 * 1000 / 424;
 
 	if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0))
-		goto fail_close;
+		goto fail;
 
 	/* ready for ATM callbacks */
 	udsl_get_instance(instance);	/* dropped in udsl_atm_dev_close */
 	mb();
 	atm_dev->dev_data = instance;
 
-	up(&instance->serialize);
-
 	return 0;
 
- fail_close:
+ fail:
 	instance->atm_dev = NULL;
 	shutdown_atm_dev(atm_dev); /* udsl_atm_dev_close will eventually be called */
-
- fail:
-	up(&instance->serialize);
-
 	return ret;
 }
 
@@ -1021,24 +1001,35 @@
 	daemonize("%s/%s", usbatm_driver_name, instance->driver->driver_name);
 	allow_signal(SIGTERM);
 
+	complete(&instance->thread_started);
+
 	ret = instance->driver->heavy_init(instance, instance->usb_intf);
 
 	if (!ret)
 		ret = usbatm_atm_init(instance);
 
-	complete_and_exit(&instance->thread_exited, ret);
+	down(&instance->serialize);
+	instance->thread_pid = -1;
+	complete(&instance->thread_exited);
+	up(&instance->serialize);
+
+	return ret;
 }
 
 static int usbatm_heavy_init(struct usbatm_data *instance)
 {
-	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_FS | CLONE_FILES);
+	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);
 
 	if (ret < 0) {
 		dbg("usbatm_heavy_init: failed to create kernel_thread (%d)!", ret);
 		return ret;
 	}
 
+	down(&instance->serialize);
 	instance->thread_pid = ret;
+	up(&instance->serialize);
+
+	wait_for_completion(&instance->thread_started);
 
 	return 0;
 }
@@ -1076,6 +1067,7 @@
 	instance->driver = driver;
 
 	instance->thread_pid = -1;
+	init_completion(&instance->thread_started);
 	init_completion(&instance->thread_exited);
 
 	instance->usb_dev = dev;
@@ -1186,12 +1178,12 @@
 	if (driver->bind && (error = driver->bind(instance, intf, &need_heavy)) < 0)
 			goto fail;
 
-	instance->bound = 1;
-
 	if (need_heavy && driver->heavy_init)
 		error = usbatm_heavy_init(instance);
-	else
+	else {
+		complete(&instance->thread_exited);	/* pretend that heavy_init was run */
 		error = usbatm_atm_init(instance);
+	}
 
 	if (error)
 		goto fail;
@@ -1235,17 +1227,15 @@
 	usb_set_intfdata(intf, NULL);
 
 	down(&instance->serialize);
-	instance->bound = 0;
+	if (instance->thread_pid >= 0)
+		kill_proc(instance->thread_pid, SIGTERM, 1);
 	up(&instance->serialize);
 
+	wait_for_completion(&instance->thread_exited);
+
 	if (instance->atm_dev && instance->driver->atm_stop)
 		instance->driver->atm_stop(instance, instance->atm_dev);
 
-	if (instance->thread_pid >= 0) {
-		kill_proc(instance->thread_pid, SIGTERM, 1);
-		wait_for_completion(&instance->thread_exited);
-	}
-
 	if (instance->driver->unbind)
 		instance->driver->unbind(instance, intf);
 




More information about the Usbatm-commits mailing list