From e294e7d480581084e0a0a7044f8451023ae1a114 Mon Sep 17 00:00:00 2001 From: Paul Fulghum Date: Wed, 26 Jul 2006 14:10:29 -0500 Subject: tty serialize flush_to_ldisc Serialize processing of tty buffers in flush_to_ldisc to fix (very rare) corruption of tty buffer free list on SMP systems. Signed-off-by: Paul Fulghum Acked-by: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/char/tty_io.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a88b94a82b1..832163c3e95 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2776,7 +2776,7 @@ static void flush_to_ldisc(void *private_) struct tty_struct *tty = (struct tty_struct *) private_; unsigned long flags; struct tty_ldisc *disc; - struct tty_buffer *tbuf; + struct tty_buffer *tbuf, *head; int count; char *char_buf; unsigned char *flag_buf; @@ -2793,7 +2793,9 @@ static void flush_to_ldisc(void *private_) goto out; } spin_lock_irqsave(&tty->buf.lock, flags); - while((tbuf = tty->buf.head) != NULL) { + head = tty->buf.head; + tty->buf.head = NULL; + while((tbuf = head) != NULL) { while ((count = tbuf->commit - tbuf->read) != 0) { char_buf = tbuf->char_buf_ptr + tbuf->read; flag_buf = tbuf->flag_buf_ptr + tbuf->read; @@ -2802,10 +2804,12 @@ static void flush_to_ldisc(void *private_) disc->receive_buf(tty, char_buf, flag_buf, count); spin_lock_irqsave(&tty->buf.lock, flags); } - if (tbuf->active) + if (tbuf->active) { + tty->buf.head = head; break; - tty->buf.head = tbuf->next; - if (tty->buf.head == NULL) + } + head = tbuf->next; + if (head == NULL) tty->buf.tail = NULL; tty_buffer_free(tty, tbuf); } -- cgit v1.2.3-18-g5258