From 31d1d48e199e99077fb30f6fb9a793be7bec756f Mon Sep 17 00:00:00 2001 From: David Howells Date: Fri, 6 Aug 2010 16:34:43 +0100 Subject: Fix init ordering of /dev/console vs callers of modprobe Make /dev/console get initialised before any initialisation routine that invokes modprobe because if modprobe fails, it's going to want to open /dev/console, presumably to write an error message to. The problem with that is that if the /dev/console driver is not yet initialised, the chardev handler will call request_module() to invoke modprobe, which will fail, because we never compile /dev/console as a module. This will lead to a modprobe loop, showing the following in the kernel log: request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 request_module: runaway loop modprobe char-major-5-1 This can happen, for example, when the built in md5 module can't find the built in cryptomgr module (because the latter fails to initialise). The md5 module comes before the call to tty_init(), presumably because 'crypto' comes before 'drivers' alphabetically. Fix this by calling tty_init() from chrdev_init(). Signed-off-by: David Howells Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index d71f0fc34b4..507441ac6ed 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -3128,7 +3128,7 @@ static struct cdev tty_cdev, console_cdev; * Ok, now we can initialize the rest of the tty devices and can count * on memory allocations, interrupts etc.. */ -static int __init tty_init(void) +int __init tty_init(void) { cdev_init(&tty_cdev, &tty_fops); if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) || @@ -3149,4 +3149,4 @@ static int __init tty_init(void) #endif return 0; } -module_init(tty_init); + -- cgit v1.2.3-70-g09d2 From ec79d6056de58511d8e46d9ae59d3878f958dc3e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:01 +0200 Subject: tty: replace BKL with a new tty_lock As a preparation for replacing the big kernel lock in the TTY layer, wrap all the callers in new macros tty_lock, tty_lock_nested and tty_unlock. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/amiserial.c | 16 +++--- drivers/char/briq_panel.c | 6 +-- drivers/char/n_hdlc.c | 16 +++--- drivers/char/n_r3964.c | 8 +-- drivers/char/pty.c | 4 +- drivers/char/selection.c | 4 +- drivers/char/serial167.c | 4 +- drivers/char/sx.c | 12 ++--- drivers/char/tty_io.c | 115 +++++++++++++++++++++++------------------ drivers/char/tty_ldisc.c | 24 +++++---- drivers/char/vc_screen.c | 4 +- drivers/char/vt_ioctl.c | 10 ++-- drivers/serial/68360serial.c | 4 +- drivers/serial/crisv10.c | 4 +- drivers/serial/serial_core.c | 10 ++-- drivers/video/console/vgacon.c | 4 +- include/linux/tty.h | 31 +++++++++++ 17 files changed, 161 insertions(+), 115 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c index 4f8d60c25a9..1b21a7adeb5 100644 --- a/drivers/char/amiserial.c +++ b/drivers/char/amiserial.c @@ -1072,7 +1072,7 @@ static int get_serial_info(struct async_struct * info, if (!retinfo) return -EFAULT; memset(&tmp, 0, sizeof(tmp)); - lock_kernel(); + tty_lock(); tmp.type = state->type; tmp.line = state->line; tmp.port = state->port; @@ -1083,7 +1083,7 @@ static int get_serial_info(struct async_struct * info, tmp.close_delay = state->close_delay; tmp.closing_wait = state->closing_wait; tmp.custom_divisor = state->custom_divisor; - unlock_kernel(); + tty_unlock(); if (copy_to_user(retinfo,&tmp,sizeof(*retinfo))) return -EFAULT; return 0; @@ -1100,14 +1100,14 @@ static int set_serial_info(struct async_struct * info, if (copy_from_user(&new_serial,new_info,sizeof(new_serial))) return -EFAULT; - lock_kernel(); + tty_lock(); state = info->state; old_state = *state; change_irq = new_serial.irq != state->irq; change_port = (new_serial.port != state->port); if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) { - unlock_kernel(); + tty_unlock(); return -EINVAL; } @@ -1127,7 +1127,7 @@ static int set_serial_info(struct async_struct * info, } if (new_serial.baud_base < 9600) { - unlock_kernel(); + tty_unlock(); return -EINVAL; } @@ -1163,7 +1163,7 @@ check_and_exit: } } else retval = startup(info); - unlock_kernel(); + tty_unlock(); return retval; } @@ -1538,7 +1538,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) orig_jiffies = jiffies; - lock_kernel(); + tty_lock_nested(); /* tty_wait_until_sent is called from lots of places */ /* * Set the check interval to be 1/5 of the estimated time to * send a single character, and make it at least 1. The check @@ -1579,7 +1579,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) break; } __set_current_state(TASK_RUNNING); - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/char/briq_panel.c b/drivers/char/briq_panel.c index 555cd93c2ee..d5fa113afe3 100644 --- a/drivers/char/briq_panel.c +++ b/drivers/char/briq_panel.c @@ -67,15 +67,15 @@ static void set_led(char state) static int briq_panel_open(struct inode *ino, struct file *filep) { - lock_kernel(); + tty_lock(); /* enforce single access, vfd_is_open is protected by BKL */ if (vfd_is_open) { - unlock_kernel(); + tty_unlock(); return -EBUSY; } vfd_is_open = 1; - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index c68118efad8..47d32281032 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c @@ -598,18 +598,18 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, return -EFAULT; } - lock_kernel(); + tty_lock(); for (;;) { if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) { - unlock_kernel(); + tty_unlock(); return -EIO; } n_hdlc = tty2n_hdlc (tty); if (!n_hdlc || n_hdlc->magic != HDLC_MAGIC || tty != n_hdlc->tty) { - unlock_kernel(); + tty_unlock(); return 0; } @@ -619,13 +619,13 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, /* no data */ if (file->f_flags & O_NONBLOCK) { - unlock_kernel(); + tty_unlock(); return -EAGAIN; } interruptible_sleep_on (&tty->read_wait); if (signal_pending(current)) { - unlock_kernel(); + tty_unlock(); return -EINTR; } } @@ -648,7 +648,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file, kfree(rbuf); else n_hdlc_buf_put(&n_hdlc->rx_free_buf_list,rbuf); - unlock_kernel(); + tty_unlock(); return ret; } /* end of n_hdlc_tty_read() */ @@ -691,7 +691,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, count = maxframe; } - lock_kernel(); + tty_lock(); add_wait_queue(&tty->write_wait, &wait); set_current_state(TASK_INTERRUPTIBLE); @@ -731,7 +731,7 @@ static ssize_t n_hdlc_tty_write(struct tty_struct *tty, struct file *file, n_hdlc_buf_put(&n_hdlc->tx_buf_list,tbuf); n_hdlc_send_frames(n_hdlc,tty); } - unlock_kernel(); + tty_unlock(); return error; } /* end of n_hdlc_tty_write() */ diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c index c1d8b54c816..f4bd2591e39 100644 --- a/drivers/char/n_r3964.c +++ b/drivers/char/n_r3964.c @@ -1067,7 +1067,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, TRACE_L("read()"); - lock_kernel(); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1109,7 +1109,7 @@ static ssize_t r3964_read(struct tty_struct *tty, struct file *file, } ret = -EPERM; unlock: - unlock_kernel(); + tty_unlock(); return ret; } @@ -1158,7 +1158,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, pHeader->locks = 0; pHeader->owner = NULL; - lock_kernel(); + tty_lock(); pClient = findClient(pInfo, task_pid(current)); if (pClient) { @@ -1177,7 +1177,7 @@ static ssize_t r3964_write(struct tty_struct *tty, struct file *file, add_tx_queue(pInfo, pHeader); trigger_transmit(pInfo); - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/pty.c b/drivers/char/pty.c index b640ef29be1..622e21ca9a5 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -692,9 +692,9 @@ static int ptmx_open(struct inode *inode, struct file *filp) { int ret; - lock_kernel(); + tty_lock(); ret = __ptmx_open(inode, filp); - unlock_kernel(); + tty_unlock(); return ret; } diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 6e79340d732..85211a3a581 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -313,7 +313,7 @@ int paste_selection(struct tty_struct *tty) struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); - lock_kernel(); + tty_lock_nested(); /* always called with BTM from vt_ioctl */ acquire_console_sem(); poke_blanked_console(); @@ -338,6 +338,6 @@ int paste_selection(struct tty_struct *tty) __set_current_state(TASK_RUNNING); tty_ldisc_deref(ld); - unlock_kernel(); + tty_unlock(); return 0; } diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index ecbe479c7d6..90b3ec0aabd 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c @@ -1505,7 +1505,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */ #endif - lock_kernel(); + tty_lock(); switch (cmd) { case CYGETMON: @@ -1561,7 +1561,7 @@ cy_ioctl(struct tty_struct *tty, struct file *file, default: ret_val = -ENOIOCTLCMD; } - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_OTHER printk("cy_ioctl done\n"); diff --git a/drivers/char/sx.c b/drivers/char/sx.c index a81ec4fcf6f..5b24db4ff7f 100644 --- a/drivers/char/sx.c +++ b/drivers/char/sx.c @@ -1699,7 +1699,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, if (!capable(CAP_SYS_RAWIO)) return -EPERM; - lock_kernel(); + tty_lock(); sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg); @@ -1848,7 +1848,7 @@ static long sx_fw_ioctl(struct file *filp, unsigned int cmd, break; } out: - unlock_kernel(); + tty_unlock(); func_exit(); return rc; } @@ -1859,7 +1859,7 @@ static int sx_break(struct tty_struct *tty, int flag) int rv; func_enter(); - lock_kernel(); + tty_lock(); if (flag) rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK); @@ -1868,7 +1868,7 @@ static int sx_break(struct tty_struct *tty, int flag) if (rv != 1) printk(KERN_ERR "sx: couldn't send break (%x).\n", read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); - unlock_kernel(); + tty_unlock(); func_exit(); return 0; } @@ -1909,7 +1909,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, /* func_enter2(); */ rc = 0; - lock_kernel(); + tty_lock(); switch (cmd) { case TIOCGSERIAL: rc = gs_getserial(&port->gs, argp); @@ -1921,7 +1921,7 @@ static int sx_ioctl(struct tty_struct *tty, struct file *filp, rc = -ENOIOCTLCMD; break; } - unlock_kernel(); + tty_unlock(); /* func_exit(); */ return rc; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 507441ac6ed..5ee9081a560 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -149,6 +149,7 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd, #else #define tty_compat_ioctl NULL #endif +static int __tty_fasync(int fd, struct file *filp, int on); static int tty_fasync(int fd, struct file *filp, int on); static void release_tty(struct tty_struct *tty, int idx); static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty); @@ -483,7 +484,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); * remains intact. * * Locking: - * BKL + * BTM * redirect lock for undoing redirection * file list lock for manipulating list of ttys * tty_ldisc_lock from called functions @@ -513,8 +514,11 @@ static void do_tty_hangup(struct work_struct *work) } spin_unlock(&redirect_lock); - /* inuse_filps is protected by the single kernel lock */ - lock_kernel(); + /* inuse_filps is protected by the single tty lock, + this really needs to change if we want to flush the + workqueue with the lock held */ + tty_lock_nested(); /* called with BTM held from pty_close and + others */ check_tty_count(tty, "do_tty_hangup"); file_list_lock(); @@ -525,7 +529,7 @@ static void do_tty_hangup(struct work_struct *work) if (filp->f_op->write != tty_write) continue; closecount++; - tty_fasync(-1, filp, 0); /* can't block */ + __tty_fasync(-1, filp, 0); /* can't block */ filp->f_op = &hung_up_tty_fops; } file_list_unlock(); @@ -594,7 +598,7 @@ static void do_tty_hangup(struct work_struct *work) */ set_bit(TTY_HUPPED, &tty->flags); tty_ldisc_enable(tty); - unlock_kernel(); + tty_unlock(); if (f) fput(f); } @@ -696,7 +700,8 @@ static void session_clear_tty(struct pid *session) * exiting; it is 0 if called by the ioctl TIOCNOTTY. * * Locking: - * BKL is taken for hysterical raisins + * BTM is taken for hysterical raisins, and held when + * called from no_tty(). * tty_mutex is taken to protect tty * ->siglock is taken to protect ->signal/->sighand * tasklist_lock is taken to walk process list for sessions @@ -714,10 +719,10 @@ void disassociate_ctty(int on_exit) tty = get_current_tty(); if (tty) { tty_pgrp = get_pid(tty->pgrp); - lock_kernel(); + tty_lock_nested(); /* see above */ if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) tty_vhangup(tty); - unlock_kernel(); + tty_unlock(); tty_kref_put(tty); } else if (on_exit) { struct pid *old_pgrp; @@ -774,9 +779,9 @@ void disassociate_ctty(int on_exit) void no_tty(void) { struct task_struct *tsk = current; - lock_kernel(); + tty_lock(); disassociate_ctty(0); - unlock_kernel(); + tty_unlock(); proc_clear_tty(tsk); } @@ -1013,19 +1018,19 @@ out: * We don't put it into the syslog queue right now maybe in the future if * really needed. * - * We must still hold the BKL and test the CLOSING flag for the moment. + * We must still hold the BTM and test the CLOSING flag for the moment. */ void tty_write_message(struct tty_struct *tty, char *msg) { if (tty) { mutex_lock(&tty->atomic_write_lock); - lock_kernel(); + tty_lock(); if (tty->ops->write && !test_bit(TTY_CLOSING, &tty->flags)) { - unlock_kernel(); + tty_unlock(); tty->ops->write(tty, msg, strlen(msg)); } else - unlock_kernel(); + tty_unlock(); tty_write_unlock(tty); } return; @@ -1208,18 +1213,18 @@ static int tty_driver_install_tty(struct tty_driver *driver, int ret; if (driver->ops->install) { - lock_kernel(); + tty_lock_nested(); /* already called with BTM held */ ret = driver->ops->install(driver, tty); - unlock_kernel(); + tty_unlock(); return ret; } if (tty_init_termios(tty) == 0) { - lock_kernel(); + tty_lock_nested(); tty_driver_kref_get(driver); tty->count++; driver->ttys[idx] = tty; - unlock_kernel(); + tty_unlock(); return 0; } return -ENOMEM; @@ -1312,14 +1317,15 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct tty_struct *tty; int retval; - lock_kernel(); + tty_lock_nested(); /* always called with tty lock held already */ + /* Check if pty master is being opened multiple times */ if (driver->subtype == PTY_TYPE_MASTER && (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { - unlock_kernel(); + tty_unlock(); return ERR_PTR(-EIO); } - unlock_kernel(); + tty_unlock(); /* * First time open is complex, especially for PTY devices. @@ -1363,9 +1369,9 @@ release_mem_out: if (printk_ratelimit()) printk(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); - lock_kernel(); + tty_lock_nested(); release_tty(tty, idx); - unlock_kernel(); + tty_unlock(); return ERR_PTR(retval); } @@ -1512,10 +1518,10 @@ int tty_release(struct inode *inode, struct file *filp) if (tty_paranoia_check(tty, inode, "tty_release_dev")) return 0; - lock_kernel(); + tty_lock(); check_tty_count(tty, "tty_release_dev"); - tty_fasync(-1, filp, 0); + __tty_fasync(-1, filp, 0); idx = tty->index; pty_master = (tty->driver->type == TTY_DRIVER_TYPE_PTY && @@ -1527,18 +1533,18 @@ int tty_release(struct inode *inode, struct file *filp) if (idx < 0 || idx >= tty->driver->num) { printk(KERN_DEBUG "tty_release_dev: bad idx when trying to " "free (%s)\n", tty->name); - unlock_kernel(); + tty_unlock(); return 0; } if (!devpts) { if (tty != tty->driver->ttys[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: driver.table[%d] not tty " "for (%s)\n", idx, tty->name); return 0; } if (tty->termios != tty->driver->termios[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: driver.termios[%d] not termios " "for (%s)\n", idx, tty->name); @@ -1556,21 +1562,21 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->driver->other && !(tty->driver->flags & TTY_DRIVER_DEVPTS_MEM)) { if (o_tty != tty->driver->other->ttys[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: other->table[%d] " "not o_tty for (%s)\n", idx, tty->name); return 0 ; } if (o_tty->termios != tty->driver->other->termios[idx]) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: other->termios[%d] " "not o_termios for (%s)\n", idx, tty->name); return 0; } if (o_tty->link != tty) { - unlock_kernel(); + tty_unlock(); printk(KERN_DEBUG "tty_release_dev: bad pty pointers\n"); return 0; } @@ -1579,7 +1585,7 @@ int tty_release(struct inode *inode, struct file *filp) if (tty->ops->close) tty->ops->close(tty, filp); - unlock_kernel(); + tty_unlock(); /* * Sanity check: if tty->count is going to zero, there shouldn't be * any waiters on tty->read_wait or tty->write_wait. We test the @@ -1602,7 +1608,7 @@ int tty_release(struct inode *inode, struct file *filp) opens on /dev/tty */ mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); tty_closing = tty->count <= 1; o_tty_closing = o_tty && (o_tty->count <= (pty_master ? 1 : 0)); @@ -1633,7 +1639,7 @@ int tty_release(struct inode *inode, struct file *filp) printk(KERN_WARNING "tty_release_dev: %s: read/write wait queue " "active!\n", tty_name(tty, buf)); - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); schedule(); } @@ -1698,7 +1704,7 @@ int tty_release(struct inode *inode, struct file *filp) /* check whether both sides are closing ... */ if (!tty_closing || (o_tty && !o_tty_closing)) { - unlock_kernel(); + tty_unlock(); return 0; } @@ -1718,7 +1724,7 @@ int tty_release(struct inode *inode, struct file *filp) /* Make this pty number available for reallocation */ if (devpts) devpts_kill_index(inode, idx); - unlock_kernel(); + tty_unlock(); return 0; } @@ -1760,12 +1766,12 @@ retry_open: retval = 0; mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); if (device == MKDEV(TTYAUX_MAJOR, 0)) { tty = get_current_tty(); if (!tty) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENXIO; } @@ -1797,14 +1803,14 @@ retry_open: goto got_driver; } } - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENODEV; } driver = get_tty_driver(device, &index); if (!driver) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return -ENODEV; } @@ -1814,7 +1820,7 @@ got_driver: tty = tty_driver_lookup_tty(driver, inode, index); if (IS_ERR(tty)) { - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return PTR_ERR(tty); } @@ -1830,7 +1836,7 @@ got_driver: mutex_unlock(&tty_mutex); tty_driver_kref_put(driver); if (IS_ERR(tty)) { - unlock_kernel(); + tty_unlock(); return PTR_ERR(tty); } @@ -1862,11 +1868,11 @@ got_driver: #endif tty_release(inode, filp); if (retval != -ERESTARTSYS) { - unlock_kernel(); + tty_unlock(); return retval; } if (signal_pending(current)) { - unlock_kernel(); + tty_unlock(); return retval; } schedule(); @@ -1875,14 +1881,14 @@ got_driver: */ if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; - unlock_kernel(); + tty_unlock(); goto retry_open; } - unlock_kernel(); + tty_unlock(); mutex_lock(&tty_mutex); - lock_kernel(); + tty_lock(); spin_lock_irq(¤t->sighand->siglock); if (!noctty && current->signal->leader && @@ -1890,7 +1896,7 @@ got_driver: tty->session == NULL) __proc_set_tty(current, tty); spin_unlock_irq(¤t->sighand->siglock); - unlock_kernel(); + tty_unlock(); mutex_unlock(&tty_mutex); return 0; } @@ -1926,13 +1932,12 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) return ret; } -static int tty_fasync(int fd, struct file *filp, int on) +static int __tty_fasync(int fd, struct file *filp, int on) { struct tty_struct *tty; unsigned long flags; int retval = 0; - lock_kernel(); tty = (struct tty_struct *)filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) goto out; @@ -1966,7 +1971,15 @@ static int tty_fasync(int fd, struct file *filp, int on) } retval = 0; out: - unlock_kernel(); + return retval; +} + +static int tty_fasync(int fd, struct file *filp, int on) +{ + int retval; + tty_lock(); + retval = __tty_fasync(fd, filp, on); + tty_unlock(); return retval; } diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 500e740ec5e..97681ffd6cb 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -440,6 +440,8 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) * * A helper opening method. Also a convenient debugging and check * point. + * + * Locking: always called with BTM already held. */ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) @@ -447,10 +449,10 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); if (ld->ops->open) { int ret; - /* BKL here locks verus a hangup event */ - lock_kernel(); + /* BTM here locks versus a hangup event */ + tty_lock_nested(); /* always held here already */ ret = ld->ops->open(tty); - unlock_kernel(); + tty_unlock(); return ret; } return 0; @@ -553,7 +555,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); - lock_kernel(); + tty_lock(); /* * We need to look at the tty locking here for pty/tty pairs * when both sides try to change in parallel. @@ -567,12 +569,12 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) */ if (tty->ldisc->ops->num == ldisc) { - unlock_kernel(); + tty_unlock(); tty_ldisc_put(new_ldisc); return 0; } - unlock_kernel(); + tty_unlock(); /* * Problem: What do we do if this blocks ? * We could deadlock here @@ -594,7 +596,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) mutex_lock(&tty->ldisc_mutex); } - lock_kernel(); + tty_lock(); set_bit(TTY_LDISC_CHANGING, &tty->flags); @@ -607,7 +609,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) o_ldisc = tty->ldisc; - unlock_kernel(); + tty_unlock(); /* * Make sure we don't change while someone holds a * reference to the line discipline. The TTY_LDISC bit @@ -633,14 +635,14 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) flush_scheduled_work(); mutex_lock(&tty->ldisc_mutex); - lock_kernel(); + tty_lock(); if (test_bit(TTY_HUPPED, &tty->flags)) { /* We were raced by the hangup method. It will have stomped the ldisc data and closed the ldisc down */ clear_bit(TTY_LDISC_CHANGING, &tty->flags); mutex_unlock(&tty->ldisc_mutex); tty_ldisc_put(new_ldisc); - unlock_kernel(); + tty_unlock(); return -EIO; } @@ -682,7 +684,7 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (o_work) schedule_delayed_work(&o_tty->buf.work, 1); mutex_unlock(&tty->ldisc_mutex); - unlock_kernel(); + tty_unlock(); return retval; } diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index c1791a63d99..bcce46c96b8 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -463,10 +463,10 @@ vcs_open(struct inode *inode, struct file *filp) unsigned int currcons = iminor(inode) & 127; int ret = 0; - lock_kernel(); + tty_lock(); if(currcons && !vc_cons_allocated(currcons-1)) ret = -ENXIO; - unlock_kernel(); + tty_unlock(); return ret; } diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c index 72dcfb2dc12..cf87c533622 100644 --- a/drivers/char/vt_ioctl.c +++ b/drivers/char/vt_ioctl.c @@ -509,7 +509,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; - lock_kernel(); + tty_lock(); if (!vc_cons_allocated(console)) { /* impossible? */ ret = -ENOIOCTLCMD; @@ -1336,7 +1336,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file, ret = -ENOIOCTLCMD; } out: - unlock_kernel(); + tty_unlock(); return ret; eperm: ret = -EPERM; @@ -1503,7 +1503,7 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, console = vc->vc_num; - lock_kernel(); + tty_lock(); if (!vc_cons_allocated(console)) { /* impossible? */ ret = -ENOIOCTLCMD; @@ -1571,11 +1571,11 @@ long vt_compat_ioctl(struct tty_struct *tty, struct file * file, goto fallback; } out: - unlock_kernel(); + tty_unlock(); return ret; fallback: - unlock_kernel(); + tty_unlock(); return vt_ioctl(tty, file, cmd, arg); } diff --git a/drivers/serial/68360serial.c b/drivers/serial/68360serial.c index 768612f8e41..16f5f2fab03 100644 --- a/drivers/serial/68360serial.c +++ b/drivers/serial/68360serial.c @@ -1705,7 +1705,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) printk("jiff=%lu...", jiffies); #endif - lock_kernel(); + tty_lock_nested(); /* always held already since we come from ->close */ /* We go through the loop at least once because we can't tell * exactly when the last character exits the shifter. There can * be at least two characters waiting to be sent after the buffers @@ -1734,7 +1734,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout) bdp--; } while (bdp->status & BD_SC_READY); current->state = TASK_RUNNING; - unlock_kernel(); + tty_unlock(); #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies); #endif diff --git a/drivers/serial/crisv10.c b/drivers/serial/crisv10.c index 30626440a06..f848e188dea 100644 --- a/drivers/serial/crisv10.c +++ b/drivers/serial/crisv10.c @@ -3935,7 +3935,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k) */ - lock_kernel(); + tty_lock_nested(); /* locked already when coming from close */ orig_jiffies = jiffies; while (info->xmit.head != info->xmit.tail || /* More in send queue */ (*info->ostatusadr & 0x007f) || /* more in FIFO */ @@ -3952,7 +3952,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) curr_time_usec - info->last_tx_active_usec; } set_current_state(TASK_RUNNING); - unlock_kernel(); + tty_unlock(); } /* diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 3d2acc2265f..851d7c29132 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1274,7 +1274,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp) struct uart_port *uport; unsigned long flags; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); if (!state) return; @@ -1382,7 +1382,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) if (port->type == PORT_UNKNOWN || port->fifosize == 0) return; - lock_kernel(); + tty_lock_nested(); /* already locked when coming from close */ /* * Set the check interval to be 1/5 of the estimated time to @@ -1429,7 +1429,7 @@ static void uart_wait_until_sent(struct tty_struct *tty, int timeout) break; } set_current_state(TASK_RUNNING); /* might not be needed */ - unlock_kernel(); + tty_unlock(); } /* @@ -1444,7 +1444,7 @@ static void uart_hangup(struct tty_struct *tty) struct tty_port *port = &state->port; unsigned long flags; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); pr_debug("uart_hangup(%d)\n", state->uart_port->line); mutex_lock(&port->mutex); @@ -1578,7 +1578,7 @@ static int uart_open(struct tty_struct *tty, struct file *filp) struct tty_port *port; int retval, line = tty->index; - BUG_ON(!kernel_locked()); + BUG_ON(!tty_locked()); pr_debug("uart_open(%d) called\n", line); /* diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 182dd6f8aad..71970057c11 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c @@ -1108,7 +1108,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) charmap += 4 * cmapsz; #endif - unlock_kernel(); + tty_unlock(); spin_lock_irq(&vga_lock); /* First, the Sequencer */ vga_wseq(state->vgabase, VGA_SEQ_RESET, 0x1); @@ -1192,7 +1192,7 @@ static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512) vga_wattr(state->vgabase, VGA_AR_ENABLE_DISPLAY, 0); } spin_unlock_irq(&vga_lock); - lock_kernel(); + tty_lock(); return 0; } diff --git a/include/linux/tty.h b/include/linux/tty.h index 2df60e4ff40..6ead6b60c74 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -576,5 +577,35 @@ extern int vt_ioctl(struct tty_struct *tty, struct file *file, extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); +/* functions for preparation of BKL removal */ + +/* + * tty_lock_nested get the tty_lock while potentially holding it + * + * The Big TTY Mutex is a recursive lock, meaning you can take it + * from a thread that is already holding it. + * This is bad for a number of reasons, so tty_lock_nested should + * really be used as rarely as possible. If a code location can + * be shown to never get called with this held already, it should + * use tty_lock() instead. + */ +static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock) +{ + lock_kernel(); +} +static inline void tty_lock(void) __acquires(kernel_lock) +{ +#ifdef CONFIG_LOCK_KERNEL + /* kernel_locked is 1 for !CONFIG_LOCK_KERNEL */ + WARN_ON(kernel_locked()); +#endif + lock_kernel(); +} +static inline void tty_unlock(void) __releases(kernel_lock) +{ + unlock_kernel(); +} +#define tty_locked() (kernel_locked()) + #endif /* __KERNEL__ */ #endif -- cgit v1.2.3-70-g09d2 From 64ba3dc3143d94bbe935722aa17fa516b232bc83 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:02 +0200 Subject: tty: never hold BTM while getting tty_mutex tty_mutex is never taken with the BTM held, except for two corner cases that are worked around here. We give up the BTM before calling tty_release() in the error path of tty_open(). Similarly, we reorder the locking in ptmx_open() to get tty_mutex before the BTM. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/pty.c | 24 +++++++++++------------- drivers/char/tty_io.c | 12 ++++++------ 2 files changed, 17 insertions(+), 19 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 622e21ca9a5..de22ea95283 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -647,7 +647,7 @@ static const struct tty_operations pty_unix98_ops = { * allocated_ptys_lock handles the list of free pty numbers */ -static int __ptmx_open(struct inode *inode, struct file *filp) +static int ptmx_open(struct inode *inode, struct file *filp) { struct tty_struct *tty; int retval; @@ -656,11 +656,14 @@ static int __ptmx_open(struct inode *inode, struct file *filp) nonseekable_open(inode, filp); /* find a device that is not in use. */ + tty_lock(); index = devpts_new_index(inode); + tty_unlock(); if (index < 0) return index; mutex_lock(&tty_mutex); + tty_lock(); tty = tty_init_dev(ptm_driver, index, 1); mutex_unlock(&tty_mutex); @@ -678,24 +681,19 @@ static int __ptmx_open(struct inode *inode, struct file *filp) goto out1; retval = ptm_driver->ops->open(tty, filp); - if (!retval) - return 0; + if (retval) + goto out2; out1: + tty_unlock(); + return retval; +out2: + tty_unlock(); tty_release(inode, filp); return retval; out: devpts_kill_index(inode, index); - return retval; -} - -static int ptmx_open(struct inode *inode, struct file *filp) -{ - int ret; - - tty_lock(); - ret = __ptmx_open(inode, filp); tty_unlock(); - return ret; + return retval; } static struct file_operations ptmx_fops; diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 5ee9081a560..bb22cf49543 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1866,19 +1866,19 @@ got_driver: printk(KERN_DEBUG "error %d in opening %s...", retval, tty->name); #endif + tty_unlock(); /* need to call tty_release without BTM */ tty_release(inode, filp); - if (retval != -ERESTARTSYS) { - tty_unlock(); + if (retval != -ERESTARTSYS) return retval; - } - if (signal_pending(current)) { - tty_unlock(); + + if (signal_pending(current)) return retval; - } + schedule(); /* * Need to reset f_op in case a hangup happened. */ + tty_lock(); if (filp->f_op == &hung_up_tty_fops) filp->f_op = &tty_fops; tty_unlock(); -- cgit v1.2.3-70-g09d2 From ddcd9fb66ae7f448b517242c10a31d4e17bcad45 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 1 Jun 2010 22:53:08 +0200 Subject: tty: remove tty_lock_nested This changes all remaining users of tty_lock_nested to be non-recursive, which lets us kill this function. As a consequence, we won't need to keep the lock count any more, which allows more simplifications later. Signed-off-by: Arnd Bergmann Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/pty.c | 2 +- drivers/char/selection.c | 4 ++-- drivers/char/tty_io.c | 41 ++++++++++++++++++++--------------------- drivers/char/tty_ldisc.c | 3 +-- include/linux/tty.h | 16 +--------------- 5 files changed, 25 insertions(+), 41 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/pty.c b/drivers/char/pty.c index de22ea95283..f2d7a76fab5 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -62,7 +62,7 @@ static void pty_close(struct tty_struct *tty, struct file *filp) if (tty->driver == ptm_driver) devpts_pty_kill(tty->link); #endif - tty_vhangup(tty->link); + tty_vhangup_locked(tty->link); } } diff --git a/drivers/char/selection.c b/drivers/char/selection.c index 75889cd9375..ebae344ce91 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c @@ -313,7 +313,8 @@ int paste_selection(struct tty_struct *tty) struct tty_ldisc *ld; DECLARE_WAITQUEUE(wait, current); - tty_lock_nested(); /* always called with BTM from vt_ioctl */ + /* always called with BTM from vt_ioctl */ + WARN_ON(!tty_locked()); acquire_console_sem(); poke_blanked_console(); @@ -343,6 +344,5 @@ int paste_selection(struct tty_struct *tty) __set_current_state(TASK_RUNNING); tty_ldisc_deref(ld); - tty_unlock(); return 0; } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index bb22cf49543..dcf7d368639 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -492,10 +492,8 @@ EXPORT_SYMBOL_GPL(tty_wakeup); * tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand */ -static void do_tty_hangup(struct work_struct *work) +void tty_vhangup_locked(struct tty_struct *tty) { - struct tty_struct *tty = - container_of(work, struct tty_struct, hangup_work); struct file *cons_filp = NULL; struct file *filp, *f = NULL; struct task_struct *p; @@ -517,8 +515,6 @@ static void do_tty_hangup(struct work_struct *work) /* inuse_filps is protected by the single tty lock, this really needs to change if we want to flush the workqueue with the lock held */ - tty_lock_nested(); /* called with BTM held from pty_close and - others */ check_tty_count(tty, "do_tty_hangup"); file_list_lock(); @@ -598,11 +594,20 @@ static void do_tty_hangup(struct work_struct *work) */ set_bit(TTY_HUPPED, &tty->flags); tty_ldisc_enable(tty); - tty_unlock(); if (f) fput(f); } +static void do_tty_hangup(struct work_struct *work) +{ + struct tty_struct *tty = + container_of(work, struct tty_struct, hangup_work); + + tty_lock(); + tty_vhangup_locked(tty); + tty_unlock(); +} + /** * tty_hangup - trigger a hangup event * @tty: tty to hangup @@ -638,7 +643,9 @@ void tty_vhangup(struct tty_struct *tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - do_tty_hangup(&tty->hangup_work); + tty_lock(); + tty_vhangup_locked(tty); + tty_unlock(); } EXPORT_SYMBOL(tty_vhangup); @@ -719,10 +726,12 @@ void disassociate_ctty(int on_exit) tty = get_current_tty(); if (tty) { tty_pgrp = get_pid(tty->pgrp); - tty_lock_nested(); /* see above */ - if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) - tty_vhangup(tty); - tty_unlock(); + if (on_exit) { + tty_lock(); + if (tty->driver->type != TTY_DRIVER_TYPE_PTY) + tty_vhangup_locked(tty); + tty_unlock(); + } tty_kref_put(tty); } else if (on_exit) { struct pid *old_pgrp; @@ -1213,18 +1222,14 @@ static int tty_driver_install_tty(struct tty_driver *driver, int ret; if (driver->ops->install) { - tty_lock_nested(); /* already called with BTM held */ ret = driver->ops->install(driver, tty); - tty_unlock(); return ret; } if (tty_init_termios(tty) == 0) { - tty_lock_nested(); tty_driver_kref_get(driver); tty->count++; driver->ttys[idx] = tty; - tty_unlock(); return 0; } return -ENOMEM; @@ -1317,15 +1322,11 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx, struct tty_struct *tty; int retval; - tty_lock_nested(); /* always called with tty lock held already */ - /* Check if pty master is being opened multiple times */ if (driver->subtype == PTY_TYPE_MASTER && (driver->flags & TTY_DRIVER_DEVPTS_MEM) && !first_ok) { - tty_unlock(); return ERR_PTR(-EIO); } - tty_unlock(); /* * First time open is complex, especially for PTY devices. @@ -1369,9 +1370,7 @@ release_mem_out: if (printk_ratelimit()) printk(KERN_INFO "tty_init_dev: ldisc open failed, " "clearing slot %d\n", idx); - tty_lock_nested(); release_tty(tty, idx); - tty_unlock(); return ERR_PTR(retval); } diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index 0f494799da8..412f9775d19 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c @@ -450,9 +450,8 @@ static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) if (ld->ops->open) { int ret; /* BTM here locks versus a hangup event */ - tty_lock_nested(); /* always held here already */ + WARN_ON(!tty_locked()); ret = ld->ops->open(tty); - tty_unlock(); return ret; } return 0; diff --git a/include/linux/tty.h b/include/linux/tty.h index 955d72ea71c..0fbafb0b69b 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h @@ -417,6 +417,7 @@ extern int is_ignored(int sig); extern int tty_signal(int sig, struct tty_struct *tty); extern void tty_hangup(struct tty_struct *tty); extern void tty_vhangup(struct tty_struct *tty); +extern void tty_vhangup_locked(struct tty_struct *tty); extern void tty_vhangup_self(void); extern void tty_unhangup(struct file *filp); extern int tty_hung_up_p(struct file *filp); @@ -578,21 +579,6 @@ extern long vt_compat_ioctl(struct tty_struct *tty, struct file * file, unsigned int cmd, unsigned long arg); /* functions for preparation of BKL removal */ - -/* - * tty_lock_nested get the tty_lock while potentially holding it - * - * The Big TTY Mutex is a recursive lock, meaning you can take it - * from a thread that is already holding it. - * This is bad for a number of reasons, so tty_lock_nested should - * really be used as rarely as possible. If a code location can - * be shown to never get called with this held already, it should - * use tty_lock() instead. - */ -static inline void __lockfunc tty_lock_nested(void) __acquires(kernel_lock) -{ - lock_kernel(); -} static inline void tty_lock(void) __acquires(kernel_lock) { #ifdef CONFIG_LOCK_KERNEL -- cgit v1.2.3-70-g09d2 From 11dbf203922dc70a340417c895c95fb96f6b7068 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 18 Jun 2010 14:58:07 +0200 Subject: tty: avoid recursive BTM in pty_close When the console has been redirected, a hangup of the tty will cause tty_release to be called under the big tty_mutex, which leads to a deadlock because hangup is also called under the BTM. This moves the BTM deeper into the tty_hangup function so we can close the redirected tty without holding the BTM. In case of pty, we now need to drop the BTM before calling tty_vhangup. Signed-off-by: Arnd Bergmann Acked-by: Alan Cox Cc: Tony Luck Cc: Thomas Gleixner Cc: Andrew Morton Cc: John Kacur Cc: Al Viro Cc: Ingo Molnar Signed-off-by: Greg Kroah-Hartman --- drivers/char/pty.c | 4 +++- drivers/char/tty_io.c | 24 ++++++++++++------------ 2 files changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/pty.c b/drivers/char/pty.c index f2d7a76fab5..ad46eae1f9b 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c @@ -62,7 +62,9 @@ static void pty_close(struct tty_struct *tty, struct file *filp) if (tty->driver == ptm_driver) devpts_pty_kill(tty->link); #endif - tty_vhangup_locked(tty->link); + tty_unlock(); + tty_vhangup(tty->link); + tty_lock(); } } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index dcf7d368639..4c4030c12d3 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -471,7 +471,7 @@ void tty_wakeup(struct tty_struct *tty) EXPORT_SYMBOL_GPL(tty_wakeup); /** - * do_tty_hangup - actual handler for hangup events + * __tty_hangup - actual handler for hangup events * @work: tty device * * This can be called by the "eventd" kernel thread. That is process @@ -492,7 +492,7 @@ EXPORT_SYMBOL_GPL(tty_wakeup); * tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand */ -void tty_vhangup_locked(struct tty_struct *tty) +void __tty_hangup(struct tty_struct *tty) { struct file *cons_filp = NULL; struct file *filp, *f = NULL; @@ -512,10 +512,12 @@ void tty_vhangup_locked(struct tty_struct *tty) } spin_unlock(&redirect_lock); + tty_lock(); + /* inuse_filps is protected by the single tty lock, this really needs to change if we want to flush the workqueue with the lock held */ - check_tty_count(tty, "do_tty_hangup"); + check_tty_count(tty, "tty_hangup"); file_list_lock(); /* This breaks for file handles being sent over AF_UNIX sockets ? */ @@ -594,6 +596,9 @@ void tty_vhangup_locked(struct tty_struct *tty) */ set_bit(TTY_HUPPED, &tty->flags); tty_ldisc_enable(tty); + + tty_unlock(); + if (f) fput(f); } @@ -603,9 +608,7 @@ static void do_tty_hangup(struct work_struct *work) struct tty_struct *tty = container_of(work, struct tty_struct, hangup_work); - tty_lock(); - tty_vhangup_locked(tty); - tty_unlock(); + __tty_hangup(tty); } /** @@ -643,13 +646,12 @@ void tty_vhangup(struct tty_struct *tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - tty_lock(); - tty_vhangup_locked(tty); - tty_unlock(); + __tty_hangup(tty); } EXPORT_SYMBOL(tty_vhangup); + /** * tty_vhangup_self - process vhangup for own ctty * @@ -727,10 +729,8 @@ void disassociate_ctty(int on_exit) if (tty) { tty_pgrp = get_pid(tty->pgrp); if (on_exit) { - tty_lock(); if (tty->driver->type != TTY_DRIVER_TYPE_PTY) - tty_vhangup_locked(tty); - tty_unlock(); + tty_vhangup(tty); } tty_kref_put(tty); } else if (on_exit) { -- cgit v1.2.3-70-g09d2 From 2b50d24760a7c0b62180e6fb5a44c2ce3db66abd Mon Sep 17 00:00:00 2001 From: Kulikov Vasiliy Date: Tue, 29 Jun 2010 14:15:09 +0400 Subject: tty_io: remove casts from void* Remove unnesessary casts from void*. Signed-off-by: Kulikov Vasiliy Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 4c4030c12d3..0350c42375a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -893,7 +893,7 @@ static ssize_t tty_read(struct file *file, char __user *buf, size_t count, struct inode *inode; struct tty_ldisc *ld; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data; inode = file->f_path.dentry->d_inode; if (tty_paranoia_check(tty, inode, "tty_read")) return -EIO; @@ -1070,7 +1070,7 @@ static ssize_t tty_write(struct file *file, const char __user *buf, ssize_t ret; struct tty_ldisc *ld; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data; if (tty_paranoia_check(tty, inode, "tty_write")) return -EIO; if (!tty || !tty->ops->write || @@ -1513,7 +1513,7 @@ int tty_release(struct inode *inode, struct file *filp) int idx; char buf[64]; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data; if (tty_paranoia_check(tty, inode, "tty_release_dev")) return 0; @@ -1920,7 +1920,7 @@ static unsigned int tty_poll(struct file *filp, poll_table *wait) struct tty_ldisc *ld; int ret = 0; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_poll")) return 0; @@ -1937,7 +1937,7 @@ static int __tty_fasync(int fd, struct file *filp, int on) unsigned long flags; int retval = 0; - tty = (struct tty_struct *)filp->private_data; + tty = filp->private_data; if (tty_paranoia_check(tty, filp->f_path.dentry->d_inode, "tty_fasync")) goto out; @@ -2497,7 +2497,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct tty_ldisc *ld; struct inode *inode = file->f_dentry->d_inode; - tty = (struct tty_struct *)file->private_data; + tty = file->private_data; if (tty_paranoia_check(tty, inode, "tty_ioctl")) return -EINVAL; -- cgit v1.2.3-70-g09d2