Messages in this thread Patch in this message | | | Date | Fri, 02 Dec 2011 09:21:12 +0100 | From | Jiri Slaby <> | Subject | Re: [PATCH 2/5] TTY: ldisc, move wait idle to caller |
| |
On 12/02/2011 12:01 AM, Tony Luck wrote: > One of my systems (HP rx2620 - ia64) has started hanging during shutdown. > Last messages on the serial console are: > > Shutting down service (localfs) network . . . . . . . . . done > Shutting down D-Bus daemon done > Running /etc/ini > > and there it hangs forever in mid word (totally repeatable stops at "ini" every > time). > > git bisect blames: > > commit 300420722e0734a4254f3b634e0f82664495d210 > Author: Jiri Slaby <jslaby@suse.cz> > Date: Wed Nov 16 16:27:08 2011 +0100 > > TTY: ldisc, move wait idle to caller > > [Though the following commit "TTY: ldisc, wait for ldisc infinitely in hangup" > sounds like it fits the symptoms] > > Ideas?
Thanks. What distro and init do you use? Does the attached patch help?
-- js suse labs From 6f778e80388f8b1ad65f0c8bfbc874704d77b3eb Mon Sep 17 00:00:00 2001 From: Jiri Slaby <jslaby@suse.cz> Date: Fri, 2 Dec 2011 09:19:05 +0100 Subject: [PATCH 1/1] TTY: ldisc, don't wait with ldisc_mutex
Signed-off-by: Jiri Slaby <jslaby@suse.cz> --- drivers/tty/tty_ldisc.c | 16 +++++++++++++--- 1 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 24b95db..c93e113 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -527,6 +527,14 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) flush_work_sync(&tty->buf.work); } +static bool tty_ldisc_is_idle(struct tty_struct *tty) +{ + bool idle; + mutex_lock(&tty->ldisc_mutex); + idle = !tty->ldisc || atomic_read(&tty->ldisc->users) == 1; + mutex_unlock(&tty->ldisc_mutex); + return idle; +} /** * tty_ldisc_wait_idle - wait for the ldisc to become idle * @tty: tty to wait for @@ -534,12 +542,14 @@ static void tty_ldisc_flush_works(struct tty_struct *tty) * * Wait for the line discipline to become idle. The discipline must * have been halted for this to guarantee it remains idle. + * + * Locking: neither BTM, nor tty->ldisc_mutex must be held */ static int tty_ldisc_wait_idle(struct tty_struct *tty, long timeout) { long ret; - ret = wait_event_timeout(tty_ldisc_idle, - atomic_read(&tty->ldisc->users) == 1, timeout); + ret = wait_event_timeout(tty_ldisc_idle, tty_ldisc_is_idle(tty), + timeout); return ret > 0 ? 0 : -EBUSY; } @@ -830,6 +840,7 @@ retry: if (atomic_read(&tty->ldisc->users) != 1) { char cur_n[TASK_COMM_LEN], tty_n[64]; long timeout = 3 * HZ; + mutex_unlock(&tty->ldisc_mutex); tty_unlock(); while (tty_ldisc_wait_idle(tty, timeout) == -EBUSY) { @@ -839,7 +850,6 @@ retry: __func__, get_task_comm(cur_n, current), tty_name(tty, tty_n)); } - mutex_unlock(&tty->ldisc_mutex); goto retry; } -- 1.7.7.3
| |