diff options
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index b6f92d3..b44aef0 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: @@ -1872,6 +1898,8 @@ got_driver: if (IS_ERR(tty)) { tty_unlock(); mutex_unlock(&tty_mutex); + tty_driver_kref_put(driver); + tty_free_file(filp); return PTR_ERR(tty); } } @@ -1887,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 && |