aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/pty.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/pty.c')
-rw-r--r--drivers/tty/pty.c40
1 files changed, 28 insertions, 12 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index eeae7fafe9a7..59af3945ea85 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -26,11 +26,13 @@
26#include <linux/bitops.h> 26#include <linux/bitops.h>
27#include <linux/devpts_fs.h> 27#include <linux/devpts_fs.h>
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/mutex.h>
29 30
30 31
31#ifdef CONFIG_UNIX98_PTYS 32#ifdef CONFIG_UNIX98_PTYS
32static struct tty_driver *ptm_driver; 33static struct tty_driver *ptm_driver;
33static struct tty_driver *pts_driver; 34static struct tty_driver *pts_driver;
35static DEFINE_MUTEX(devpts_mutex);
34#endif 36#endif
35 37
36static void pty_close(struct tty_struct *tty, struct file *filp) 38static void pty_close(struct tty_struct *tty, struct file *filp)
@@ -45,6 +47,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
45 wake_up_interruptible(&tty->read_wait); 47 wake_up_interruptible(&tty->read_wait);
46 wake_up_interruptible(&tty->write_wait); 48 wake_up_interruptible(&tty->write_wait);
47 tty->packet = 0; 49 tty->packet = 0;
50 /* Review - krefs on tty_link ?? */
48 if (!tty->link) 51 if (!tty->link)
49 return; 52 return;
50 tty->link->packet = 0; 53 tty->link->packet = 0;
@@ -54,12 +57,15 @@ static void pty_close(struct tty_struct *tty, struct file *filp)
54 if (tty->driver->subtype == PTY_TYPE_MASTER) { 57 if (tty->driver->subtype == PTY_TYPE_MASTER) {
55 set_bit(TTY_OTHER_CLOSED, &tty->flags); 58 set_bit(TTY_OTHER_CLOSED, &tty->flags);
56#ifdef CONFIG_UNIX98_PTYS 59#ifdef CONFIG_UNIX98_PTYS
57 if (tty->driver == ptm_driver) 60 if (tty->driver == ptm_driver) {
61 mutex_lock(&devpts_mutex);
58 devpts_pty_kill(tty->link); 62 devpts_pty_kill(tty->link);
63 mutex_unlock(&devpts_mutex);
64 }
59#endif 65#endif
60 tty_unlock(); 66 tty_unlock(tty);
61 tty_vhangup(tty->link); 67 tty_vhangup(tty->link);
62 tty_lock(); 68 tty_lock(tty);
63 } 69 }
64} 70}
65 71
@@ -475,13 +481,17 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver,
475 * @idx: tty index 481 * @idx: tty index
476 * 482 *
477 * Look up a pty master device. Called under the tty_mutex for now. 483 * Look up a pty master device. Called under the tty_mutex for now.
478 * This provides our locking. 484 * This provides our locking for the tty pointer.
479 */ 485 */
480 486
481static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, 487static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver,
482 struct inode *pts_inode, int idx) 488 struct inode *pts_inode, int idx)
483{ 489{
484 struct tty_struct *tty = devpts_get_tty(pts_inode, idx); 490 struct tty_struct *tty;
491
492 mutex_lock(&devpts_mutex);
493 tty = devpts_get_tty(pts_inode, idx);
494 mutex_unlock(&devpts_mutex);
485 /* Master must be open before slave */ 495 /* Master must be open before slave */
486 if (!tty) 496 if (!tty)
487 return ERR_PTR(-EIO); 497 return ERR_PTR(-EIO);
@@ -613,24 +623,29 @@ static int ptmx_open(struct inode *inode, struct file *filp)
613 return retval; 623 return retval;
614 624
615 /* find a device that is not in use. */ 625 /* find a device that is not in use. */
616 tty_lock(); 626 mutex_lock(&devpts_mutex);
617 index = devpts_new_index(inode); 627 index = devpts_new_index(inode);
618 tty_unlock();
619 if (index < 0) { 628 if (index < 0) {
620 retval = index; 629 retval = index;
621 goto err_file; 630 goto err_file;
622 } 631 }
623 632
633 mutex_unlock(&devpts_mutex);
634
624 mutex_lock(&tty_mutex); 635 mutex_lock(&tty_mutex);
625 tty_lock(); 636 mutex_lock(&devpts_mutex);
626 tty = tty_init_dev(ptm_driver, index); 637 tty = tty_init_dev(ptm_driver, index);
627 mutex_unlock(&tty_mutex);
628 638
629 if (IS_ERR(tty)) { 639 if (IS_ERR(tty)) {
630 retval = PTR_ERR(tty); 640 retval = PTR_ERR(tty);
631 goto out; 641 goto out;
632 } 642 }
633 643
644 /* The tty returned here is locked so we can safely
645 drop the mutex */
646 mutex_unlock(&devpts_mutex);
647 mutex_unlock(&tty_mutex);
648
634 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 649 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
635 650
636 tty_add_file(tty, filp); 651 tty_add_file(tty, filp);
@@ -643,16 +658,17 @@ static int ptmx_open(struct inode *inode, struct file *filp)
643 if (retval) 658 if (retval)
644 goto err_release; 659 goto err_release;
645 660
646 tty_unlock(); 661 tty_unlock(tty);
647 return 0; 662 return 0;
648err_release: 663err_release:
649 tty_unlock(); 664 tty_unlock(tty);
650 tty_release(inode, filp); 665 tty_release(inode, filp);
651 return retval; 666 return retval;
652out: 667out:
668 mutex_unlock(&tty_mutex);
653 devpts_kill_index(inode, index); 669 devpts_kill_index(inode, index);
654 tty_unlock();
655err_file: 670err_file:
671 mutex_unlock(&devpts_mutex);
656 tty_free_file(filp); 672 tty_free_file(filp);
657 return retval; 673 return retval;
658} 674}