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/tty_io.c | 115 ++++++++++++++++++++++++++++---------------------- 1 file changed, 64 insertions(+), 51 deletions(-) (limited to 'drivers/char/tty_io.c') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 507441ac6edb..5ee9081a560f 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; } -- cgit v1.2.3 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 622e21ca9a5c..de22ea952832 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 5ee9081a560f..bb22cf495435 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 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 de22ea952832..f2d7a76fab54 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 75889cd9375f..ebae344ce910 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 bb22cf495435..dcf7d368639e 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 0f494799da89..412f9775d19c 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 955d72ea71c0..0fbafb0b69bf 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 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 f2d7a76fab54..ad46eae1f9bb 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 dcf7d368639e..4c4030c12d3a 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 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 4c4030c12d3a..0350c42375a2 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