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