提交 be294a51 编写于 作者: T Toshiaki Makita 提交者: David S. Miller

vhost_net: Avoid rx queue wake-ups during busypoll

We may run handle_rx() while rx work is queued. For example a packet can
push the rx work during the window before handle_rx calls
vhost_net_disable_vq().
In that case busypoll immediately exits due to vhost_has_work()
condition and enables vq again. This can lead to another unnecessary rx
wake-ups, so poll rx work instead of enabling the vq.
Signed-off-by: NToshiaki Makita <makita.toshiaki@lab.ntt.co.jp>
Acked-by: NJason Wang <jasowang@redhat.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 027b1760
...@@ -653,7 +653,8 @@ static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq) ...@@ -653,7 +653,8 @@ static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq)
nvq->done_idx = 0; nvq->done_idx = 0;
} }
static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk) static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk,
bool *busyloop_intr)
{ {
struct vhost_net_virtqueue *rnvq = &net->vqs[VHOST_NET_VQ_RX]; struct vhost_net_virtqueue *rnvq = &net->vqs[VHOST_NET_VQ_RX];
struct vhost_net_virtqueue *tnvq = &net->vqs[VHOST_NET_VQ_TX]; struct vhost_net_virtqueue *tnvq = &net->vqs[VHOST_NET_VQ_TX];
...@@ -671,11 +672,16 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk) ...@@ -671,11 +672,16 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk)
preempt_disable(); preempt_disable();
endtime = busy_clock() + tvq->busyloop_timeout; endtime = busy_clock() + tvq->busyloop_timeout;
while (vhost_can_busy_poll(endtime) && while (vhost_can_busy_poll(endtime)) {
!vhost_has_work(&net->dev) && if (vhost_has_work(&net->dev)) {
!sk_has_rx_data(sk) && *busyloop_intr = true;
vhost_vq_avail_empty(&net->dev, tvq)) break;
}
if (sk_has_rx_data(sk) ||
!vhost_vq_avail_empty(&net->dev, tvq))
break;
cpu_relax(); cpu_relax();
}
preempt_enable(); preempt_enable();
...@@ -795,6 +801,7 @@ static void handle_rx(struct vhost_net *net) ...@@ -795,6 +801,7 @@ static void handle_rx(struct vhost_net *net)
s16 headcount; s16 headcount;
size_t vhost_hlen, sock_hlen; size_t vhost_hlen, sock_hlen;
size_t vhost_len, sock_len; size_t vhost_len, sock_len;
bool busyloop_intr = false;
struct socket *sock; struct socket *sock;
struct iov_iter fixup; struct iov_iter fixup;
__virtio16 num_buffers; __virtio16 num_buffers;
...@@ -818,7 +825,9 @@ static void handle_rx(struct vhost_net *net) ...@@ -818,7 +825,9 @@ static void handle_rx(struct vhost_net *net)
vq->log : NULL; vq->log : NULL;
mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF);
while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk,
&busyloop_intr))) {
busyloop_intr = false;
sock_len += sock_hlen; sock_len += sock_hlen;
vhost_len = sock_len + vhost_hlen; vhost_len = sock_len + vhost_hlen;
headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx, headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx,
...@@ -905,7 +914,10 @@ static void handle_rx(struct vhost_net *net) ...@@ -905,7 +914,10 @@ static void handle_rx(struct vhost_net *net)
goto out; goto out;
} }
} }
vhost_net_enable_vq(net, vq); if (unlikely(busyloop_intr))
vhost_poll_queue(&vq->poll);
else
vhost_net_enable_vq(net, vq);
out: out:
vhost_rx_signal_used(nvq); vhost_rx_signal_used(nvq);
mutex_unlock(&vq->mutex); mutex_unlock(&vq->mutex);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册