Commit 5fbf1a65 authored by Peter Hurley's avatar Peter Hurley Committed by Greg Kroah-Hartman

Revert "tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc"

This reverts commit 6a20dbd6.

Although the commit correctly identifies an unsafe race condition
between __tty_buffer_request_room() and flush_to_ldisc(), the commit
fixes the race with an unnecessary spinlock in a lockless algorithm.

The follow-on commit, "tty: Fix lockless tty buffer race" fixes
the race locklessly.
Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 501fed45
...@@ -255,16 +255,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, ...@@ -255,16 +255,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
if (change || left < size) { if (change || left < size) {
/* This is the slow path - looking for new buffers to use */ /* This is the slow path - looking for new buffers to use */
if ((n = tty_buffer_alloc(port, size)) != NULL) { if ((n = tty_buffer_alloc(port, size)) != NULL) {
unsigned long iflags;
n->flags = flags; n->flags = flags;
buf->tail = n; buf->tail = n;
spin_lock_irqsave(&buf->flush_lock, iflags);
b->commit = b->used; b->commit = b->used;
smp_mb();
b->next = n; b->next = n;
spin_unlock_irqrestore(&buf->flush_lock, iflags);
} else if (change) } else if (change)
size = 0; size = 0;
else else
...@@ -448,7 +443,6 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -448,7 +443,6 @@ static void flush_to_ldisc(struct work_struct *work)
mutex_lock(&buf->lock); mutex_lock(&buf->lock);
while (1) { while (1) {
unsigned long flags;
struct tty_buffer *head = buf->head; struct tty_buffer *head = buf->head;
int count; int count;
...@@ -456,19 +450,14 @@ static void flush_to_ldisc(struct work_struct *work) ...@@ -456,19 +450,14 @@ static void flush_to_ldisc(struct work_struct *work)
if (atomic_read(&buf->priority)) if (atomic_read(&buf->priority))
break; break;
spin_lock_irqsave(&buf->flush_lock, flags);
count = head->commit - head->read; count = head->commit - head->read;
if (!count) { if (!count) {
if (head->next == NULL) { if (head->next == NULL)
spin_unlock_irqrestore(&buf->flush_lock, flags);
break; break;
}
buf->head = head->next; buf->head = head->next;
spin_unlock_irqrestore(&buf->flush_lock, flags);
tty_buffer_free(port, head); tty_buffer_free(port, head);
continue; continue;
} }
spin_unlock_irqrestore(&buf->flush_lock, flags);
count = receive_buf(tty, head, count); count = receive_buf(tty, head, count);
if (!count) if (!count)
...@@ -523,7 +512,6 @@ void tty_buffer_init(struct tty_port *port) ...@@ -523,7 +512,6 @@ void tty_buffer_init(struct tty_port *port)
struct tty_bufhead *buf = &port->buf; struct tty_bufhead *buf = &port->buf;
mutex_init(&buf->lock); mutex_init(&buf->lock);
spin_lock_init(&buf->flush_lock);
tty_buffer_reset(&buf->sentinel, 0); tty_buffer_reset(&buf->sentinel, 0);
buf->head = &buf->sentinel; buf->head = &buf->sentinel;
buf->tail = &buf->sentinel; buf->tail = &buf->sentinel;
......
...@@ -61,7 +61,6 @@ struct tty_bufhead { ...@@ -61,7 +61,6 @@ struct tty_bufhead {
struct tty_buffer *head; /* Queue head */ struct tty_buffer *head; /* Queue head */
struct work_struct work; struct work_struct work;
struct mutex lock; struct mutex lock;
spinlock_t flush_lock;
atomic_t priority; atomic_t priority;
struct tty_buffer sentinel; struct tty_buffer sentinel;
struct llist_head free; /* Free queue head */ struct llist_head free; /* Free queue head */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment