Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Jiri Slaby <jirislaby@kernel.org>
To: juanfengpy@gmail.com, gregkh@linuxfoundation.org
Cc: ilpo.jarvinen@linux.intel.com, benbjiang@tencent.com,
	robinlai@tencent.com, linux-serial@vger.kernel.org,
	Hui Li <caelli@tencent.com>,
	stable@vger.kernel.org
Subject: Re: [PATCH v7] tty: fix hang on tty device with no_room set
Date: Fri, 17 Mar 2023 07:32:54 +0100	[thread overview]
Message-ID: <35358148-3d46-40e5-aa1e-84e7fb6dbb6f@kernel.org> (raw)
In-Reply-To: <1679020915-8349-1-git-send-email-caelli@tencent.com>

On 17. 03. 23, 3:41, juanfengpy@gmail.com wrote:
> From: Hui Li <caelli@tencent.com>
> 
> We have met a hang on pty device, the reader was blocking
> at epoll on master side, the writer was sleeping at wait_woken
> inside n_tty_write on slave side, and the write buffer on
> tty_port was full, we found that the reader and writer would
> never be woken again and blocked forever.
> 
> The problem was caused by a race between reader and kworker:
> n_tty_read(reader):  n_tty_receive_buf_common(kworker):
> copy_from_read_buf()|
>                      |room = N_TTY_BUF_SIZE - (ldata->read_head - tail)
>                      |room <= 0
> n_tty_kick_worker() |
>                      |ldata->no_room = true
> 
> After writing to slave device, writer wakes up kworker to flush
> data on tty_port to reader, and the kworker finds that reader
> has no room to store data so room <= 0 is met. At this moment,
> reader consumes all the data on reader buffer and calls
> n_tty_kick_worker to check ldata->no_room which is false and
> reader quits reading. Then kworker sets ldata->no_room=true
> and quits too.
...
> --- a/drivers/tty/n_tty.c
> +++ b/drivers/tty/n_tty.c
...
> @@ -1729,6 +1729,27 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
>   	} else
>   		n_tty_check_throttle(tty);
>   
> +	if (unlikely(ldata->no_room)) {
> +		/*
> +		 * Barrier here is to ensure to read the latest read_tail in
> +		 * chars_in_buffer() and to make sure that read_tail is not loaded
> +		 * before ldata->no_room is set,


I am not sure I would keep the following part of the comment in the code:

 > otherwise, following race may occur:
> +		 * n_tty_receive_buf_common()
> +		 *				n_tty_read()
> +		 *   if (!chars_in_buffer(tty))->false
> +		 *				  copy_from_read_buf()
> +		 *				    read_tail=commit_head
> +		 *				  n_tty_kick_worker()
> +		 *				    if (ldata->no_room)->false
> +		 *   ldata->no_room = 1
> +		 * Then both kworker and reader will fail to kick n_tty_kick_worker(),
> +		 * smp_mb is paired with smp_mb() in n_tty_read().

I would only let it ^^^ documented in the commit log as you did.

> +		 */
> +		smp_mb();
> +		if (!chars_in_buffer(tty))
> +			n_tty_kick_worker(tty);
> +	}
> +
>   	up_read(&tty->termios_rwsem);
>   
>   	return rcvd;
> @@ -2282,8 +2303,25 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file,
>   		if (time)
>   			timeout = time;
>   	}
> -	if (old_tail != ldata->read_tail)
> +	if (old_tail != ldata->read_tail) {
> +		/*
> +		 * Make sure no_room is not read in n_tty_kick_worker()
> +		 * before setting ldata->read_tail in copy_from_read_buf(),

The same here (it's only repeated). I think the above two lines are 
enough for the comment. We have git blame after all.

> +		 * otherwise, following race may occur:
> +		 * n_tty_read()
> +		 *			n_tty_receive_buf_common()
> +		 *   n_tty_kick_worker()
> +		 *     if(ldata->no_room)->false
> +		 *			  ldata->no_room = 1
> +		 *			  if (!chars_in_buffer(tty))->false
> +		 *   copy_from_read_buf()
> +		 *     read_tail=commit_head
> +		 * Both reader and kworker will fail to kick tty_buffer_restart_work(),
> +		 * smp_mb is paired with smp_mb() in n_tty_receive_buf_common().
> +		 */
> +		smp_mb();
>   		n_tty_kick_worker(tty);
> +	}
>   	up_read(&tty->termios_rwsem);
>   
>   	remove_wait_queue(&tty->read_wait, &wait);

-- 
js


  reply	other threads:[~2023-03-17  6:33 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <YrmdEJrM3z6Dbvgn@kroah.com>
2023-03-17  2:37 ` [PATCH v7] tty: fix hang on tty device with no_room set juanfengpy
2023-03-17  2:41 ` juanfengpy
2023-03-17  6:32   ` Jiri Slaby [this message]
2023-03-17  7:25     ` [PATCH v8] " juanfengpy
2023-04-06  2:44       ` [PATCH v9] " juanfengpy
2023-06-15 10:21         ` patch "tty: fix hang on tty device with no_room set" added to tty-testing gregkh
2023-06-16  6:14         ` patch "tty: fix hang on tty device with no_room set" added to tty-next gregkh
2023-03-17  2:24 [PATCH v7] tty: fix hang on tty device with no_room set juanfengpy
2023-04-04  2:49 ` Bagas Sanjaya
2023-04-04  2:55   ` Bagas Sanjaya
2023-04-04  7:02     ` caelli

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=35358148-3d46-40e5-aa1e-84e7fb6dbb6f@kernel.org \
    --to=jirislaby@kernel.org \
    --cc=benbjiang@tencent.com \
    --cc=caelli@tencent.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=ilpo.jarvinen@linux.intel.com \
    --cc=juanfengpy@gmail.com \
    --cc=linux-serial@vger.kernel.org \
    --cc=robinlai@tencent.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox