Refactor __tty_hangup() into: 1. __tty_hangup_common(), the portion requiring the tty lock 2. __tty_hangup(), which performs the pre- and post-lock processing (TIOCCONS redirect undo) and calls through a function ptr parameter to lock/hangup/unlock 3. __tty_hangup_standard(), which performs the lock/hangup/unlock Allows an alternate function to lock/hangup/unlock with the nested tty lock. Signed-off-by: Peter Hurley <peter@xxxxxxxxxxxxxxxxxx> --- drivers/tty/tty_io.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 58015b3..48c1def 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c @@ -665,32 +665,17 @@ static int tty_signal_session_leader(struct tty_struct *tty, int exit_session) * tasklist_lock to walk task list for hangup event * ->siglock to protect ->signal/->sighand */ -static void __tty_hangup(struct tty_struct *tty, int exit_session) +static void __tty_hangup_common(struct tty_struct *tty, int exit_session) { struct file *cons_filp = NULL; - struct file *filp, *f = NULL; + struct file *filp; struct tty_file_private *priv; int closecount = 0, n; int refs; - if (!tty) + if (test_bit(TTY_HUPPED, &tty->flags)) return; - - spin_lock(&redirect_lock); - if (redirect && file_tty(redirect) == tty) { - f = redirect; - redirect = NULL; - } - spin_unlock(&redirect_lock); - - tty_lock(tty); - - if (test_bit(TTY_HUPPED, &tty->flags)) { - tty_unlock(tty); - return; - } - /* 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 */ @@ -746,7 +731,31 @@ static void __tty_hangup(struct tty_struct *tty, int exit_session) * can't yet guarantee all that. */ set_bit(TTY_HUPPED, &tty->flags); +} + +static void __tty_hangup_standard(struct tty_struct* tty, int exit_session) +{ + tty_lock(tty); + __tty_hangup_common(tty, exit_session); tty_unlock(tty); +} + +static void __tty_hangup(struct tty_struct *tty, int exit_session, + void (*hangup)(struct tty_struct *, int)) +{ + struct file *f = NULL; + + if (!tty) + return; + + spin_lock(&redirect_lock); + if (redirect && file_tty(redirect) == tty) { + f = redirect; + redirect = NULL; + } + spin_unlock(&redirect_lock); + + hangup(tty, exit_session); if (f) fput(f); @@ -757,7 +766,7 @@ static void do_tty_hangup(struct work_struct *work) struct tty_struct *tty = container_of(work, struct tty_struct, hangup_work); - __tty_hangup(tty, 0); + __tty_hangup(tty, 0, __tty_hangup_standard); } /** @@ -795,7 +804,7 @@ void tty_vhangup(struct tty_struct *tty) printk(KERN_DEBUG "%s vhangup...\n", tty_name(tty, buf)); #endif - __tty_hangup(tty, 0); + __tty_hangup(tty, 0, __tty_hangup_standard); } EXPORT_SYMBOL(tty_vhangup); @@ -836,7 +845,7 @@ static void tty_vhangup_session(struct tty_struct *tty) printk(KERN_DEBUG "%s vhangup session...\n", tty_name(tty, buf)); #endif - __tty_hangup(tty, 1); + __tty_hangup(tty, 1, __tty_hangup_standard); } /** -- 2.1.1 -- To unsubscribe from this list: send the line "unsubscribe linux-serial" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html