aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/tty_io.c10
-rw-r--r--include/linux/tty.h1
2 files changed, 10 insertions, 1 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 615ecf37e28..e0f7f4b8c28 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -553,6 +553,9 @@ void __tty_hangup(struct tty_struct *tty)
tty_lock();
+ /* some functions below drop BTM, so we need this bit */
+ set_bit(TTY_HUPPING, &tty->flags);
+
/* inuse_filps is protected by the single tty lock,
this really needs to change if we want to flush the
workqueue with the lock held */
@@ -572,6 +575,10 @@ void __tty_hangup(struct tty_struct *tty)
}
spin_unlock(&tty_files_lock);
+ /*
+ * it drops BTM and thus races with reopen
+ * we protect the race by TTY_HUPPING
+ */
tty_ldisc_hangup(tty);
read_lock(&tasklist_lock);
@@ -609,7 +616,6 @@ void __tty_hangup(struct tty_struct *tty)
tty->session = NULL;
tty->pgrp = NULL;
tty->ctrl_status = 0;
- set_bit(TTY_HUPPED, &tty->flags);
spin_unlock_irqrestore(&tty->ctrl_lock, flags);
/* Account for the p->signal references we killed */
@@ -635,6 +641,7 @@ void __tty_hangup(struct tty_struct *tty)
* can't yet guarantee all that.
*/
set_bit(TTY_HUPPED, &tty->flags);
+ clear_bit(TTY_HUPPING, &tty->flags);
tty_ldisc_enable(tty);
tty_unlock();
@@ -1305,6 +1312,7 @@ static int tty_reopen(struct tty_struct *tty)
struct tty_driver *driver = tty->driver;
if (test_bit(TTY_CLOSING, &tty->flags) ||
+ test_bit(TTY_HUPPING, &tty->flags) ||
test_bit(TTY_LDISC_CHANGING, &tty->flags))
return -EIO;
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 67d64e6efe7..6f62c305581 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -365,6 +365,7 @@ struct tty_file_private {
#define TTY_HUPPED 18 /* Post driver->hangup() */
#define TTY_FLUSHING 19 /* Flushing to ldisc in progress */
#define TTY_FLUSHPENDING 20 /* Queued buffer flush pending */
+#define TTY_HUPPING 21 /* ->hangup() in progress */
#define TTY_WRITE_FLUSH(tty) tty_write_flush((tty))