public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* Re: [patch] 2.4.0, 2.2.18: A critical problem with tty_io.c
@ 2001-05-17 20:00 Al Borchers
  2001-05-17 21:23 ` Alan Cox
  0 siblings, 1 reply; 11+ messages in thread
From: Al Borchers @ 2001-05-17 20:00 UTC (permalink / raw)
  To: linux-kernel, macro, tytso; +Cc: Peter Berger, James Puzzo

Maciej, Ted --

Maciej's patch to tty_io.c from lkml 2/22/01

  http://www.uwsg.indiana.edu/hypermail/linux/kernel/0101.2/1049.html

has been incorporated in RH 7.1's kernel (for example) but not in the
main 2.4.x kernels.

This presents two different interfaces for serial drivers, and it is
awkward to detect and support both interfaces.  The change breaks some
drivers from Digi International, for example.

In Maciej's patch, if a driver open is interrupted the driver close
IS NOT called.  In the 2.4.x series the close IS called.

A serial driver needs to know whether close is going to be called or
not after an interrupted open, so it can do clean up--like DEC_MOD_USE_COUNT--
appropriately.

Suppose the driver open calls INC_MOD_USE_COUNT, sleeps for the port to get
carrier, then gets interrupted.  If the open calls DEC_MOD_USE_COUNT after
the interrupt, the use count will be right under Maciej's patch but too low on
2.4.x.  If the open does not call DEC_MOD_USE_COUNT after an interrupt, instead
deferring that for the close, then the use count will be too high under
Maciej's patch, but right under 2.4.x.  This is particularly a problem if there
is another outstanding open on the port--in that case you can end up with zero
use count (and a closed port!) while the port is open or a non-zero use count
when no one has the port open. 

Personally, I think Maciej's patch is correct and interrupted opens should
clean up after themselves--however, this is a different interface than presented
by the tty subsystem up to now, and will require changes in some serial drivers.

Ted can you get this patch in the kernel or ban it as interface breaking
heresy?  It would be much nicer for us device driver writers to have just
one interface to support.

Thanks,
-- Al Borchers, Peter Berger

PS. James Puzzo at Digi first pointed out this problem to us.

^ permalink raw reply	[flat|nested] 11+ messages in thread
* [patch] 2.4.0, 2.2.18: A critical problem with tty_io.c
@ 2001-01-22 13:55 Maciej W. Rozycki
  0 siblings, 0 replies; 11+ messages in thread
From: Maciej W. Rozycki @ 2001-01-22 13:55 UTC (permalink / raw)
  To: linux-kernel, Theodore Ts'o

Hello,

 There is a problem with handling of TTYs, which manifests itself for
modular backends.  I've been able to observe it with the serial.c backend. 
The symptoms are if open() fails for some reason (e.g. due to an inactive
DSR line), the module count for the responsible backend decrements
multiple times.  This may lead (and does for me frequently enough) to the
module being unloaded while still in use and a crash as soon as one of the
module's holders makes use of it.

 I've narrowed it down to tty_io.c calling backend's close() function
after a failed open(), which makes no sense.  Following are two patches,
for 2.4.0 and 2.2.18.  For 2.2.18 there is currently a workaround
implemented in serial.c, which was created by Ted after I reported the
very same problem in 2.1.12* or so about two years ago.  The 2.2.18 patch
reverts the workaround and provides a proper fix. 

 Both patches were proven to work as expected for the serial.c backend.  I
wasn't able to verify it against other backends, especially the zillion of
zs.c drivers.  They need to be fixed if they break after this change.

 I believe the fix should go into 2.4.1 and 2.2.19.  If anyone objects,
please speak up now.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

patch-2.4.0-tty_io-2
diff -up --recursive --new-file linux-2.4.0.macro/drivers/char/tty_io.c linux-2.4.0/drivers/char/tty_io.c
--- linux-2.4.0.macro/drivers/char/tty_io.c	Wed Jan  3 07:54:03 2001
+++ linux-2.4.0/drivers/char/tty_io.c	Sun Jan 21 20:39:32 2001
@@ -60,6 +60,9 @@
  *
  * Reduced memory usage for older ARM systems
  *      -- Russell King <rmk@arm.linux.org.uk>
+ *
+ * Don't call close after a failed open.
+ *	-- Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 21-Jan-2001
  */
 
 #include <linux/config.h>
@@ -1044,7 +1047,7 @@ static void release_mem(struct tty_struc
  * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  * lead to double frees or releasing memory still in use.
  */
-static void release_dev(struct file * filp)
+static void release_dev(struct file * filp, int do_close)
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
@@ -1122,7 +1125,7 @@ static void release_dev(struct file * fi
 	}
 #endif
 
-	if (tty->driver.close)
+	if (do_close && tty->driver.close)
 		tty->driver.close(tty, filp);
 
 	/*
@@ -1285,7 +1288,7 @@ static void release_dev(struct file * fi
 static int tty_open(struct inode * inode, struct file * filp)
 {
 	struct tty_struct *tty;
-	int noctty, retval;
+	int noctty, retval, open_ok;
 	kdev_t device;
 	unsigned short saved_flags;
 	char	buf[64];
@@ -1370,9 +1373,12 @@ init_dev_done:
 #ifdef TTY_DEBUG_HANGUP
 	printk("opening %s...", tty_name(tty, buf));
 #endif
-	if (tty->driver.open)
+	open_ok = 0;
+	if (tty->driver.open) {
 		retval = tty->driver.open(tty, filp);
-	else
+		if (!retval)
+			open_ok = 1;
+	} else
 		retval = -ENODEV;
 	filp->f_flags = saved_flags;
 
@@ -1385,7 +1391,7 @@ init_dev_done:
 		       tty_name(tty, buf));
 #endif
 
-		release_dev(filp);
+		release_dev(filp, open_ok);
 		if (retval != -ERESTARTSYS)
 			return retval;
 		if (signal_pending(current))
@@ -1427,7 +1433,7 @@ init_dev_done:
 static int tty_release(struct inode * inode, struct file * filp)
 {
 	lock_kernel();
-	release_dev(filp);
+	release_dev(filp, 1);
 	unlock_kernel();
 	return 0;
 }

patch-2.2.18-tty_io-4
diff -up --recursive --new-file linux-2.2.18.macro/drivers/char/serial.c linux-2.2.18/drivers/char/serial.c
--- linux-2.2.18.macro/drivers/char/serial.c	Thu Jun  8 19:14:48 2000
+++ linux-2.2.18/drivers/char/serial.c	Sun Jan 21 17:35:45 2001
@@ -2622,7 +2622,7 @@ static int rs_open(struct tty_struct *tt
 	tty->driver_data = info;
 	info->tty = tty;
 	if (serial_paranoia_check(info, tty->device, "rs_open")) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this */
+		MOD_DEC_USE_COUNT;
 		return -ENODEV;
 	}
 
@@ -2635,7 +2635,7 @@ static int rs_open(struct tty_struct *tt
 	if (!tmp_buf) {
 		page = get_free_page(GFP_KERNEL);
 		if (!page) {
-			/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+			MOD_DEC_USE_COUNT;
 			return -ENOMEM;
 		}
 		if (tmp_buf)
@@ -2651,7 +2651,7 @@ static int rs_open(struct tty_struct *tt
 	    (info->flags & ASYNC_CLOSING)) {
 		if (info->flags & ASYNC_CLOSING)
 			interruptible_sleep_on(&info->close_wait);
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+		MOD_DEC_USE_COUNT;
 #ifdef SERIAL_DO_RESTART
 		return ((info->flags & ASYNC_HUP_NOTIFY) ?
 			-EAGAIN : -ERESTARTSYS);
@@ -2665,13 +2665,13 @@ static int rs_open(struct tty_struct *tt
 	 */
 	retval = startup(info);
 	if (retval) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+		MOD_DEC_USE_COUNT;
 		return retval;
 	}
 
 	retval = block_til_ready(tty, filp, info);
 	if (retval) {
-		/* MOD_DEC_USE_COUNT; "info->tty" will cause this? */
+		MOD_DEC_USE_COUNT;
 #ifdef SERIAL_DEBUG_OPEN
 		printk("rs_open returning after block_til_ready with %d\n",
 		       retval);
diff -up --recursive --new-file linux-2.2.18.macro/drivers/char/tty_io.c linux-2.2.18/drivers/char/tty_io.c
--- linux-2.2.18.macro/drivers/char/tty_io.c	Mon Dec 11 22:50:34 2000
+++ linux-2.2.18/drivers/char/tty_io.c	Sun Jan 21 20:48:08 2001
@@ -54,6 +54,9 @@
  *
  * Added support for a Unix98-style ptmx device.
  *      -- C. Scott Ananian <cananian@alumni.princeton.edu>, 14-Jan-1998
+ *
+ * Don't call close after a failed open.
+ *	-- Maciej W. Rozycki <macro@ds2.pg.gda.pl>, 21-Jan-2001
  */
 
 #include <linux/config.h>
@@ -1009,7 +1012,7 @@ static void release_mem(struct tty_struc
  * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
  * lead to double frees or releasing memory still in use.
  */
-static void release_dev(struct file * filp)
+static void release_dev(struct file * filp, int do_close)
 {
 	struct tty_struct *tty, *o_tty;
 	int	pty_master, tty_closing, o_tty_closing, do_sleep;
@@ -1087,7 +1090,7 @@ static void release_dev(struct file * fi
 	}
 #endif
 
-	if (tty->driver.close)
+	if (do_close && tty->driver.close)
 		tty->driver.close(tty, filp);
 
 	/*
@@ -1258,7 +1261,7 @@ static void release_dev(struct file * fi
 static int tty_open(struct inode * inode, struct file * filp)
 {
 	struct tty_struct *tty;
-	int noctty, retval;
+	int noctty, retval, open_ok;
 	kdev_t device;
 	unsigned short saved_flags;
 	char	buf[64];
@@ -1340,9 +1343,12 @@ init_dev_done:
 #ifdef TTY_DEBUG_HANGUP
 	printk("opening %s...", tty_name(tty, buf));
 #endif
-	if (tty->driver.open)
+	open_ok = 0;
+	if (tty->driver.open) {
 		retval = tty->driver.open(tty, filp);
-	else
+		if (!retval)
+			open_ok = 1;
+	} else
 		retval = -ENODEV;
 	filp->f_flags = saved_flags;
 
@@ -1355,7 +1361,7 @@ init_dev_done:
 		       tty_name(tty, buf));
 #endif
 
-		release_dev(filp);
+		release_dev(filp, open_ok);
 		if (retval != -ERESTARTSYS)
 			return retval;
 		if (signal_pending(current))
@@ -1394,7 +1400,7 @@ init_dev_done:
 
 static int tty_release(struct inode * inode, struct file * filp)
 {
-	release_dev(filp);
+	release_dev(filp, 1);
 	return 0;
 }
 

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
Please read the FAQ at http://www.tux.org/lkml/

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

end of thread, other threads:[~2001-05-18 15:47 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-05-17 20:00 [patch] 2.4.0, 2.2.18: A critical problem with tty_io.c Al Borchers
2001-05-17 21:23 ` Alan Cox
2001-05-18  2:12   ` Al Borchers
2001-05-18  7:50     ` Alan Cox
2001-05-18  8:24       ` Alan Cox
2001-05-18  9:08         ` Al Borchers
2001-05-18 11:25           ` Alan Cox
2001-05-18 15:22             ` Al Borchers
2001-05-18 10:09         ` Andrew Morton
2001-05-18 11:29           ` Alan Cox
  -- strict thread matches above, loose matches on Subject: below --
2001-01-22 13:55 Maciej W. Rozycki

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