aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/tty_io.c
diff options
context:
space:
mode:
authorAlan Cox <alan@lxorguk.ukuu.org.uk>2008-04-30 03:53:29 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-30 11:29:40 -0400
commit04f378b198da233ca0aca341b113dc6579d46123 (patch)
tree696e7bd401125cee71ecaa2047c4273f38732554 /drivers/char/tty_io.c
parente52384426064bca0669a954736206adca7595d48 (diff)
tty: BKL pushdown
- Push the BKL down into the line disciplines - Switch the tty layer to unlocked_ioctl - Introduce a new ctrl_lock spin lock for the control bits - Eliminate much of the lock_kernel use in n_tty - Prepare to (but don't yet) call the drivers with the lock dropped on the paths that historically held the lock BKL now primarily protects open/close/ldisc change in the tty layer [jirislaby@gmail.com: a couple of fixes] Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/tty_io.c')
-rw-r--r--drivers/char/tty_io.c107
1 files changed, 74 insertions, 33 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 2fa6856706ab..0b0354bc28d6 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -152,8 +152,7 @@ ssize_t redirected_tty_write(struct file *, const char __user *,
152static unsigned int tty_poll(struct file *, poll_table *); 152static unsigned int tty_poll(struct file *, poll_table *);
153static int tty_open(struct inode *, struct file *); 153static int tty_open(struct inode *, struct file *);
154static int tty_release(struct inode *, struct file *); 154static int tty_release(struct inode *, struct file *);
155int tty_ioctl(struct inode *inode, struct file *file, 155long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
156 unsigned int cmd, unsigned long arg);
157#ifdef CONFIG_COMPAT 156#ifdef CONFIG_COMPAT
158static long tty_compat_ioctl(struct file *file, unsigned int cmd, 157static long tty_compat_ioctl(struct file *file, unsigned int cmd,
159 unsigned long arg); 158 unsigned long arg);
@@ -1205,7 +1204,7 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
1205 * not in the foreground, send a SIGTTOU. If the signal is blocked or 1204 * not in the foreground, send a SIGTTOU. If the signal is blocked or
1206 * ignored, go ahead and perform the operation. (POSIX 7.2) 1205 * ignored, go ahead and perform the operation. (POSIX 7.2)
1207 * 1206 *
1208 * Locking: none 1207 * Locking: none - FIXME: review this
1209 */ 1208 */
1210 1209
1211int tty_check_change(struct tty_struct *tty) 1210int tty_check_change(struct tty_struct *tty)
@@ -1247,8 +1246,8 @@ static unsigned int hung_up_tty_poll(struct file *filp, poll_table *wait)
1247 return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM; 1246 return POLLIN | POLLOUT | POLLERR | POLLHUP | POLLRDNORM | POLLWRNORM;
1248} 1247}
1249 1248
1250static int hung_up_tty_ioctl(struct inode *inode, struct file *file, 1249static long hung_up_tty_ioctl(struct file *file, unsigned int cmd,
1251 unsigned int cmd, unsigned long arg) 1250 unsigned long arg)
1252{ 1251{
1253 return cmd == TIOCSPGRP ? -ENOTTY : -EIO; 1252 return cmd == TIOCSPGRP ? -ENOTTY : -EIO;
1254} 1253}
@@ -1264,7 +1263,7 @@ static const struct file_operations tty_fops = {
1264 .read = tty_read, 1263 .read = tty_read,
1265 .write = tty_write, 1264 .write = tty_write,
1266 .poll = tty_poll, 1265 .poll = tty_poll,
1267 .ioctl = tty_ioctl, 1266 .unlocked_ioctl = tty_ioctl,
1268 .compat_ioctl = tty_compat_ioctl, 1267 .compat_ioctl = tty_compat_ioctl,
1269 .open = tty_open, 1268 .open = tty_open,
1270 .release = tty_release, 1269 .release = tty_release,
@@ -1277,7 +1276,7 @@ static const struct file_operations ptmx_fops = {
1277 .read = tty_read, 1276 .read = tty_read,
1278 .write = tty_write, 1277 .write = tty_write,
1279 .poll = tty_poll, 1278 .poll = tty_poll,
1280 .ioctl = tty_ioctl, 1279 .unlocked_ioctl = tty_ioctl,
1281 .compat_ioctl = tty_compat_ioctl, 1280 .compat_ioctl = tty_compat_ioctl,
1282 .open = ptmx_open, 1281 .open = ptmx_open,
1283 .release = tty_release, 1282 .release = tty_release,
@@ -1290,7 +1289,7 @@ static const struct file_operations console_fops = {
1290 .read = tty_read, 1289 .read = tty_read,
1291 .write = redirected_tty_write, 1290 .write = redirected_tty_write,
1292 .poll = tty_poll, 1291 .poll = tty_poll,
1293 .ioctl = tty_ioctl, 1292 .unlocked_ioctl = tty_ioctl,
1294 .compat_ioctl = tty_compat_ioctl, 1293 .compat_ioctl = tty_compat_ioctl,
1295 .open = tty_open, 1294 .open = tty_open,
1296 .release = tty_release, 1295 .release = tty_release,
@@ -1302,7 +1301,7 @@ static const struct file_operations hung_up_tty_fops = {
1302 .read = hung_up_tty_read, 1301 .read = hung_up_tty_read,
1303 .write = hung_up_tty_write, 1302 .write = hung_up_tty_write,
1304 .poll = hung_up_tty_poll, 1303 .poll = hung_up_tty_poll,
1305 .ioctl = hung_up_tty_ioctl, 1304 .unlocked_ioctl = hung_up_tty_ioctl,
1306 .compat_ioctl = hung_up_tty_compat_ioctl, 1305 .compat_ioctl = hung_up_tty_compat_ioctl,
1307 .release = tty_release, 1306 .release = tty_release,
1308}; 1307};
@@ -1626,16 +1625,17 @@ void disassociate_ctty(int on_exit)
1626 struct tty_struct *tty; 1625 struct tty_struct *tty;
1627 struct pid *tty_pgrp = NULL; 1626 struct pid *tty_pgrp = NULL;
1628 1627
1629 lock_kernel();
1630 1628
1631 mutex_lock(&tty_mutex); 1629 mutex_lock(&tty_mutex);
1632 tty = get_current_tty(); 1630 tty = get_current_tty();
1633 if (tty) { 1631 if (tty) {
1634 tty_pgrp = get_pid(tty->pgrp); 1632 tty_pgrp = get_pid(tty->pgrp);
1635 mutex_unlock(&tty_mutex); 1633 mutex_unlock(&tty_mutex);
1634 lock_kernel();
1636 /* XXX: here we race, there is nothing protecting tty */ 1635 /* XXX: here we race, there is nothing protecting tty */
1637 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) 1636 if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY)
1638 tty_vhangup(tty); 1637 tty_vhangup(tty);
1638 unlock_kernel();
1639 } else if (on_exit) { 1639 } else if (on_exit) {
1640 struct pid *old_pgrp; 1640 struct pid *old_pgrp;
1641 spin_lock_irq(&current->sighand->siglock); 1641 spin_lock_irq(&current->sighand->siglock);
@@ -1648,7 +1648,6 @@ void disassociate_ctty(int on_exit)
1648 put_pid(old_pgrp); 1648 put_pid(old_pgrp);
1649 } 1649 }
1650 mutex_unlock(&tty_mutex); 1650 mutex_unlock(&tty_mutex);
1651 unlock_kernel();
1652 return; 1651 return;
1653 } 1652 }
1654 if (tty_pgrp) { 1653 if (tty_pgrp) {
@@ -1683,7 +1682,6 @@ void disassociate_ctty(int on_exit)
1683 read_lock(&tasklist_lock); 1682 read_lock(&tasklist_lock);
1684 session_clear_tty(task_session(current)); 1683 session_clear_tty(task_session(current));
1685 read_unlock(&tasklist_lock); 1684 read_unlock(&tasklist_lock);
1686 unlock_kernel();
1687} 1685}
1688 1686
1689/** 1687/**
@@ -1693,8 +1691,10 @@ void disassociate_ctty(int on_exit)
1693void no_tty(void) 1691void no_tty(void)
1694{ 1692{
1695 struct task_struct *tsk = current; 1693 struct task_struct *tsk = current;
1694 lock_kernel();
1696 if (tsk->signal->leader) 1695 if (tsk->signal->leader)
1697 disassociate_ctty(0); 1696 disassociate_ctty(0);
1697 unlock_kernel();
1698 proc_clear_tty(tsk); 1698 proc_clear_tty(tsk);
1699} 1699}
1700 1700
@@ -1714,19 +1714,24 @@ void no_tty(void)
1714 * but not always. 1714 * but not always.
1715 * 1715 *
1716 * Locking: 1716 * Locking:
1717 * Broken. Relies on BKL which is unsafe here. 1717 * Uses the tty control lock internally
1718 */ 1718 */
1719 1719
1720void stop_tty(struct tty_struct *tty) 1720void stop_tty(struct tty_struct *tty)
1721{ 1721{
1722 if (tty->stopped) 1722 unsigned long flags;
1723 spin_lock_irqsave(&tty->ctrl_lock, flags);
1724 if (tty->stopped) {
1725 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1723 return; 1726 return;
1727 }
1724 tty->stopped = 1; 1728 tty->stopped = 1;
1725 if (tty->link && tty->link->packet) { 1729 if (tty->link && tty->link->packet) {
1726 tty->ctrl_status &= ~TIOCPKT_START; 1730 tty->ctrl_status &= ~TIOCPKT_START;
1727 tty->ctrl_status |= TIOCPKT_STOP; 1731 tty->ctrl_status |= TIOCPKT_STOP;
1728 wake_up_interruptible(&tty->link->read_wait); 1732 wake_up_interruptible(&tty->link->read_wait);
1729 } 1733 }
1734 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1730 if (tty->driver->stop) 1735 if (tty->driver->stop)
1731 (tty->driver->stop)(tty); 1736 (tty->driver->stop)(tty);
1732} 1737}
@@ -1743,19 +1748,24 @@ EXPORT_SYMBOL(stop_tty);
1743 * driver start method is invoked and the line discipline woken. 1748 * driver start method is invoked and the line discipline woken.
1744 * 1749 *
1745 * Locking: 1750 * Locking:
1746 * Broken. Relies on BKL which is unsafe here. 1751 * ctrl_lock
1747 */ 1752 */
1748 1753
1749void start_tty(struct tty_struct *tty) 1754void start_tty(struct tty_struct *tty)
1750{ 1755{
1751 if (!tty->stopped || tty->flow_stopped) 1756 unsigned long flags;
1757 spin_lock_irqsave(&tty->ctrl_lock, flags);
1758 if (!tty->stopped || tty->flow_stopped) {
1759 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1752 return; 1760 return;
1761 }
1753 tty->stopped = 0; 1762 tty->stopped = 0;
1754 if (tty->link && tty->link->packet) { 1763 if (tty->link && tty->link->packet) {
1755 tty->ctrl_status &= ~TIOCPKT_STOP; 1764 tty->ctrl_status &= ~TIOCPKT_STOP;
1756 tty->ctrl_status |= TIOCPKT_START; 1765 tty->ctrl_status |= TIOCPKT_START;
1757 wake_up_interruptible(&tty->link->read_wait); 1766 wake_up_interruptible(&tty->link->read_wait);
1758 } 1767 }
1768 spin_unlock_irqrestore(&tty->ctrl_lock, flags);
1759 if (tty->driver->start) 1769 if (tty->driver->start)
1760 (tty->driver->start)(tty); 1770 (tty->driver->start)(tty);
1761 /* If we have a running line discipline it may need kicking */ 1771 /* If we have a running line discipline it may need kicking */
@@ -1799,13 +1809,11 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count,
1799 /* We want to wait for the line discipline to sort out in this 1809 /* We want to wait for the line discipline to sort out in this
1800 situation */ 1810 situation */
1801 ld = tty_ldisc_ref_wait(tty); 1811 ld = tty_ldisc_ref_wait(tty);
1802 lock_kernel();
1803 if (ld->read) 1812 if (ld->read)
1804 i = (ld->read)(tty, file, buf, count); 1813 i = (ld->read)(tty, file, buf, count);
1805 else 1814 else
1806 i = -EIO; 1815 i = -EIO;
1807 tty_ldisc_deref(ld); 1816 tty_ldisc_deref(ld);
1808 unlock_kernel();
1809 if (i > 0) 1817 if (i > 0)
1810 inode->i_atime = current_fs_time(inode->i_sb); 1818 inode->i_atime = current_fs_time(inode->i_sb);
1811 return i; 1819 return i;
@@ -1893,9 +1901,7 @@ static inline ssize_t do_tty_write(
1893 ret = -EFAULT; 1901 ret = -EFAULT;
1894 if (copy_from_user(tty->write_buf, buf, size)) 1902 if (copy_from_user(tty->write_buf, buf, size))
1895 break; 1903 break;
1896 lock_kernel();
1897 ret = write(tty, file, tty->write_buf, size); 1904 ret = write(tty, file, tty->write_buf, size);
1898 unlock_kernel();
1899 if (ret <= 0) 1905 if (ret <= 0)
1900 break; 1906 break;
1901 written += ret; 1907 written += ret;
@@ -3070,10 +3076,13 @@ static int fionbio(struct file *file, int __user *p)
3070 if (get_user(nonblock, p)) 3076 if (get_user(nonblock, p))
3071 return -EFAULT; 3077 return -EFAULT;
3072 3078
3079 /* file->f_flags is still BKL protected in the fs layer - vomit */
3080 lock_kernel();
3073 if (nonblock) 3081 if (nonblock)
3074 file->f_flags |= O_NONBLOCK; 3082 file->f_flags |= O_NONBLOCK;
3075 else 3083 else
3076 file->f_flags &= ~O_NONBLOCK; 3084 file->f_flags &= ~O_NONBLOCK;
3085 unlock_kernel();
3077 return 0; 3086 return 0;
3078} 3087}
3079 3088
@@ -3162,7 +3171,7 @@ static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t
3162 * Set the process group of the tty to the session passed. Only 3171 * Set the process group of the tty to the session passed. Only
3163 * permitted where the tty session is our session. 3172 * permitted where the tty session is our session.
3164 * 3173 *
3165 * Locking: None 3174 * Locking: RCU
3166 */ 3175 */
3167 3176
3168static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p) 3177static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
@@ -3237,10 +3246,16 @@ static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t _
3237static int tiocsetd(struct tty_struct *tty, int __user *p) 3246static int tiocsetd(struct tty_struct *tty, int __user *p)
3238{ 3247{
3239 int ldisc; 3248 int ldisc;
3249 int ret;
3240 3250
3241 if (get_user(ldisc, p)) 3251 if (get_user(ldisc, p))
3242 return -EFAULT; 3252 return -EFAULT;
3243 return tty_set_ldisc(tty, ldisc); 3253
3254 lock_kernel();
3255 ret = tty_set_ldisc(tty, ldisc);
3256 unlock_kernel();
3257
3258 return ret;
3244} 3259}
3245 3260
3246/** 3261/**
@@ -3258,16 +3273,21 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
3258 3273
3259static int send_break(struct tty_struct *tty, unsigned int duration) 3274static int send_break(struct tty_struct *tty, unsigned int duration)
3260{ 3275{
3276 int retval = -EINTR;
3277
3278 lock_kernel();
3261 if (tty_write_lock(tty, 0) < 0) 3279 if (tty_write_lock(tty, 0) < 0)
3262 return -EINTR; 3280 goto out;
3263 tty->driver->break_ctl(tty, -1); 3281 tty->driver->break_ctl(tty, -1);
3264 if (!signal_pending(current)) 3282 if (!signal_pending(current))
3265 msleep_interruptible(duration); 3283 msleep_interruptible(duration);
3266 tty->driver->break_ctl(tty, 0); 3284 tty->driver->break_ctl(tty, 0);
3267 tty_write_unlock(tty); 3285 tty_write_unlock(tty);
3268 if (signal_pending(current)) 3286 if (!signal_pending(current))
3269 return -EINTR; 3287 retval = 0;
3270 return 0; 3288out:
3289 unlock_kernel();
3290 return retval;
3271} 3291}
3272 3292
3273/** 3293/**
@@ -3287,7 +3307,9 @@ static int tty_tiocmget(struct tty_struct *tty, struct file *file, int __user *p
3287 int retval = -EINVAL; 3307 int retval = -EINVAL;
3288 3308
3289 if (tty->driver->tiocmget) { 3309 if (tty->driver->tiocmget) {
3310 lock_kernel();
3290 retval = tty->driver->tiocmget(tty, file); 3311 retval = tty->driver->tiocmget(tty, file);
3312 unlock_kernel();
3291 3313
3292 if (retval >= 0) 3314 if (retval >= 0)
3293 retval = put_user(retval, p); 3315 retval = put_user(retval, p);
@@ -3337,7 +3359,9 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
3337 set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; 3359 set &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
3338 clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP; 3360 clear &= TIOCM_DTR|TIOCM_RTS|TIOCM_OUT1|TIOCM_OUT2|TIOCM_LOOP;
3339 3361
3362 lock_kernel();
3340 retval = tty->driver->tiocmset(tty, file, set, clear); 3363 retval = tty->driver->tiocmset(tty, file, set, clear);
3364 unlock_kernel();
3341 } 3365 }
3342 return retval; 3366 return retval;
3343} 3367}
@@ -3345,20 +3369,18 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
3345/* 3369/*
3346 * Split this up, as gcc can choke on it otherwise.. 3370 * Split this up, as gcc can choke on it otherwise..
3347 */ 3371 */
3348int tty_ioctl(struct inode *inode, struct file *file, 3372long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3349 unsigned int cmd, unsigned long arg)
3350{ 3373{
3351 struct tty_struct *tty, *real_tty; 3374 struct tty_struct *tty, *real_tty;
3352 void __user *p = (void __user *)arg; 3375 void __user *p = (void __user *)arg;
3353 int retval; 3376 int retval;
3354 struct tty_ldisc *ld; 3377 struct tty_ldisc *ld;
3378 struct inode *inode = file->f_dentry->d_inode;
3355 3379
3356 tty = (struct tty_struct *)file->private_data; 3380 tty = (struct tty_struct *)file->private_data;
3357 if (tty_paranoia_check(tty, inode, "tty_ioctl")) 3381 if (tty_paranoia_check(tty, inode, "tty_ioctl"))
3358 return -EINVAL; 3382 return -EINVAL;
3359 3383
3360 /* CHECKME: is this safe as one end closes ? */
3361
3362 real_tty = tty; 3384 real_tty = tty;
3363 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 3385 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
3364 tty->driver->subtype == PTY_TYPE_MASTER) 3386 tty->driver->subtype == PTY_TYPE_MASTER)
@@ -3367,13 +3389,19 @@ int tty_ioctl(struct inode *inode, struct file *file,
3367 /* 3389 /*
3368 * Break handling by driver 3390 * Break handling by driver
3369 */ 3391 */
3392
3393 retval = -EINVAL;
3394
3370 if (!tty->driver->break_ctl) { 3395 if (!tty->driver->break_ctl) {
3371 switch (cmd) { 3396 switch (cmd) {
3372 case TIOCSBRK: 3397 case TIOCSBRK:
3373 case TIOCCBRK: 3398 case TIOCCBRK:
3374 if (tty->driver->ioctl) 3399 if (tty->driver->ioctl) {
3375 return tty->driver->ioctl(tty, file, cmd, arg); 3400 lock_kernel();
3376 return -EINVAL; 3401 retval = tty->driver->ioctl(tty, file, cmd, arg);
3402 unlock_kernel();
3403 }
3404 return retval;
3377 3405
3378 /* These two ioctl's always return success; even if */ 3406 /* These two ioctl's always return success; even if */
3379 /* the driver doesn't support them. */ 3407 /* the driver doesn't support them. */
@@ -3381,7 +3409,9 @@ int tty_ioctl(struct inode *inode, struct file *file,
3381 case TCSBRKP: 3409 case TCSBRKP:
3382 if (!tty->driver->ioctl) 3410 if (!tty->driver->ioctl)
3383 return 0; 3411 return 0;
3412 lock_kernel();
3384 retval = tty->driver->ioctl(tty, file, cmd, arg); 3413 retval = tty->driver->ioctl(tty, file, cmd, arg);
3414 unlock_kernel();
3385 if (retval == -ENOIOCTLCMD) 3415 if (retval == -ENOIOCTLCMD)
3386 retval = 0; 3416 retval = 0;
3387 return retval; 3417 return retval;
@@ -3401,7 +3431,9 @@ int tty_ioctl(struct inode *inode, struct file *file,
3401 if (retval) 3431 if (retval)
3402 return retval; 3432 return retval;
3403 if (cmd != TIOCCBRK) { 3433 if (cmd != TIOCCBRK) {
3434 lock_kernel();
3404 tty_wait_until_sent(tty, 0); 3435 tty_wait_until_sent(tty, 0);
3436 unlock_kernel();
3405 if (signal_pending(current)) 3437 if (signal_pending(current))
3406 return -EINTR; 3438 return -EINTR;
3407 } 3439 }
@@ -3451,11 +3483,15 @@ int tty_ioctl(struct inode *inode, struct file *file,
3451 * Break handling 3483 * Break handling
3452 */ 3484 */
3453 case TIOCSBRK: /* Turn break on, unconditionally */ 3485 case TIOCSBRK: /* Turn break on, unconditionally */
3486 lock_kernel();
3454 tty->driver->break_ctl(tty, -1); 3487 tty->driver->break_ctl(tty, -1);
3488 unlock_kernel();
3455 return 0; 3489 return 0;
3456 3490
3457 case TIOCCBRK: /* Turn break off, unconditionally */ 3491 case TIOCCBRK: /* Turn break off, unconditionally */
3492 lock_kernel();
3458 tty->driver->break_ctl(tty, 0); 3493 tty->driver->break_ctl(tty, 0);
3494 unlock_kernel();
3459 return 0; 3495 return 0;
3460 case TCSBRK: /* SVID version: non-zero arg --> no break */ 3496 case TCSBRK: /* SVID version: non-zero arg --> no break */
3461 /* non-zero arg means wait for all output data 3497 /* non-zero arg means wait for all output data
@@ -3485,14 +3521,18 @@ int tty_ioctl(struct inode *inode, struct file *file,
3485 break; 3521 break;
3486 } 3522 }
3487 if (tty->driver->ioctl) { 3523 if (tty->driver->ioctl) {
3524 lock_kernel();
3488 retval = (tty->driver->ioctl)(tty, file, cmd, arg); 3525 retval = (tty->driver->ioctl)(tty, file, cmd, arg);
3526 unlock_kernel();
3489 if (retval != -ENOIOCTLCMD) 3527 if (retval != -ENOIOCTLCMD)
3490 return retval; 3528 return retval;
3491 } 3529 }
3492 ld = tty_ldisc_ref_wait(tty); 3530 ld = tty_ldisc_ref_wait(tty);
3493 retval = -EINVAL; 3531 retval = -EINVAL;
3494 if (ld->ioctl) { 3532 if (ld->ioctl) {
3533 lock_kernel();
3495 retval = ld->ioctl(tty, file, cmd, arg); 3534 retval = ld->ioctl(tty, file, cmd, arg);
3535 unlock_kernel();
3496 if (retval == -ENOIOCTLCMD) 3536 if (retval == -ENOIOCTLCMD)
3497 retval = -EINVAL; 3537 retval = -EINVAL;
3498 } 3538 }
@@ -3770,6 +3810,7 @@ static void initialize_tty_struct(struct tty_struct *tty)
3770 mutex_init(&tty->atomic_read_lock); 3810 mutex_init(&tty->atomic_read_lock);
3771 mutex_init(&tty->atomic_write_lock); 3811 mutex_init(&tty->atomic_write_lock);
3772 spin_lock_init(&tty->read_lock); 3812 spin_lock_init(&tty->read_lock);
3813 spin_lock_init(&tty->ctrl_lock);
3773 INIT_LIST_HEAD(&tty->tty_files); 3814 INIT_LIST_HEAD(&tty->tty_files);
3774 INIT_WORK(&tty->SAK_work, do_SAK_work); 3815 INIT_WORK(&tty->SAK_work, do_SAK_work);
3775} 3816}