linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] tty_ldisc: Fix BUG() on hangup
@ 2010-10-26 15:49 Philippe Rétornaz
  2010-10-26 16:13 ` Alan Cox
  0 siblings, 1 reply; 3+ messages in thread
From: Philippe Rétornaz @ 2010-10-26 15:49 UTC (permalink / raw)
  To: Alan Cox; +Cc: Greg Kroah-Hartman, linux-kernel

Hello

A kernel BUG when bluetooth rfcomm connection drop while 
the associated serial port is open is sometime triggered.

It seems that the line discipline can disappear between the tty_ldisc_put  and 
tty_ldisc_get. This patch fall back to the N_TTY line discipline if the 
previous discipline is not available anymore.

This seem to fix the BUG(), but I don't know if it's correct.

Regards,

Philippe

---

--- linux-2.6.34.x86_64/drivers/char/tty_ldisc.c.orig	2010-05-16 
23:17:36.000000000 +0200
+++ linux-2.6.34.x86_64/drivers/char/tty_ldisc.c	2010-10-15 10:48:01.871721197 
+0200
@@ -712,9 +712,12 @@ static void tty_reset_termios(struct tty
  *	state closed
  */
 
-static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
+static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 {
-	struct tty_ldisc *ld;
+	struct tty_ldisc *ld = tty_ldisc_get(ldisc);
+
+	if (IS_ERR(ld))
+		return -1;
 
 	tty_ldisc_close(tty, tty->ldisc);
 	tty_ldisc_put(tty->ldisc);
@@ -722,10 +725,10 @@ static void tty_ldisc_reinit(struct tty_
 	/*
 	 *	Switch the line discipline back
 	 */
-	ld = tty_ldisc_get(ldisc);
-	BUG_ON(IS_ERR(ld));
 	tty_ldisc_assign(tty, ld);
 	tty_set_termios_ldisc(tty, ldisc);
+
+	return 0;
 }
 
 /**
@@ -787,13 +790,16 @@ void tty_ldisc_hangup(struct tty_struct 
 	   a FIXME */
 	if (tty->ldisc) {	/* Not yet closed */
 		if (reset == 0) {
-			tty_ldisc_reinit(tty, tty->termios->c_line);
-			err = tty_ldisc_open(tty, tty->ldisc);
+			
+			if (!tty_ldisc_reinit(tty, tty->termios->c_line))
+				err = tty_ldisc_open(tty, tty->ldisc);
+			else
+				err = 1;
 		}
 		/* If the re-open fails or we reset then go to N_TTY. The
 		   N_TTY open cannot fail */
 		if (reset || err) {
-			tty_ldisc_reinit(tty, N_TTY);
+			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
 			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
 		}
 		tty_ldisc_enable(tty);

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

* Re: [PATCH] tty_ldisc: Fix BUG() on hangup
  2010-10-26 15:49 [PATCH] tty_ldisc: Fix BUG() on hangup Philippe Rétornaz
@ 2010-10-26 16:13 ` Alan Cox
  2010-10-27 15:13   ` Philippe Rétornaz
  0 siblings, 1 reply; 3+ messages in thread
From: Alan Cox @ 2010-10-26 16:13 UTC (permalink / raw)
  To: Philippe Rétornaz; +Cc: Alan Cox, Greg Kroah-Hartman, linux-kernel

On Tue, 26 Oct 2010 17:49:03 +0200
Philippe Rétornaz <philippe.retornaz@epfl.ch> wrote:

> Hello
> 
> A kernel BUG when bluetooth rfcomm connection drop while 
> the associated serial port is open is sometime triggered.
> 
> It seems that the line discipline can disappear between the tty_ldisc_put  and 
> tty_ldisc_get. This patch fall back to the N_TTY line discipline if the 
> previous discipline is not available anymore.
> 
> This seem to fix the BUG(), but I don't know if it's correct.

I can see what you are trying to handle, and in theory you could if you
unload modules as they go unused hit a race there - I'm amazed it's
possible however.

The first part looks right - grab the reference before changing over and
error if it isn't available, and the second part follows logically,
although that bit of the hangup code is looking even more untidy now.

Acked-by: Alan Cox <alan@linux.intel.com>

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

* [PATCH] tty_ldisc: Fix BUG() on hangup
  2010-10-26 16:13 ` Alan Cox
@ 2010-10-27 15:13   ` Philippe Rétornaz
  0 siblings, 0 replies; 3+ messages in thread
From: Philippe Rétornaz @ 2010-10-27 15:13 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Alan Cox, linux-kernel

A kernel BUG when bluetooth rfcomm connection drop while 
the associated serial port is open is sometime triggered.

It seems that the line discipline can disappear between the tty_ldisc_put  and 
tty_ldisc_get. This patch fall back to the N_TTY line discipline if the 
previous discipline is not available anymore.

Signed-off-by: Philippe Retornaz <philippe.retornaz@epfl.ch>
Acked-by: Alan Cox <alan@linux.intel.com>

---

--- linux-2.6.34.x86_64/drivers/char/tty_ldisc.c.orig	2010-05-16 23:17:36.000000000 +0200
+++ linux-2.6.34.x86_64/drivers/char/tty_ldisc.c	2010-10-15 10:48:01.871721197 +0200
@@ -712,9 +712,12 @@ static void tty_reset_termios(struct tty
  *	state closed
  */
 
-static void tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
+static int tty_ldisc_reinit(struct tty_struct *tty, int ldisc)
 {
-	struct tty_ldisc *ld;
+	struct tty_ldisc *ld = tty_ldisc_get(ldisc);
+
+	if (IS_ERR(ld))
+		return -1;
 
 	tty_ldisc_close(tty, tty->ldisc);
 	tty_ldisc_put(tty->ldisc);
@@ -722,10 +725,10 @@ static void tty_ldisc_reinit(struct tty_
 	/*
 	 *	Switch the line discipline back
 	 */
-	ld = tty_ldisc_get(ldisc);
-	BUG_ON(IS_ERR(ld));
 	tty_ldisc_assign(tty, ld);
 	tty_set_termios_ldisc(tty, ldisc);
+
+	return 0;
 }
 
 /**
@@ -787,13 +790,16 @@ void tty_ldisc_hangup(struct tty_struct 
 	   a FIXME */
 	if (tty->ldisc) {	/* Not yet closed */
 		if (reset == 0) {
-			tty_ldisc_reinit(tty, tty->termios->c_line);
-			err = tty_ldisc_open(tty, tty->ldisc);
+			
+			if (!tty_ldisc_reinit(tty, tty->termios->c_line))
+				err = tty_ldisc_open(tty, tty->ldisc);
+			else
+				err = 1;
 		}
 		/* If the re-open fails or we reset then go to N_TTY. The
 		   N_TTY open cannot fail */
 		if (reset || err) {
-			tty_ldisc_reinit(tty, N_TTY);
+			BUG_ON(tty_ldisc_reinit(tty, N_TTY));
 			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
 		}
 		tty_ldisc_enable(tty);

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

end of thread, other threads:[~2010-10-27 15:13 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-26 15:49 [PATCH] tty_ldisc: Fix BUG() on hangup Philippe Rétornaz
2010-10-26 16:13 ` Alan Cox
2010-10-27 15:13   ` Philippe Rétornaz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).