aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/tty/pty.c16
-rw-r--r--drivers/tty/tty_io.c47
-rw-r--r--include/linux/tty.h4
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:
697out: 701out:
698 devpts_kill_index(inode, index); 702 devpts_kill_index(inode, index);
699 tty_unlock(); 703 tty_unlock();
704err_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 */ 197int tty_alloc_file(struct file *file)
198int 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 */
211void 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 */
229void 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
1814retry_open: 1833retry_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 }
1868got_driver: 1894got_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);
471extern struct tty_struct *get_current_tty(void); 471extern struct tty_struct *get_current_tty(void);
472extern void tty_default_fops(struct file_operations *fops); 472extern void tty_default_fops(struct file_operations *fops);
473extern struct tty_struct *alloc_tty_struct(void); 473extern struct tty_struct *alloc_tty_struct(void);
474extern int tty_add_file(struct tty_struct *tty, struct file *file); 474extern int tty_alloc_file(struct file *file);
475extern void tty_add_file(struct tty_struct *tty, struct file *file);
476extern void tty_free_file(struct file *file);
475extern void free_tty_struct(struct tty_struct *tty); 477extern void free_tty_struct(struct tty_struct *tty);
476extern void initialize_tty_struct(struct tty_struct *tty, 478extern void initialize_tty_struct(struct tty_struct *tty,
477 struct tty_driver *driver, int idx); 479 struct tty_driver *driver, int idx);