diff options
Diffstat (limited to 'drivers/tty/pty.c')
-rw-r--r-- | drivers/tty/pty.c | 40 |
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 @@ #include <linux/bitops.h> #include <linux/devpts_fs.h> #include <linux/slab.h> +#include <linux/mutex.h> #ifdef CONFIG_UNIX98_PTYS static struct tty_driver *ptm_driver; static struct tty_driver *pts_driver; +static DEFINE_MUTEX(devpts_mutex); #endif static 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) wake_up_interruptible(&tty->read_wait); wake_up_interruptible(&tty->write_wait); tty->packet = 0; + /* Review - krefs on tty_link ?? */ if (!tty->link) return; tty->link->packet = 0; @@ -54,12 +57,15 @@ static void pty_close(struct tty_struct *tty, struct file *filp) if (tty->driver->subtype == PTY_TYPE_MASTER) { set_bit(TTY_OTHER_CLOSED, &tty->flags); #ifdef CONFIG_UNIX98_PTYS - if (tty->driver == ptm_driver) + if (tty->driver == ptm_driver) { + mutex_lock(&devpts_mutex); devpts_pty_kill(tty->link); + mutex_unlock(&devpts_mutex); + } #endif - tty_unlock(); + tty_unlock(tty); tty_vhangup(tty->link); - tty_lock(); + tty_lock(tty); } } @@ -475,13 +481,17 @@ static struct tty_struct *ptm_unix98_lookup(struct tty_driver *driver, * @idx: tty index * * Look up a pty master device. Called under the tty_mutex for now. - * This provides our locking. + * This provides our locking for the tty pointer. */ static struct tty_struct *pts_unix98_lookup(struct tty_driver *driver, struct inode *pts_inode, int idx) { - struct tty_struct *tty = devpts_get_tty(pts_inode, idx); + struct tty_struct *tty; + + mutex_lock(&devpts_mutex); + tty = devpts_get_tty(pts_inode, idx); + mutex_unlock(&devpts_mutex); /* Master must be open before slave */ if (!tty) return ERR_PTR(-EIO); @@ -613,24 +623,29 @@ static int ptmx_open(struct inode *inode, struct file *filp) return retval; /* find a device that is not in use. */ - tty_lock(); + mutex_lock(&devpts_mutex); index = devpts_new_index(inode); - tty_unlock(); if (index < 0) { retval = index; goto err_file; } + mutex_unlock(&devpts_mutex); + mutex_lock(&tty_mutex); - tty_lock(); + mutex_lock(&devpts_mutex); tty = tty_init_dev(ptm_driver, index); - mutex_unlock(&tty_mutex); if (IS_ERR(tty)) { retval = PTR_ERR(tty); goto out; } + /* The tty returned here is locked so we can safely + drop the mutex */ + mutex_unlock(&devpts_mutex); + mutex_unlock(&tty_mutex); + set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ tty_add_file(tty, filp); @@ -643,16 +658,17 @@ static int ptmx_open(struct inode *inode, struct file *filp) if (retval) goto err_release; - tty_unlock(); + tty_unlock(tty); return 0; err_release: - tty_unlock(); + tty_unlock(tty); tty_release(inode, filp); return retval; out: + mutex_unlock(&tty_mutex); devpts_kill_index(inode, index); - tty_unlock(); err_file: + mutex_unlock(&devpts_mutex); tty_free_file(filp); return retval; } |