aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-11-30 08:18:29 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2009-12-11 18:18:08 -0500
commiteeb89d918c2fa2b809e464136bbafdaec2aacb30 (patch)
treed811f53e0182c40a793b948e72739040670f97c8
parente8c62103fd5fecc8d2086bae244b32d089892175 (diff)
tty: push the BKL down into the handlers a bit
Start trying to untangle the remaining BKL mess Updated to fix missing unlock_kernel noted by Dan Carpenter Signed-off-by: Alan "I must be out of my tree" Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/char/pty.c2
-rw-r--r--drivers/char/tty_io.c141
-rw-r--r--drivers/char/tty_ldisc.c13
-rw-r--r--include/linux/tty.h2
4 files changed, 95 insertions, 63 deletions
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index d86c0bc05c1c..385c44b3034f 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -659,7 +659,7 @@ static int __ptmx_open(struct inode *inode, struct file *filp)
659 if (!retval) 659 if (!retval)
660 return 0; 660 return 0;
661out1: 661out1:
662 tty_release_dev(filp); 662 tty_release(inode, filp);
663 return retval; 663 return retval;
664out: 664out:
665 devpts_kill_index(inode, index); 665 devpts_kill_index(inode, index);
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 59499ee0fe6a..1e2413093615 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -142,7 +142,6 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
142 size_t, loff_t *); 142 size_t, loff_t *);
143static unsigned int tty_poll(struct file *, poll_table *); 143static unsigned int tty_poll(struct file *, poll_table *);
144static int tty_open(struct inode *, struct file *); 144static int tty_open(struct inode *, struct file *);
145static int tty_release(struct inode *, struct file *);
146long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg); 145long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
147#ifdef CONFIG_COMPAT 146#ifdef CONFIG_COMPAT
148static long tty_compat_ioctl(struct file *file, unsigned int cmd, 147static long tty_compat_ioctl(struct file *file, unsigned int cmd,
@@ -1017,14 +1016,16 @@ out:
1017 1016
1018void tty_write_message(struct tty_struct *tty, char *msg) 1017void tty_write_message(struct tty_struct *tty, char *msg)
1019{ 1018{
1020 lock_kernel();
1021 if (tty) { 1019 if (tty) {
1022 mutex_lock(&tty->atomic_write_lock); 1020 mutex_lock(&tty->atomic_write_lock);
1023 if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) 1021 lock_kernel();
1022 if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) {
1023 unlock_kernel();
1024 tty->ops->write(tty, msg, strlen(msg)); 1024 tty->ops->write(tty, msg, strlen(msg));
1025 } else
1026 unlock_kernel();
1025 tty_write_unlock(tty); 1027 tty_write_unlock(tty);
1026 } 1028 }
1027 unlock_kernel();
1028 return; 1029 return;
1029} 1030}
1030 1031
@@ -1202,14 +1203,21 @@ static int tty_driver_install_tty(struct tty_driver *driver,
1202 struct tty_struct *tty) 1203 struct tty_struct *tty)
1203{ 1204{
1204 int idx = tty->index; 1205 int idx = tty->index;
1206 int ret;
1205 1207
1206 if (driver->ops->install) 1208 if (driver->ops->install) {
1207 return driver->ops->install(driver, tty); 1209 lock_kernel();
1210 ret = driver->ops->install(driver, tty);
1211 unlock_kernel();
1212 return ret;
1213 }
1208 1214
1209 if (tty_init_termios(tty) == 0) { 1215 if (tty_init_termios(tty) == 0) {
1216 lock_kernel();
1210 tty_driver_kref_get(driver); 1217 tty_driver_kref_get(driver);
1211 tty->count++; 1218 tty->count++;
1212 driver->ttys[idx] = tty; 1219 driver->ttys[idx] = tty;
1220 unlock_kernel();
1213 return 0; 1221 return 0;
1214 } 1222 }
1215 return -ENOMEM; 1223 return -ENOMEM;
@@ -1302,10 +1310,14 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
1302 struct tty_struct *tty; 1310 struct tty_struct *tty;
1303 int retval; 1311 int retval;
1304 1312
1313 lock_kernel();
1305 /* Check if pty master is being opened multiple times */ 1314 /* Check if pty master is being opened multiple times */
1306 if (driver->subtype == PTY_TYPE_MASTER && 1315 if (driver->subtype == PTY_TYPE_MASTER &&
1307 (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) 1316 (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) {
1317 unlock_kernel();
1308 return ERR_PTR(-EIO); 1318 return ERR_PTR(-EIO);
1319 }
1320 unlock_kernel();
1309 1321
1310 /* 1322 /*
1311 * First time open is complex, especially for PTY devices. 1323 * First time open is complex, especially for PTY devices.
@@ -1335,8 +1347,9 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
1335 * If we fail here just call release_tty to clean up. No need 1347 * If we fail here just call release_tty to clean up. No need
1336 * to decrement the use counts, as release_tty doesn't care. 1348 * to decrement the use counts, as release_tty doesn't care.
1337 */ 1349 */
1338 1350 lock_kernel();
1339 retval = tty_ldisc_setup(tty, tty->link); 1351 retval = tty_ldisc_setup(tty, tty->link);
1352 unlock_kernel();
1340 if (retval) 1353 if (retval)
1341 goto release_mem_out; 1354 goto release_mem_out;
1342 return tty; 1355 return tty;
@@ -1350,7 +1363,9 @@ release_mem_out:
1350 if (printk_ratelimit()) 1363 if (printk_ratelimit())
1351 printk(KERN_INFO "tty_init_dev: ldisc open failed, " 1364 printk(KERN_INFO "tty_init_dev: ldisc open failed, "
1352 "clearing slot %d\n", idx); 1365 "clearing slot %d\n", idx);
1366 lock_kernel();
1353 release_tty(tty, idx); 1367 release_tty(tty, idx);
1368 unlock_kernel();
1354 return ERR_PTR(retval); 1369 return ERR_PTR(retval);
1355} 1370}
1356 1371
@@ -1464,7 +1479,17 @@ static void release_tty(struct tty_struct *tty, int idx)
1464 tty_kref_put(tty); 1479 tty_kref_put(tty);
1465} 1480}
1466 1481
1467/* 1482/**
1483 * tty_release - vfs callback for close
1484 * @inode: inode of tty
1485 * @filp: file pointer for handle to tty
1486 *
1487 * Called the last time each file handle is closed that references
1488 * this tty. There may however be several such references.
1489 *
1490 * Locking:
1491 * Takes bkl. See tty_release_dev
1492 *
1468 * Even releasing the tty structures is a tricky business.. We have 1493 * Even releasing the tty structures is a tricky business.. We have
1469 * to be very careful that the structures are all released at the 1494 * to be very careful that the structures are all released at the
1470 * same time, as interrupts might otherwise get the wrong pointers. 1495 * same time, as interrupts might otherwise get the wrong pointers.
@@ -1472,20 +1497,20 @@ static void release_tty(struct tty_struct *tty, int idx)
1472 * WSH 09/09/97: rewritten to avoid some nasty race conditions that could 1497 * WSH 09/09/97: rewritten to avoid some nasty race conditions that could
1473 * lead to double frees or releasing memory still in use. 1498 * lead to double frees or releasing memory still in use.
1474 */ 1499 */
1475void tty_release_dev(struct file *filp) 1500
1501int tty_release(struct inode *inode, struct file *filp)
1476{ 1502{
1477 struct tty_struct *tty, *o_tty; 1503 struct tty_struct *tty, *o_tty;
1478 int pty_master, tty_closing, o_tty_closing, do_sleep; 1504 int pty_master, tty_closing, o_tty_closing, do_sleep;
1479 int devpts; 1505 int devpts;
1480 int idx; 1506 int idx;
1481 char buf[64]; 1507 char buf[64];
1482 struct inode *inode;
1483 1508
1484 inode = filp->f_path.dentry->d_inode;
1485 tty = (struct tty_struct *)filp->private_data; 1509 tty = (struct tty_struct *)filp->private_data;
1486 if (tty_paranoia_check(tty, inode, "tty_release_dev")) 1510 if (tty_paranoia_check(tty, inode, "tty_release_dev"))
1487 return; 1511 return 0;
1488 1512
1513 lock_kernel();
1489 check_tty_count(tty, "tty_release_dev"); 1514 check_tty_count(tty, "tty_release_dev");
1490 1515
1491 tty_fasync(-1, filp, 0); 1516 tty_fasync(-1, filp, 0);
@@ -1500,19 +1525,22 @@ void tty_release_dev(struct file *filp)
1500 if (idx < 0 || idx >= tty->driver->num) { 1525 if (idx < 0 || idx >= tty->driver->num) {
1501 printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " 1526 printk(KERN_DEBUG "tty_release_dev: bad idx when trying to "
1502 "free (%s)\n", tty->name); 1527 "free (%s)\n", tty->name);
1503 return; 1528 unlock_kernel();
1529 return 0;
1504 } 1530 }
1505 if (!devpts) { 1531 if (!devpts) {
1506 if (tty != tty->driver->ttys[idx]) { 1532 if (tty != tty->driver->ttys[idx]) {
1533 unlock_kernel();
1507 printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " 1534 printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty "
1508 "for (%s)\n", idx, tty->name); 1535 "for (%s)\n", idx, tty->name);
1509 return; 1536 return 0;
1510 } 1537 }
1511 if (tty->termios != tty->driver->termios[idx]) { 1538 if (tty->termios != tty->driver->termios[idx]) {
1539 unlock_kernel();
1512 printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " 1540 printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios "
1513 "for (%s)\n", 1541 "for (%s)\n",
1514 idx, tty->name); 1542 idx, tty->name);
1515 return; 1543 return 0;
1516 } 1544 }
1517 } 1545 }
1518#endif 1546#endif
@@ -1526,26 +1554,30 @@ void tty_release_dev(struct file *filp)
1526 if (tty->driver->other && 1554 if (tty->driver->other &&
1527 !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { 1555 !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) {
1528 if (o_tty != tty->driver->other->ttys[idx]) { 1556 if (o_tty != tty->driver->other->ttys[idx]) {
1557 unlock_kernel();
1529 printk(KERN_DEBUG "tty_release_dev: other->table[%d] " 1558 printk(KERN_DEBUG "tty_release_dev: other->table[%d] "
1530 "not o_tty for (%s)\n", 1559 "not o_tty for (%s)\n",
1531 idx, tty->name); 1560 idx, tty->name);
1532 return; 1561 return 0 ;
1533 } 1562 }
1534 if (o_tty->termios != tty->driver->other->termios[idx]) { 1563 if (o_tty->termios != tty->driver->other->termios[idx]) {
1564 unlock_kernel();
1535 printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " 1565 printk(KERN_DEBUG "tty_release_dev: other->termios[%d] "
1536 "not o_termios for (%s)\n", 1566 "not o_termios for (%s)\n",
1537 idx, tty->name); 1567 idx, tty->name);
1538 return; 1568 return 0;
1539 } 1569 }
1540 if (o_tty->link != tty) { 1570 if (o_tty->link != tty) {
1571 unlock_kernel();
1541 printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); 1572 printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n");
1542 return; 1573 return 0;
1543 } 1574 }
1544 } 1575 }
1545#endif 1576#endif
1546 if (tty->ops->close) 1577 if (tty->ops->close)
1547 tty->ops->close(tty, filp); 1578 tty->ops->close(tty, filp);
1548 1579
1580 unlock_kernel();
1549 /* 1581 /*
1550 * Sanity check: if tty->count is going to zero, there shouldn't be 1582 * Sanity check: if tty->count is going to zero, there shouldn't be
1551 * any waiters on tty->read_wait or tty->write_wait. We test the 1583 * any waiters on tty->read_wait or tty->write_wait. We test the
@@ -1568,6 +1600,7 @@ void tty_release_dev(struct file *filp)
1568 opens on /dev/tty */ 1600 opens on /dev/tty */
1569 1601
1570 mutex_lock(&tty_mutex); 1602 mutex_lock(&tty_mutex);
1603 lock_kernel();
1571 tty_closing = tty->count <= 1; 1604 tty_closing = tty->count <= 1;
1572 o_tty_closing = o_tty && 1605 o_tty_closing = o_tty &&
1573 (o_tty->count <= (pty_master ? 1 : 0)); 1606 (o_tty->count <= (pty_master ? 1 : 0));
@@ -1598,6 +1631,7 @@ void tty_release_dev(struct file *filp)
1598 1631
1599 printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " 1632 printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue "
1600 "active!\n", tty_name(tty, buf)); 1633 "active!\n", tty_name(tty, buf));
1634 unlock_kernel();
1601 mutex_unlock(&tty_mutex); 1635 mutex_unlock(&tty_mutex);
1602 schedule(); 1636 schedule();
1603 } 1637 }
@@ -1661,8 +1695,10 @@ void tty_release_dev(struct file *filp)
1661 mutex_unlock(&tty_mutex); 1695 mutex_unlock(&tty_mutex);
1662 1696
1663 /* check whether both sides are closing ... */ 1697 /* check whether both sides are closing ... */
1664 if (!tty_closing || (o_tty && !o_tty_closing)) 1698 if (!tty_closing || (o_tty && !o_tty_closing)) {
1665 return; 1699 unlock_kernel();
1700 return 0;
1701 }
1666 1702
1667#ifdef TTY_DEBUG_HANGUP 1703#ifdef TTY_DEBUG_HANGUP
1668 printk(KERN_DEBUG "freeing tty structure..."); 1704 printk(KERN_DEBUG "freeing tty structure...");
@@ -1680,10 +1716,12 @@ void tty_release_dev(struct file *filp)
1680 /* Make this pty number available for reallocation */ 1716 /* Make this pty number available for reallocation */
1681 if (devpts) 1717 if (devpts)
1682 devpts_kill_index(inode, idx); 1718 devpts_kill_index(inode, idx);
1719 unlock_kernel();
1720 return 0;
1683} 1721}
1684 1722
1685/** 1723/**
1686 * __tty_open - open a tty device 1724 * tty_open - open a tty device
1687 * @inode: inode of device file 1725 * @inode: inode of device file
1688 * @filp: file pointer to tty 1726 * @filp: file pointer to tty
1689 * 1727 *
@@ -1703,7 +1741,7 @@ void tty_release_dev(struct file *filp)
1703 * ->siglock protects ->signal/->sighand 1741 * ->siglock protects ->signal/->sighand
1704 */ 1742 */
1705 1743
1706static int __tty_open(struct inode *inode, struct file *filp) 1744static int tty_open(struct inode *inode, struct file *filp)
1707{ 1745{
1708 struct tty_struct *tty = NULL; 1746 struct tty_struct *tty = NULL;
1709 int noctty, retval; 1747 int noctty, retval;
@@ -1720,10 +1758,12 @@ retry_open:
1720 retval = 0; 1758 retval = 0;
1721 1759
1722 mutex_lock(&tty_mutex); 1760 mutex_lock(&tty_mutex);
1761 lock_kernel();
1723 1762
1724 if (device == MKDEV(TTYAUX_MAJOR, 0)) { 1763 if (device == MKDEV(TTYAUX_MAJOR, 0)) {
1725 tty = get_current_tty(); 1764 tty = get_current_tty();
1726 if (!tty) { 1765 if (!tty) {
1766 unlock_kernel();
1727 mutex_unlock(&tty_mutex); 1767 mutex_unlock(&tty_mutex);
1728 return -ENXIO; 1768 return -ENXIO;
1729 } 1769 }
@@ -1755,12 +1795,14 @@ retry_open:
1755 goto got_driver; 1795 goto got_driver;
1756 } 1796 }
1757 } 1797 }
1798 unlock_kernel();
1758 mutex_unlock(&tty_mutex); 1799 mutex_unlock(&tty_mutex);
1759 return -ENODEV; 1800 return -ENODEV;
1760 } 1801 }
1761 1802
1762 driver = get_tty_driver(device, &index); 1803 driver = get_tty_driver(device, &index);
1763 if (!driver) { 1804 if (!driver) {
1805 unlock_kernel();
1764 mutex_unlock(&tty_mutex); 1806 mutex_unlock(&tty_mutex);
1765 return -ENODEV; 1807 return -ENODEV;
1766 } 1808 }
@@ -1770,6 +1812,7 @@ got_driver:
1770 tty = tty_driver_lookup_tty(driver, inode, index); 1812 tty = tty_driver_lookup_tty(driver, inode, index);
1771 1813
1772 if (IS_ERR(tty)) { 1814 if (IS_ERR(tty)) {
1815 unlock_kernel();
1773 mutex_unlock(&tty_mutex); 1816 mutex_unlock(&tty_mutex);
1774 return PTR_ERR(tty); 1817 return PTR_ERR(tty);
1775 } 1818 }
@@ -1784,8 +1827,10 @@ got_driver:
1784 1827
1785 mutex_unlock(&tty_mutex); 1828 mutex_unlock(&tty_mutex);
1786 tty_driver_kref_put(driver); 1829 tty_driver_kref_put(driver);
1787 if (IS_ERR(tty)) 1830 if (IS_ERR(tty)) {
1831 unlock_kernel();
1788 return PTR_ERR(tty); 1832 return PTR_ERR(tty);
1833 }
1789 1834
1790 filp->private_data = tty; 1835 filp->private_data = tty;
1791 file_move(filp, &tty->tty_files); 1836 file_move(filp, &tty->tty_files);
@@ -1813,11 +1858,15 @@ got_driver:
1813 printk(KERN_DEBUG "error %d in opening %s...", retval, 1858 printk(KERN_DEBUG "error %d in opening %s...", retval,
1814 tty->name); 1859 tty->name);
1815#endif 1860#endif
1816 tty_release_dev(filp); 1861 tty_release(inode, filp);
1817 if (retval != -ERESTARTSYS) 1862 if (retval != -ERESTARTSYS) {
1863 unlock_kernel();
1818 return retval; 1864 return retval;
1819 if (signal_pending(current)) 1865 }
1866 if (signal_pending(current)) {
1867 unlock_kernel();
1820 return retval; 1868 return retval;
1869 }
1821 schedule(); 1870 schedule();
1822 /* 1871 /*
1823 * Need to reset f_op in case a hangup happened. 1872 * Need to reset f_op in case a hangup happened.
@@ -1826,8 +1875,11 @@ got_driver:
1826 filp->f_op = &tty_fops; 1875 filp->f_op = &tty_fops;
1827 goto retry_open; 1876 goto retry_open;
1828 } 1877 }
1878 unlock_kernel();
1879
1829 1880
1830 mutex_lock(&tty_mutex); 1881 mutex_lock(&tty_mutex);
1882 lock_kernel();
1831 spin_lock_irq(&current->sighand->siglock); 1883 spin_lock_irq(&current->sighand->siglock);
1832 if (!noctty && 1884 if (!noctty &&
1833 current->signal->leader && 1885 current->signal->leader &&
@@ -1835,44 +1887,13 @@ got_driver:
1835 tty->session == NULL) 1887 tty->session == NULL)
1836 __proc_set_tty(current, tty); 1888 __proc_set_tty(current, tty);
1837 spin_unlock_irq(&current->sighand->siglock); 1889 spin_unlock_irq(&current->sighand->siglock);
1890 unlock_kernel();
1838 mutex_unlock(&tty_mutex); 1891 mutex_unlock(&tty_mutex);
1839 return 0; 1892 return 0;
1840} 1893}
1841 1894
1842/* BKL pushdown: scary code avoidance wrapper */
1843static int tty_open(struct inode *inode, struct file *filp)
1844{
1845 int ret;
1846
1847 lock_kernel();
1848 ret = __tty_open(inode, filp);
1849 unlock_kernel();
1850 return ret;
1851}
1852 1895
1853 1896
1854
1855
1856/**
1857 * tty_release - vfs callback for close
1858 * @inode: inode of tty
1859 * @filp: file pointer for handle to tty
1860 *
1861 * Called the last time each file handle is closed that references
1862 * this tty. There may however be several such references.
1863 *
1864 * Locking:
1865 * Takes bkl. See tty_release_dev
1866 */
1867
1868static int tty_release(struct inode *inode, struct file *filp)
1869{
1870 lock_kernel();
1871 tty_release_dev(filp);
1872 unlock_kernel();
1873 return 0;
1874}
1875
1876/** 1897/**
1877 * tty_poll - check tty status 1898 * tty_poll - check tty status
1878 * @filp: file being polled 1899 * @filp: file being polled
@@ -2317,9 +2338,7 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
2317 if (get_user(ldisc, p)) 2338 if (get_user(ldisc, p))
2318 return -EFAULT; 2339 return -EFAULT;
2319 2340
2320 lock_kernel();
2321 ret = tty_set_ldisc(tty, ldisc); 2341 ret = tty_set_ldisc(tty, ldisc);
2322 unlock_kernel();
2323 2342
2324 return ret; 2343 return ret;
2325} 2344}
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index feb55075819b..d914e77f7f01 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -34,6 +34,8 @@
34#include <linux/vt_kern.h> 34#include <linux/vt_kern.h>
35#include <linux/selection.h> 35#include <linux/selection.h>
36 36
37#include <linux/smp_lock.h> /* For the moment */
38
37#include <linux/kmod.h> 39#include <linux/kmod.h>
38#include <linux/nsproxy.h> 40#include <linux/nsproxy.h>
39 41
@@ -545,6 +547,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
545 if (IS_ERR(new_ldisc)) 547 if (IS_ERR(new_ldisc))
546 return PTR_ERR(new_ldisc); 548 return PTR_ERR(new_ldisc);
547 549
550 lock_kernel();
548 /* 551 /*
549 * We need to look at the tty locking here for pty/tty pairs 552 * We need to look at the tty locking here for pty/tty pairs
550 * when both sides try to change in parallel. 553 * when both sides try to change in parallel.
@@ -558,6 +561,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
558 */ 561 */
559 562
560 if (tty->ldisc->ops->num == ldisc) { 563 if (tty->ldisc->ops->num == ldisc) {
564 unlock_kernel();
561 tty_ldisc_put(new_ldisc); 565 tty_ldisc_put(new_ldisc);
562 return 0; 566 return 0;
563 } 567 }
@@ -569,6 +573,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
569 573
570 tty_wait_until_sent(tty, 0); 574 tty_wait_until_sent(tty, 0);
571 575
576 unlock_kernel();
572 mutex_lock(&tty->ldisc_mutex); 577 mutex_lock(&tty->ldisc_mutex);
573 578
574 /* 579 /*
@@ -582,6 +587,9 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
582 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); 587 test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0);
583 mutex_lock(&tty->ldisc_mutex); 588 mutex_lock(&tty->ldisc_mutex);
584 } 589 }
590
591 lock_kernel();
592
585 set_bit(TTY_LDISC_CHANGING, &tty->flags); 593 set_bit(TTY_LDISC_CHANGING, &tty->flags);
586 594
587 /* 595 /*
@@ -592,6 +600,8 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
592 tty->receive_room = 0; 600 tty->receive_room = 0;
593 601
594 o_ldisc = tty->ldisc; 602 o_ldisc = tty->ldisc;
603
604 unlock_kernel();
595 /* 605 /*
596 * Make sure we don't change while someone holds a 606 * Make sure we don't change while someone holds a
597 * reference to the line discipline. The TTY_LDISC bit 607 * reference to the line discipline. The TTY_LDISC bit
@@ -617,12 +627,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
617 flush_scheduled_work(); 627 flush_scheduled_work();
618 628
619 mutex_lock(&tty->ldisc_mutex); 629 mutex_lock(&tty->ldisc_mutex);
630 lock_kernel();
620 if (test_bit(TTY_HUPPED, &tty->flags)) { 631 if (test_bit(TTY_HUPPED, &tty->flags)) {
621 /* We were raced by the hangup method. It will have stomped 632 /* We were raced by the hangup method. It will have stomped
622 the ldisc data and closed the ldisc down */ 633 the ldisc data and closed the ldisc down */
623 clear_bit(TTY_LDISC_CHANGING, &tty->flags); 634 clear_bit(TTY_LDISC_CHANGING, &tty->flags);
624 mutex_unlock(&tty->ldisc_mutex); 635 mutex_unlock(&tty->ldisc_mutex);
625 tty_ldisc_put(new_ldisc); 636 tty_ldisc_put(new_ldisc);
637 unlock_kernel();
626 return -EIO; 638 return -EIO;
627 } 639 }
628 640
@@ -664,6 +676,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc)
664 if (o_work) 676 if (o_work)
665 schedule_delayed_work(&o_tty->buf.work, 1); 677 schedule_delayed_work(&o_tty->buf.work, 1);
666 mutex_unlock(&tty->ldisc_mutex); 678 mutex_unlock(&tty->ldisc_mutex);
679 unlock_kernel();
667 return retval; 680 return retval;
668} 681}
669 682
diff --git a/include/linux/tty.h b/include/linux/tty.h
index e6da667ba34d..405a9035fe40 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -449,7 +449,7 @@ extern void initialize_tty_struct(struct tty_struct *tty,
449 struct tty_driver *driver, int idx); 449 struct tty_driver *driver, int idx);
450extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, 450extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx,
451 int first_ok); 451 int first_ok);
452extern void tty_release_dev(struct file *filp); 452extern int tty_release(struct inode *inode, struct file *filp);
453extern int tty_init_termios(struct tty_struct *tty); 453extern int tty_init_termios(struct tty_struct *tty);
454 454
455extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty); 455extern struct tty_struct *tty_pair_get_tty(struct tty_struct *tty);