From: Peter Hurley <peter@hurleysoftware.com>
To: Alan Cox <alan@linux.intel.com>, Jiri Slaby <jslaby@suse.cz>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-serial@vger.kernel.org, linux-kernel@vger.kernel.org,
Peter Hurley <peter@hurleysoftware.com>
Subject: [PATCH -next 6/9] tty: Fix ldisc halt sequence on hangup
Date: Tue, 4 Dec 2012 02:07:42 -0500 [thread overview]
Message-ID: <1354604865-10278-7-git-send-email-peter@hurleysoftware.com> (raw)
In-Reply-To: <1354604865-10278-1-git-send-email-peter@hurleysoftware.com>
Flip buffer work cannot be cancelled until all outstanding ldisc
references have been released. Convert the ldisc ref wait into
a full ldisc halt with buffer work cancellation.
Note that the legacy mutex is not held while cancelling.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
---
drivers/tty/tty_ldisc.c | 40 ++++++++++++++++++++--------------------
1 file changed, 20 insertions(+), 20 deletions(-)
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index 0d18d1e..c3dec37 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -549,22 +549,31 @@ static int tty_ldisc_halt(struct tty_struct *tty)
}
/**
- * tty_ldisc_hangup_wait_idle - wait for the ldisc to become idle
- * @tty: tty to wait for
- *
- * Wait for the line discipline to become idle. The discipline must
- * have been halted for this to guarantee it remains idle.
+ * tty_ldisc_hangup_halt - halt the line discipline for hangup
+ * @tty: tty being hung up
*
+ * Shut down the line discipline and work queue for the tty device
+ * being hungup. Clear the TTY_LDISC flag to ensure no further
+ * references can be obtained, wait for remaining references to be
+ * released, and cancel pending buffer work to ensure no more
+ * data is fed to the ldisc.
* Caller must hold legacy and ->ldisc_mutex.
*
* NB: tty_set_ldisc() is prevented from changing the ldisc concurrently
* with this function when it checks the TTY_HUPPING state.
+ *
+ * NB: if tty->ldisc is NULL then buffer work does not need to be
+ * cancelled because it must already have done as a precondition
+ * of setting tty->ldisc to NULL
+ *
*/
-static bool tty_ldisc_hangup_wait_idle(struct tty_struct *tty)
+static bool tty_ldisc_hangup_halt(struct tty_struct *tty)
{
char cur_n[TASK_COMM_LEN], tty_n[64];
long timeout = 3 * HZ;
+ clear_bit(TTY_LDISC, &tty->flags);
+
if (tty->ldisc) { /* Not yet closed */
tty_unlock(tty);
@@ -575,6 +584,10 @@ static bool tty_ldisc_hangup_wait_idle(struct tty_struct *tty)
__func__, get_task_comm(cur_n, current),
tty_name(tty, tty_n));
}
+
+ cancel_work_sync(&tty->port->buf.work);
+ set_bit(TTY_LDISC_HALTED, &tty->flags);
+
/* must reacquire both locks and preserve lock order */
mutex_unlock(&tty->ldisc_mutex);
tty_lock(tty);
@@ -849,24 +862,11 @@ void tty_ldisc_hangup(struct tty_struct *tty)
*/
mutex_lock(&tty->ldisc_mutex);
- /*
- * this is like tty_ldisc_halt, but we need to give up
- * the BTM before calling cancel_work_sync, which may
- * need to wait for another function taking the BTM
- */
- clear_bit(TTY_LDISC, &tty->flags);
- tty_unlock(tty);
- cancel_work_sync(&tty->port->buf.work);
- set_bit(TTY_LDISC_HALTED, &tty->flags);
- mutex_unlock(&tty->ldisc_mutex);
- tty_lock(tty);
- mutex_lock(&tty->ldisc_mutex);
-
/* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but
it means auditing a lot of other paths so this is
a FIXME */
- if (tty_ldisc_hangup_wait_idle(tty)) {
+ if (tty_ldisc_hangup_halt(tty)) {
if (reset == 0) {
if (!tty_ldisc_reinit(tty, tty->termios.c_line))
--
1.8.0
next prev parent reply other threads:[~2012-12-04 7:07 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-12-04 7:07 [PATCH -next 0/9] tty: Fix buffer work access-after-free Peter Hurley
2012-12-04 7:07 ` [PATCH -next 1/9] tty: WARN if buffer work racing with tty free Peter Hurley
2012-12-04 7:07 ` [PATCH -next 2/9] tty: Add diagnostic for halted line discipline Peter Hurley
2012-12-04 7:07 ` [PATCH -next 3/9] tty: Don't reschedule buffer work while closing Peter Hurley
2012-12-04 7:07 ` [PATCH -next 4/9] tty: Refactor wait for ldisc refs out of tty_ldisc_hangup() Peter Hurley
2012-12-04 7:07 ` [PATCH -next 5/9] tty: Remove unnecessary re-test of ldisc ref count Peter Hurley
2012-12-04 7:07 ` Peter Hurley [this message]
2012-12-04 7:07 ` [PATCH -next 7/9] tty: Strengthen no-subsequent-use guarantee of tty_ldisc_halt() Peter Hurley
2012-12-04 7:07 ` [PATCH -next 8/9] tty: Remove unnecessary buffer work flush Peter Hurley
2012-12-04 7:07 ` [PATCH -next 9/9] tty: Halt both ldiscs concurrently Peter Hurley
2012-12-04 7:40 ` [PATCH -next 0/9] tty: Fix buffer work access-after-free Ilya Zykov
2012-12-04 8:54 ` Alan Cox
2012-12-04 13:58 ` Peter Hurley
2012-12-04 14:30 ` Alan Cox
2012-12-04 9:38 ` Jiri Slaby
2012-12-07 0:57 ` Peter Hurley
2012-12-10 19:00 ` Ilya Zykov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1354604865-10278-7-git-send-email-peter@hurleysoftware.com \
--to=peter@hurleysoftware.com \
--cc=alan@linux.intel.com \
--cc=gregkh@linuxfoundation.org \
--cc=jslaby@suse.cz \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.