diff options
-rw-r--r-- | drivers/tty/pty.c | 16 | ||||
-rw-r--r-- | drivers/tty/tty_io.c | 47 | ||||
-rw-r--r-- | include/linux/tty.h | 4 |
3 files changed, 49 insertions, 18 deletions
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index e809e9d4683c..696e8510a5f4 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -670,12 +670,18 @@ static int ptmx_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); + retval = tty_alloc_file(filp); + if (retval) + return retval; + /* find a device that is not in use. */ tty_lock(); index = devpts_new_index(inode); tty_unlock(); - if (index < 0) - return index; + if (index < 0) { + retval = index; + goto err_file; + } mutex_lock(&tty_mutex); tty_lock(); @@ -689,9 +695,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ - retval = tty_add_file(tty, filp); - if (retval) - goto out; + tty_add_file(tty, filp); retval = devpts_pty_new(inode, tty->link); if (retval) @@ -710,6 +714,8 @@ out2: out: devpts_kill_index(inode, index); tty_unlock(); +err_file: + tty_free_file(filp); return retval; } diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index e9495ed8ec01..b44aef078f10 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -193,8 +193,7 @@ static inline struct tty_struct *file_tty(struct file *file) return ((struct tty_file_private *)file->private_data)->tty; } -/* Associate a new file with the tty structure */ -int tty_add_file(struct tty_struct *tty, struct file *file) +int tty_alloc_file(struct file *file) { struct tty_file_private *priv; @@ -202,15 +201,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file) if (!priv) return -ENOMEM; + file->private_data = priv; + + return 0; +} + +/* Associate a new file with the tty structure */ +void tty_add_file(struct tty_struct *tty, struct file *file) +{ + struct tty_file_private *priv = file->private_data; + priv->tty = tty; priv->file = file; - file->private_data = priv; spin_lock(&tty_files_lock); list_add(&priv->list, &tty->tty_files); spin_unlock(&tty_files_lock); +} - return 0; +/** + * tty_free_file - free file->private_data + * + * This shall be used only for fail path handling when tty_add_file was not + * called yet. + */ +void tty_free_file(struct file *file) +{ + struct tty_file_private *priv = file->private_data; + + file->private_data = NULL; + kfree(priv); } /* Delete file from its tty */ @@ -221,8 +241,7 @@ void tty_del_file(struct file *file) spin_lock(&tty_files_lock); list_del(&priv->list); spin_unlock(&tty_files_lock); - file->private_data = NULL; - kfree(priv); + tty_free_file(file); } @@ -1811,6 +1830,10 @@ static int tty_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); retry_open: + retval = tty_alloc_file(filp); + if (retval) + return -ENOMEM; + noctty = filp->f_flags & O_NOCTTY; index = -1; retval = 0; @@ -1823,6 +1846,7 @@ retry_open: if (!tty) { tty_unlock(); mutex_unlock(&tty_mutex); + tty_free_file(filp); return -ENXIO; } driver = tty_driver_kref_get(tty->driver); @@ -1855,6 +1879,7 @@ retry_open: } tty_unlock(); mutex_unlock(&tty_mutex); + tty_free_file(filp); return -ENODEV; } @@ -1862,6 +1887,7 @@ retry_open: if (!driver) { tty_unlock(); mutex_unlock(&tty_mutex); + tty_free_file(filp); return -ENODEV; } got_driver: @@ -1873,6 +1899,7 @@ got_driver: tty_unlock(); mutex_unlock(&tty_mutex); tty_driver_kref_put(driver); + tty_free_file(filp); return PTR_ERR(tty); } } @@ -1888,15 +1915,11 @@ got_driver: tty_driver_kref_put(driver); if (IS_ERR(tty)) { tty_unlock(); + tty_free_file(filp); return PTR_ERR(tty); } - retval = tty_add_file(tty, filp); - if (retval) { - tty_unlock(); - tty_release(inode, filp); - return retval; - } + tty_add_file(tty, filp); check_tty_count(tty, "tty_open"); if (tty->driver->type == TTY_DRIVER_TYPE_PTY && diff --git a/include/linux/tty.h b/include/linux/tty.h index 6660c41949ba..1ff6b62fb697 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -472,7 +472,9 @@ extern void proc_clear_tty(struct task_struct *p); extern struct tty_struct *get_current_tty(void); extern void tty_default_fops(struct file_operations *fops); extern struct tty_struct *alloc_tty_struct(void); -extern int tty_add_file(struct tty_struct *tty, struct file *file); +extern int tty_alloc_file(struct file *file); +extern void tty_add_file(struct tty_struct *tty, struct file *file); +extern void tty_free_file(struct file *file); extern void free_tty_struct(struct tty_struct *tty); extern void initialize_tty_struct(struct tty_struct *tty, struct tty_driver *driver, int idx); |