ACK: [SRU][Bionic][PATCH] tuntap: correctly set SOCKWQ_ASYNC_NOSPACE

Kleber Souza kleber.souza at canonical.com
Mon Sep 2 16:26:19 UTC 2019


On 8/26/19 7:14 PM, Kamal Mostafa wrote:
> From: Jason Wang <jasowang at redhat.com>
> 
> BugLink: https://bugs.launchpad.net/bugs/1830756
> 
> When link is down, writes to the device might fail with
> -EIO. Userspace needs an indication when the status is resolved.  As a
> fix, tun_net_open() attempts to wake up writers - but that is only
> effective if SOCKWQ_ASYNC_NOSPACE has been set in the past. This is
> not the case of vhost_net which only poll for EPOLLOUT after it meets
> errors during sendmsg().
> 
> This patch fixes this by making sure SOCKWQ_ASYNC_NOSPACE is set when
> socket is not writable or device is down to guarantee EPOLLOUT will be
> raised in either tun_chr_poll() or tun_sock_write_space() after device
> is up.
> 
> Cc: Hannes Frederic Sowa <hannes at stressinduktion.org>
> Cc: Eric Dumazet <edumazet at google.com>
> Fixes: 1bd4978a88ac2 ("tun: honor IFF_UP in tun_get_user()")
> Signed-off-by: Jason Wang <jasowang at redhat.com>
> Signed-off-by: David S. Miller <davem at davemloft.net>
> (backported from commit 2f3ab6221e4c87960347d65c7cab9bd917d1f637)
> Signed-off-by: Kamal Mostafa <kamal at canonical.com>

Acked-by: Kleber Sacilotto de Souza <kleber.souza at canonical.com>

> ---
>  drivers/net/tun.c | 19 +++++++++++++++----
>  1 file changed, 15 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
> index 01c706f8fb74..5d1d5bf3a378 100644
> --- a/drivers/net/tun.c
> +++ b/drivers/net/tun.c
> @@ -1252,6 +1252,13 @@ static void tun_net_init(struct net_device *dev)
>  	dev->max_mtu = MAX_MTU - dev->hard_header_len;
>  }
>  
> +static bool tun_sock_writeable(struct tun_struct *tun, struct tun_file *tfile)
> +{
> +	struct sock *sk = tfile->socket.sk;
> +
> +	return (tun->dev->flags & IFF_UP) && sock_writeable(sk);
> +}
> +
>  /* Character device part */
>  
>  /* Poll */
> @@ -1274,10 +1281,14 @@ static unsigned int tun_chr_poll(struct file *file, poll_table *wait)
>  	if (!skb_array_empty(&tfile->tx_array))
>  		mask |= POLLIN | POLLRDNORM;
>  
> -	if (tun->dev->flags & IFF_UP &&
> -	    (sock_writeable(sk) ||
> -	     (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
> -	      sock_writeable(sk))))
> +	/* Make sure SOCKWQ_ASYNC_NOSPACE is set if not writable to
> +	 * guarantee EPOLLOUT to be raised by either here or
> +	 * tun_sock_write_space(). Then process could get notification
> +	 * after it writes to a down device and meets -EIO.
> +	 */
> +	if (tun_sock_writeable(tun, tfile) ||
> +	    (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &sk->sk_socket->flags) &&
> +	     tun_sock_writeable(tun, tfile)))
>  		mask |= POLLOUT | POLLWRNORM;
>  
>  	if (tun->dev->reg_state != NETREG_REGISTERED)
> 




More information about the kernel-team mailing list