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 98b6e3bdb000..7613f95f2d6b 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
| @@ -657,12 +657,18 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 657 | 657 | ||
| 658 | nonseekable_open(inode, filp); | 658 | nonseekable_open(inode, filp); |
| 659 | 659 | ||
| 660 | retval = tty_alloc_file(filp); | ||
| 661 | if (retval) | ||
| 662 | return retval; | ||
| 663 | |||
| 660 | /* find a device that is not in use. */ | 664 | /* find a device that is not in use. */ |
| 661 | tty_lock(); | 665 | tty_lock(); |
| 662 | index = devpts_new_index(inode); | 666 | index = devpts_new_index(inode); |
| 663 | tty_unlock(); | 667 | tty_unlock(); |
| 664 | if (index < 0) | 668 | if (index < 0) { |
| 665 | return index; | 669 | retval = index; |
| 670 | goto err_file; | ||
| 671 | } | ||
| 666 | 672 | ||
| 667 | mutex_lock(&tty_mutex); | 673 | mutex_lock(&tty_mutex); |
| 668 | tty_lock(); | 674 | tty_lock(); |
| @@ -676,9 +682,7 @@ static int ptmx_open(struct inode *inode, struct file *filp) | |||
| 676 | 682 | ||
| 677 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ | 683 | set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ |
| 678 | 684 | ||
| 679 | retval = tty_add_file(tty, filp); | 685 | tty_add_file(tty, filp); |
| 680 | if (retval) | ||
| 681 | goto out; | ||
| 682 | 686 | ||
| 683 | retval = devpts_pty_new(inode, tty->link); | 687 | retval = devpts_pty_new(inode, tty->link); |
| 684 | if (retval) | 688 | if (retval) |
| @@ -697,6 +701,8 @@ out2: | |||
| 697 | out: | 701 | out: |
| 698 | devpts_kill_index(inode, index); | 702 | devpts_kill_index(inode, index); |
| 699 | tty_unlock(); | 703 | tty_unlock(); |
| 704 | err_file: | ||
| 705 | tty_free_file(filp); | ||
| 700 | return retval; | 706 | return retval; |
| 701 | } | 707 | } |
| 702 | 708 | ||
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 6913da8f202c..767ecbb4761a 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
| @@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file) | |||
| 194 | return ((struct tty_file_private *)file->private_data)->tty; | 194 | return ((struct tty_file_private *)file->private_data)->tty; |
| 195 | } | 195 | } |
| 196 | 196 | ||
| 197 | /* Associate a new file with the tty structure */ | 197 | int tty_alloc_file(struct file *file) |
| 198 | int tty_add_file(struct tty_struct *tty, struct file *file) | ||
| 199 | { | 198 | { |
| 200 | struct tty_file_private *priv; | 199 | struct tty_file_private *priv; |
| 201 | 200 | ||
| @@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file) | |||
| 203 | if (!priv) | 202 | if (!priv) |
| 204 | return -ENOMEM; | 203 | return -ENOMEM; |
| 205 | 204 | ||
| 205 | file->private_data = priv; | ||
| 206 | |||
| 207 | return 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | /* Associate a new file with the tty structure */ | ||
| 211 | void tty_add_file(struct tty_struct *tty, struct file *file) | ||
| 212 | { | ||
| 213 | struct tty_file_private *priv = file->private_data; | ||
| 214 | |||
| 206 | priv->tty = tty; | 215 | priv->tty = tty; |
| 207 | priv->file = file; | 216 | priv->file = file; |
| 208 | file->private_data = priv; | ||
| 209 | 217 | ||
| 210 | spin_lock(&tty_files_lock); | 218 | spin_lock(&tty_files_lock); |
| 211 | list_add(&priv->list, &tty->tty_files); | 219 | list_add(&priv->list, &tty->tty_files); |
| 212 | spin_unlock(&tty_files_lock); | 220 | spin_unlock(&tty_files_lock); |
| 221 | } | ||
| 213 | 222 | ||
| 214 | return 0; | 223 | /** |
| 224 | * tty_free_file - free file->private_data | ||
| 225 | * | ||
| 226 | * This shall be used only for fail path handling when tty_add_file was not | ||
| 227 | * called yet. | ||
| 228 | */ | ||
| 229 | void tty_free_file(struct file *file) | ||
| 230 | { | ||
| 231 | struct tty_file_private *priv = file->private_data; | ||
| 232 | |||
| 233 | file->private_data = NULL; | ||
| 234 | kfree(priv); | ||
| 215 | } | 235 | } |
| 216 | 236 | ||
| 217 | /* Delete file from its tty */ | 237 | /* Delete file from its tty */ |
| @@ -222,8 +242,7 @@ void tty_del_file(struct file *file) | |||
| 222 | spin_lock(&tty_files_lock); | 242 | spin_lock(&tty_files_lock); |
| 223 | list_del(&priv->list); | 243 | list_del(&priv->list); |
| 224 | spin_unlock(&tty_files_lock); | 244 | spin_unlock(&tty_files_lock); |
| 225 | file->private_data = NULL; | 245 | tty_free_file(file); |
| 226 | kfree(priv); | ||
| 227 | } | 246 | } |
| 228 | 247 | ||
| 229 | 248 | ||
| @@ -1812,6 +1831,10 @@ static int tty_open(struct inode *inode, struct file *filp) | |||
| 1812 | nonseekable_open(inode, filp); | 1831 | nonseekable_open(inode, filp); |
| 1813 | 1832 | ||
| 1814 | retry_open: | 1833 | retry_open: |
| 1834 | retval = tty_alloc_file(filp); | ||
| 1835 | if (retval) | ||
| 1836 | return -ENOMEM; | ||
| 1837 | |||
| 1815 | noctty = filp->f_flags & O_NOCTTY; | 1838 | noctty = filp->f_flags & O_NOCTTY; |
| 1816 | index = -1; | 1839 | index = -1; |
| 1817 | retval = 0; | 1840 | retval = 0; |
| @@ -1824,6 +1847,7 @@ retry_open: | |||
| 1824 | if (!tty) { | 1847 | if (!tty) { |
| 1825 | tty_unlock(); | 1848 | tty_unlock(); |
| 1826 | mutex_unlock(&tty_mutex); | 1849 | mutex_unlock(&tty_mutex); |
| 1850 | tty_free_file(filp); | ||
| 1827 | return -ENXIO; | 1851 | return -ENXIO; |
| 1828 | } | 1852 | } |
| 1829 | driver = tty_driver_kref_get(tty->driver); | 1853 | driver = tty_driver_kref_get(tty->driver); |
| @@ -1856,6 +1880,7 @@ retry_open: | |||
| 1856 | } | 1880 | } |
| 1857 | tty_unlock(); | 1881 | tty_unlock(); |
| 1858 | mutex_unlock(&tty_mutex); | 1882 | mutex_unlock(&tty_mutex); |
| 1883 | tty_free_file(filp); | ||
| 1859 | return -ENODEV; | 1884 | return -ENODEV; |
| 1860 | } | 1885 | } |
| 1861 | 1886 | ||
| @@ -1863,6 +1888,7 @@ retry_open: | |||
| 1863 | if (!driver) { | 1888 | if (!driver) { |
| 1864 | tty_unlock(); | 1889 | tty_unlock(); |
| 1865 | mutex_unlock(&tty_mutex); | 1890 | mutex_unlock(&tty_mutex); |
| 1891 | tty_free_file(filp); | ||
| 1866 | return -ENODEV; | 1892 | return -ENODEV; |
| 1867 | } | 1893 | } |
| 1868 | got_driver: | 1894 | got_driver: |
| @@ -1874,6 +1900,7 @@ got_driver: | |||
| 1874 | tty_unlock(); | 1900 | tty_unlock(); |
| 1875 | mutex_unlock(&tty_mutex); | 1901 | mutex_unlock(&tty_mutex); |
| 1876 | tty_driver_kref_put(driver); | 1902 | tty_driver_kref_put(driver); |
| 1903 | tty_free_file(filp); | ||
| 1877 | return PTR_ERR(tty); | 1904 | return PTR_ERR(tty); |
| 1878 | } | 1905 | } |
| 1879 | } | 1906 | } |
| @@ -1889,15 +1916,11 @@ got_driver: | |||
| 1889 | tty_driver_kref_put(driver); | 1916 | tty_driver_kref_put(driver); |
| 1890 | if (IS_ERR(tty)) { | 1917 | if (IS_ERR(tty)) { |
| 1891 | tty_unlock(); | 1918 | tty_unlock(); |
| 1919 | tty_free_file(filp); | ||
| 1892 | return PTR_ERR(tty); | 1920 | return PTR_ERR(tty); |
| 1893 | } | 1921 | } |
| 1894 | 1922 | ||
| 1895 | retval = tty_add_file(tty, filp); | 1923 | tty_add_file(tty, filp); |
| 1896 | if (retval) { | ||
| 1897 | tty_unlock(); | ||
| 1898 | tty_release(inode, filp); | ||
| 1899 | return retval; | ||
| 1900 | } | ||
| 1901 | 1924 | ||
| 1902 | check_tty_count(tty, "tty_open"); | 1925 | check_tty_count(tty, "tty_open"); |
| 1903 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 1926 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 64c12a3e65f0..ff2925aa4e79 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
| @@ -471,7 +471,9 @@ extern void proc_clear_tty(struct task_struct *p); | |||
| 471 | extern struct tty_struct *get_current_tty(void); | 471 | extern struct tty_struct *get_current_tty(void); |
| 472 | extern void tty_default_fops(struct file_operations *fops); | 472 | extern void tty_default_fops(struct file_operations *fops); |
| 473 | extern struct tty_struct *alloc_tty_struct(void); | 473 | extern struct tty_struct *alloc_tty_struct(void); |
| 474 | extern int tty_add_file(struct tty_struct *tty, struct file *file); | 474 | extern int tty_alloc_file(struct file *file); |
| 475 | extern void tty_add_file(struct tty_struct *tty, struct file *file); | ||
| 476 | extern void tty_free_file(struct file *file); | ||
| 475 | extern void free_tty_struct(struct tty_struct *tty); | 477 | extern void free_tty_struct(struct tty_struct *tty); |
| 476 | extern void initialize_tty_struct(struct tty_struct *tty, | 478 | extern void initialize_tty_struct(struct tty_struct *tty, |
| 477 | struct tty_driver *driver, int idx); | 479 | struct tty_driver *driver, int idx); |
