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); |