Michael S. Tsirkin
2021-Jan-19 09:55 UTC
[PATCH net-next v7] vhost_net: avoid tx queue stuck when sendmsg fails
On Fri, Jan 15, 2021 at 12:46:20PM +0800, wangyunjian wrote:> From: Yunjian Wang <wangyunjian at huawei.com> > > Currently the driver doesn't drop a packet which can't be sent by tun > (e.g bad packet). In this case, the driver will always process the > same packet lead to the tx queue stuck. > > To fix this issue: > 1. in the case of persistent failure (e.g bad packet), the driver > can skip this descriptor by ignoring the error. > 2. in the case of transient failure (e.g -ENOBUFS, -EAGAIN and -ENOMEM), > the driver schedules the worker to try again. > > Signed-off-by: Yunjian Wang <wangyunjian at huawei.com>Acked-by: Michael S. Tsirkin <mst at redhat.com>> --- > v7: > * code rebase > v6: > * update code styles and commit log > --- > drivers/vhost/net.c | 26 ++++++++++++++------------ > 1 file changed, 14 insertions(+), 12 deletions(-) > > diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c > index 3b744031ec8f..df82b124170e 100644 > --- a/drivers/vhost/net.c > +++ b/drivers/vhost/net.c > @@ -828,14 +828,15 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock) > msg.msg_flags &= ~MSG_MORE; > } > > - /* TODO: Check specific error and bomb out unless ENOBUFS? */ > err = sock->ops->sendmsg(sock, &msg, len); > if (unlikely(err < 0)) { > - vhost_discard_vq_desc(vq, 1); > - vhost_net_enable_vq(net, vq); > - break; > - } > - if (err != len) > + if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) { > + vhost_discard_vq_desc(vq, 1); > + vhost_net_enable_vq(net, vq); > + break; > + } > + pr_debug("Fail to send packet: err %d", err); > + } else if (unlikely(err != len)) > pr_debug("Truncated TX packet: len %d != %zd\n", > err, len); > done: > @@ -924,7 +925,6 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) > msg.msg_flags &= ~MSG_MORE; > } > > - /* TODO: Check specific error and bomb out unless ENOBUFS? */ > err = sock->ops->sendmsg(sock, &msg, len); > if (unlikely(err < 0)) { > if (zcopy_used) { > @@ -933,11 +933,13 @@ static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) > nvq->upend_idx = ((unsigned)nvq->upend_idx - 1) > % UIO_MAXIOV; > } > - vhost_discard_vq_desc(vq, 1); > - vhost_net_enable_vq(net, vq); > - break; > - } > - if (err != len) > + if (err == -EAGAIN || err == -ENOMEM || err == -ENOBUFS) { > + vhost_discard_vq_desc(vq, 1); > + vhost_net_enable_vq(net, vq); > + break; > + } > + pr_debug("Fail to send packet: err %d", err); > + } else if (unlikely(err != len)) > pr_debug("Truncated TX packet: " > " len %d != %zd\n", err, len); > if (!zcopy_used) > -- > 2.23.0