diff options
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r-- | drivers/char/tty_io.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 613c852ee0fe..e0f7f4b8c286 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
@@ -553,6 +553,9 @@ void __tty_hangup(struct tty_struct *tty) | |||
553 | 553 | ||
554 | tty_lock(); | 554 | tty_lock(); |
555 | 555 | ||
556 | /* some functions below drop BTM, so we need this bit */ | ||
557 | set_bit(TTY_HUPPING, &tty->flags); | ||
558 | |||
556 | /* inuse_filps is protected by the single tty lock, | 559 | /* inuse_filps is protected by the single tty lock, |
557 | this really needs to change if we want to flush the | 560 | this really needs to change if we want to flush the |
558 | workqueue with the lock held */ | 561 | workqueue with the lock held */ |
@@ -572,6 +575,10 @@ void __tty_hangup(struct tty_struct *tty) | |||
572 | } | 575 | } |
573 | spin_unlock(&tty_files_lock); | 576 | spin_unlock(&tty_files_lock); |
574 | 577 | ||
578 | /* | ||
579 | * it drops BTM and thus races with reopen | ||
580 | * we protect the race by TTY_HUPPING | ||
581 | */ | ||
575 | tty_ldisc_hangup(tty); | 582 | tty_ldisc_hangup(tty); |
576 | 583 | ||
577 | read_lock(&tasklist_lock); | 584 | read_lock(&tasklist_lock); |
@@ -609,7 +616,6 @@ void __tty_hangup(struct tty_struct *tty) | |||
609 | tty->session = NULL; | 616 | tty->session = NULL; |
610 | tty->pgrp = NULL; | 617 | tty->pgrp = NULL; |
611 | tty->ctrl_status = 0; | 618 | tty->ctrl_status = 0; |
612 | set_bit(TTY_HUPPED, &tty->flags); | ||
613 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 619 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
614 | 620 | ||
615 | /* Account for the p->signal references we killed */ | 621 | /* Account for the p->signal references we killed */ |
@@ -635,6 +641,7 @@ void __tty_hangup(struct tty_struct *tty) | |||
635 | * can't yet guarantee all that. | 641 | * can't yet guarantee all that. |
636 | */ | 642 | */ |
637 | set_bit(TTY_HUPPED, &tty->flags); | 643 | set_bit(TTY_HUPPED, &tty->flags); |
644 | clear_bit(TTY_HUPPING, &tty->flags); | ||
638 | tty_ldisc_enable(tty); | 645 | tty_ldisc_enable(tty); |
639 | 646 | ||
640 | tty_unlock(); | 647 | tty_unlock(); |
@@ -1304,7 +1311,9 @@ static int tty_reopen(struct tty_struct *tty) | |||
1304 | { | 1311 | { |
1305 | struct tty_driver *driver = tty->driver; | 1312 | struct tty_driver *driver = tty->driver; |
1306 | 1313 | ||
1307 | if (test_bit(TTY_CLOSING, &tty->flags)) | 1314 | if (test_bit(TTY_CLOSING, &tty->flags) || |
1315 | test_bit(TTY_HUPPING, &tty->flags) || | ||
1316 | test_bit(TTY_LDISC_CHANGING, &tty->flags)) | ||
1308 | return -EIO; | 1317 | return -EIO; |
1309 | 1318 | ||
1310 | if (driver->type == TTY_DRIVER_TYPE_PTY && | 1319 | if (driver->type == TTY_DRIVER_TYPE_PTY && |