[PATCH]omninet write vs. close race

Oliver Neukum <[email protected]>
Newsgroups gmane.linux.usb.devel
Organization Novell
Message-ID <[email protected]>
Hi,

omninet kills all URBs in close. However write() returns as soon as
the URB has been submitted. Killing the last URB means a race that
can lose that date written in the last call to write().
As a fix this is moved to shutdown().

	Regards
		Oliver

Signed-off-by: Oliver Neukum <[email protected]>
------

--- a/drivers/usb/serial/omninet.c	2007-03-27 14:56:45.000000000 +0200
+++ b/drivers/usb/serial/omninet.c	2007-03-27 15:53:26.000000000 +0200
@@ -69,6 +69,7 @@
 static int  omninet_write		(struct usb_serial_port *port, const unsigned char *buf, int count);
 static int  omninet_write_room		(struct usb_serial_port *port);
 static void omninet_shutdown		(struct usb_serial *serial);
+static int omninet_attach		(struct usb_serial *serial);
 
 static struct usb_device_id id_table [] = {
 	{ USB_DEVICE(ZYXEL_VENDOR_ID, ZYXEL_OMNINET_ID) },
@@ -99,6 +100,7 @@
 	.num_bulk_in =		1,
 	.num_bulk_out =		2,
 	.num_ports =		1,
+	.attach =		omninet_attach,
 	.open =			omninet_open,
 	.close =		omninet_close,
 	.write =		omninet_write,
@@ -145,22 +147,30 @@
 	__u8	od_outseq;	// Sequence number for bulk_out URBs
 };
 
+static int omninet_attach (struct usb_serial *serial)
+{
+	struct omninet_data *od;
+	struct usb_serial_port *port = serial->port[0];
+
+	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
+	if( !od ) {
+		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
+		return -ENOMEM;
+	}
+	usb_set_serial_port_data(port, od);
+	return 0;
+}
+
 static int omninet_open (struct usb_serial_port *port, struct file *filp)
 {
 	struct usb_serial	*serial = port->serial;
 	struct usb_serial_port	*wport;
-	struct omninet_data	*od;
+	struct omninet_data	*od = usb_get_serial_port_data(port);
 	int			result = 0;
 
 	dbg("%s - port %d", __FUNCTION__, port->number);
 
 	od = kmalloc( sizeof(struct omninet_data), GFP_KERNEL );
-	if( !od ) {
-		err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct omninet_data));
-		return -ENOMEM;
-	}
-
-	usb_set_serial_port_data(port, od);
 	wport = serial->port[1];
 	wport->tty = port->tty;
 
@@ -172,9 +182,6 @@
 	result = usb_submit_urb(port->read_urb, GFP_KERNEL);
 	if (result) {
 		err("%s - failed submitting read urb, error %d", __FUNCTION__, result);
-		/* open failed - all allocations must be freed */
-		kfree(od);
-		usb_set_serial_port_data(port, NULL);
 	}
 
 	return result;
@@ -182,16 +189,8 @@
 
 static void omninet_close (struct usb_serial_port *port, struct file * filp)
 {
-	struct usb_serial 	*serial = port->serial;
-	struct usb_serial_port 	*wport;
-
 	dbg("%s - port %d", __FUNCTION__, port->number);
-
-	wport = serial->port[1];
-	usb_kill_urb(wport->write_urb);
 	usb_kill_urb(port->read_urb);
-
-	kfree(usb_get_serial_port_data(port));
 }
 
 
@@ -330,7 +329,12 @@
 
 static void omninet_shutdown (struct usb_serial *serial)
 {
+	struct usb_serial_port *wport = serial->port[1];
+	struct usb_serial_port *port = serial->port[0];
 	dbg ("%s", __FUNCTION__);
+
+	usb_kill_urb(wport->write_urb);
+	kfree(usb_get_serial_port_data(port));
 }
 
 

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.