Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+2 −14
Original line number Diff line number Diff line
@@ -255,16 +255,11 @@ static int __tty_buffer_request_room(struct tty_port *port, size_t size,
	if (change || left < size) {
		/* This is the slow path - looking for new buffers to use */
		if ((n = tty_buffer_alloc(port, size)) != NULL) {
			unsigned long iflags;

			n->flags = flags;
			buf->tail = n;

			spin_lock_irqsave(&buf->flush_lock, iflags);
			b->commit = b->used;
			smp_mb();
			b->next = n;
			spin_unlock_irqrestore(&buf->flush_lock, iflags);

		} else if (change)
			size = 0;
		else
@@ -448,7 +443,6 @@ static void flush_to_ldisc(struct work_struct *work)
	mutex_lock(&buf->lock);

	while (1) {
		unsigned long flags;
		struct tty_buffer *head = buf->head;
		int count;

@@ -456,19 +450,14 @@ static void flush_to_ldisc(struct work_struct *work)
		if (atomic_read(&buf->priority))
			break;

		spin_lock_irqsave(&buf->flush_lock, flags);
		count = head->commit - head->read;
		if (!count) {
			if (head->next == NULL) {
				spin_unlock_irqrestore(&buf->flush_lock, flags);
			if (head->next == NULL)
				break;
			}
			buf->head = head->next;
			spin_unlock_irqrestore(&buf->flush_lock, flags);
			tty_buffer_free(port, head);
			continue;
		}
		spin_unlock_irqrestore(&buf->flush_lock, flags);

		count = receive_buf(tty, head, count);
		if (!count)
@@ -523,7 +512,6 @@ void tty_buffer_init(struct tty_port *port)
	struct tty_bufhead *buf = &port->buf;

	mutex_init(&buf->lock);
	spin_lock_init(&buf->flush_lock);
	tty_buffer_reset(&buf->sentinel, 0);
	buf->head = &buf->sentinel;
	buf->tail = &buf->sentinel;
+0 −1
Original line number Diff line number Diff line
@@ -61,7 +61,6 @@ struct tty_bufhead {
	struct tty_buffer *head;	/* Queue head */
	struct work_struct work;
	struct mutex	   lock;
	spinlock_t	   flush_lock;
	atomic_t	   priority;
	struct tty_buffer sentinel;
	struct llist_head free;		/* Free queue head */