diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2014-05-02 10:56:11 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-03 18:14:28 -0400 |
commit | 5fbf1a65dd53ef313783c34a0e93a6e29def6136 (patch) | |
tree | e4631779d08d03cd27d0b4a5546e4a5768a77ead | |
parent | 501fed45b7e8836ee9373f4d31e2d85e3db6103a (diff) |
Revert "tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc"
This reverts commit 6a20dbd6caa2358716136144bf524331d70b1e03.
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: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/tty/tty_buffer.c | 16 | ||||
-rw-r--r-- | include/linux/tty.h | 1 |
2 files changed, 2 insertions, 15 deletions
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index f1d30f6945af..8ebd9f88a6f6 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -255,16 +255,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size, | |||
255 | if (change || left < size) { | 255 | if (change || left < size) { |
256 | /* This is the slow path - looking for new buffers to use */ | 256 | /* This is the slow path - looking for new buffers to use */ |
257 | if ((n = tty_buffer_alloc(port, size)) != NULL) { | 257 | if ((n = tty_buffer_alloc(port, size)) != NULL) { |
258 | unsigned long iflags; | ||
259 | |||
260 | n->flags = flags; | 258 | n->flags = flags; |
261 | buf->tail = n; | 259 | buf->tail = n; |
262 | |||
263 | spin_lock_irqsave(&buf->flush_lock, iflags); | ||
264 | b->commit = b->used; | 260 | b->commit = b->used; |
261 | smp_mb(); | ||
265 | b->next = n; | 262 | b->next = n; |
266 | spin_unlock_irqrestore(&buf->flush_lock, iflags); | ||
267 | |||
268 | } else if (change) | 263 | } else if (change) |
269 | size = 0; | 264 | size = 0; |
270 | else | 265 | else |
@@ -448,7 +443,6 @@ static void flush_to_ldisc(struct work_struct *work) | |||
448 | mutex_lock(&buf->lock); | 443 | mutex_lock(&buf->lock); |
449 | 444 | ||
450 | while (1) { | 445 | while (1) { |
451 | unsigned long flags; | ||
452 | struct tty_buffer *head = buf->head; | 446 | struct tty_buffer *head = buf->head; |
453 | int count; | 447 | int count; |
454 | 448 | ||
@@ -456,19 +450,14 @@ static void flush_to_ldisc(struct work_struct *work) | |||
456 | if (atomic_read(&buf->priority)) | 450 | if (atomic_read(&buf->priority)) |
457 | break; | 451 | break; |
458 | 452 | ||
459 | spin_lock_irqsave(&buf->flush_lock, flags); | ||
460 | count = head->commit - head->read; | 453 | count = head->commit - head->read; |
461 | if (!count) { | 454 | if (!count) { |
462 | if (head->next == NULL) { | 455 | if (head->next == NULL) |
463 | spin_unlock_irqrestore(&buf->flush_lock, flags); | ||
464 | break; | 456 | break; |
465 | } | ||
466 | buf->head = head->next; | 457 | buf->head = head->next; |
467 | spin_unlock_irqrestore(&buf->flush_lock, flags); | ||
468 | tty_buffer_free(port, head); | 458 | tty_buffer_free(port, head); |
469 | continue; | 459 | continue; |
470 | } | 460 | } |
471 | spin_unlock_irqrestore(&buf->flush_lock, flags); | ||
472 | 461 | ||
473 | count = receive_buf(tty, head, count); | 462 | count = receive_buf(tty, head, count); |
474 | if (!count) | 463 | if (!count) |
@@ -523,7 +512,6 @@ void tty_buffer_init(struct tty_port *port) | |||
523 | struct tty_bufhead *buf = &port->buf; | 512 | struct tty_bufhead *buf = &port->buf; |
524 | 513 | ||
525 | mutex_init(&buf->lock); | 514 | mutex_init(&buf->lock); |
526 | spin_lock_init(&buf->flush_lock); | ||
527 | tty_buffer_reset(&buf->sentinel, 0); | 515 | tty_buffer_reset(&buf->sentinel, 0); |
528 | buf->head = &buf->sentinel; | 516 | buf->head = &buf->sentinel; |
529 | buf->tail = &buf->sentinel; | 517 | buf->tail = &buf->sentinel; |
diff --git a/include/linux/tty.h b/include/linux/tty.h index 036cccd80d9f..1c3316a47d7e 100644 --- a/include/linux/tty.h +++ b/include/linux/tty.h | |||
@@ -61,7 +61,6 @@ struct tty_bufhead { | |||
61 | struct tty_buffer *head; /* Queue head */ | 61 | struct tty_buffer *head; /* Queue head */ |
62 | struct work_struct work; | 62 | struct work_struct work; |
63 | struct mutex lock; | 63 | struct mutex lock; |
64 | spinlock_t flush_lock; | ||
65 | atomic_t priority; | 64 | atomic_t priority; |
66 | struct tty_buffer sentinel; | 65 | struct tty_buffer sentinel; |
67 | struct llist_head free; /* Free queue head */ | 66 | struct llist_head free; /* Free queue head */ |