Re: [Bug #14388] keyboard under X with 2.6.31

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, 13 Oct 2009, Linus Torvalds wrote:


Another bug:

On Tue, 13 Oct 2009, Linus Torvalds wrote:
 			if (!count) {
-				if (head->next == NULL)
-					break;

Those two lines should _not_ be deleted. I cleaned up a bit too much.

The rule is that we must not free the last buffer, because it's also going
to be 'tail'.

So here's a new version with that fixed (and the previous bug I already
mentioned).

Whether it _works_ is still not clear. It might eat your pet goldfish, or
make farting noises in your general direction. Or it might fix the bug.
Who knows?

		Linus

---
drivers/char/tty_buffer.c |   29 +++++++++++++----------------
1 files changed, 13 insertions(+), 16 deletions(-)

diff --git a/drivers/char/tty_buffer.c b/drivers/char/tty_buffer.c
index 3108991..0296612 100644
--- a/drivers/char/tty_buffer.c
+++ b/drivers/char/tty_buffer.c
@@ -402,28 +402,26 @@ static void flush_to_ldisc(struct work_struct *work)
		container_of(work, struct tty_struct, buf.work.work);
	unsigned long 	flags;
	struct tty_ldisc *disc;
-	struct tty_buffer *tbuf, *head;
-	char *char_buf;
-	unsigned char *flag_buf;

	disc = tty_ldisc_ref(tty);
	if (disc == NULL)	/*  !TTY_LDISC */
		return;

	spin_lock_irqsave(&tty->buf.lock, flags);
-	/* So we know a flush is running */
-	set_bit(TTY_FLUSHING, &tty->flags);
-	head = tty->buf.head;
-	if (head != NULL) {
-		tty->buf.head = NULL;
-		for (;;) {
-			int count = head->commit - head->read;
+
+	if (!test_and_set_bit(TTY_FLUSHING, &tty->flags)) {
+		struct tty_buffer *head;
+		while ((head = tty->buf.head) != NULL) {
+			int count;
+			char *char_buf;
+			unsigned char *flag_buf;
+
+			count = head->commit - head->read;
			if (!count) {
				if (head->next == NULL)
					break;
-				tbuf = head;
-				head = head->next;
-				tty_buffer_free(tty, tbuf);
+				tty->buf.head = head->next;
+				tty_buffer_free(tty, head);
				continue;
			}
			/* Ldisc or user is trying to flush the buffers
@@ -445,9 +443,9 @@ static void flush_to_ldisc(struct work_struct *work)
							flag_buf, count);
			spin_lock_irqsave(&tty->buf.lock, flags);
		}
-		/* Restore the queue head */
-		tty->buf.head = head;
+		clear_bit(TTY_FLUSHING, &tty->flags);
	}
+
	/* We may have a deferred request to flush the input buffer,
	   if so pull the chain under the lock and empty the queue */
	if (test_bit(TTY_FLUSHPENDING, &tty->flags)) {
@@ -455,7 +453,6 @@ static void flush_to_ldisc(struct work_struct *work)
		clear_bit(TTY_FLUSHPENDING, &tty->flags);
		wake_up(&tty->read_wait);
	}
-	clear_bit(TTY_FLUSHING, &tty->flags);
	spin_unlock_irqrestore(&tty->buf.lock, flags);

	tty_ldisc_deref(disc);

For now (more than 3h), it isn't doing any harm. And no keyboard lockups.

BTW, the old version of the patch was funny. It booted, but at the login prompt I could only enter the first letter.
--
To unsubscribe from this list: send the line "unsubscribe kernel-testers" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux