diff options
author | Paul Fulghum <paulkf@microgate.com> | 2006-07-26 14:10:29 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-08-06 20:52:16 -0700 |
commit | e294e7d480581084e0a0a7044f8451023ae1a114 (patch) | |
tree | 4d04580709a4a8643ce5d5d590761e37b72004d9 /drivers | |
parent | 3b6eaf273f4a41cbba86e0cb164e5d69c84c25a3 (diff) |
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 <paulkf@microgate.com>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/tty_io.c | 14 |
1 files changed, 9 insertions, 5 deletions
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); } |