Skip to content

Commit f5a4941

Browse files
jasowangdavem330
authored andcommitted
vhost_net: flush batched heads before trying to busy polling
After commit e2b3b35 ("vhost_net: batch used ring update in rx"), we tend to batch updating used heads. But it doesn't flush batched heads before trying to do busy polling, this will cause vhost to wait for guest TX which waits for the used RX. Fixing by flush batched heads before busy loop. 1 byte TCP_RR performance recovers from 13107.83 to 50402.65. Fixes: e2b3b35 ("vhost_net: batch used ring update in rx") Signed-off-by: Jason Wang <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 6547e38 commit f5a4941

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

drivers/vhost/net.c

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,9 @@ struct vhost_net_virtqueue {
105105
/* vhost zerocopy support fields below: */
106106
/* last used idx for outstanding DMA zerocopy buffers */
107107
int upend_idx;
108-
/* first used idx for DMA done zerocopy buffers */
108+
/* For TX, first used idx for DMA done zerocopy buffers
109+
* For RX, number of batched heads
110+
*/
109111
int done_idx;
110112
/* an array of userspace buffers info */
111113
struct ubuf_info *ubuf_info;
@@ -626,6 +628,18 @@ static int sk_has_rx_data(struct sock *sk)
626628
return skb_queue_empty(&sk->sk_receive_queue);
627629
}
628630

631+
static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq)
632+
{
633+
struct vhost_virtqueue *vq = &nvq->vq;
634+
struct vhost_dev *dev = vq->dev;
635+
636+
if (!nvq->done_idx)
637+
return;
638+
639+
vhost_add_used_and_signal_n(dev, vq, vq->heads, nvq->done_idx);
640+
nvq->done_idx = 0;
641+
}
642+
629643
static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk)
630644
{
631645
struct vhost_net_virtqueue *rvq = &net->vqs[VHOST_NET_VQ_RX];
@@ -635,6 +649,8 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk)
635649
int len = peek_head_len(rvq, sk);
636650

637651
if (!len && vq->busyloop_timeout) {
652+
/* Flush batched heads first */
653+
vhost_rx_signal_used(rvq);
638654
/* Both tx vq and rx socket were polled here */
639655
mutex_lock_nested(&vq->mutex, 1);
640656
vhost_disable_notify(&net->dev, vq);
@@ -762,7 +778,7 @@ static void handle_rx(struct vhost_net *net)
762778
};
763779
size_t total_len = 0;
764780
int err, mergeable;
765-
s16 headcount, nheads = 0;
781+
s16 headcount;
766782
size_t vhost_hlen, sock_hlen;
767783
size_t vhost_len, sock_len;
768784
struct socket *sock;
@@ -790,8 +806,8 @@ static void handle_rx(struct vhost_net *net)
790806
while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) {
791807
sock_len += sock_hlen;
792808
vhost_len = sock_len + vhost_hlen;
793-
headcount = get_rx_bufs(vq, vq->heads + nheads, vhost_len,
794-
&in, vq_log, &log,
809+
headcount = get_rx_bufs(vq, vq->heads + nvq->done_idx,
810+
vhost_len, &in, vq_log, &log,
795811
likely(mergeable) ? UIO_MAXIOV : 1);
796812
/* On error, stop handling until the next kick. */
797813
if (unlikely(headcount < 0))
@@ -862,12 +878,9 @@ static void handle_rx(struct vhost_net *net)
862878
vhost_discard_vq_desc(vq, headcount);
863879
goto out;
864880
}
865-
nheads += headcount;
866-
if (nheads > VHOST_RX_BATCH) {
867-
vhost_add_used_and_signal_n(&net->dev, vq, vq->heads,
868-
nheads);
869-
nheads = 0;
870-
}
881+
nvq->done_idx += headcount;
882+
if (nvq->done_idx > VHOST_RX_BATCH)
883+
vhost_rx_signal_used(nvq);
871884
if (unlikely(vq_log))
872885
vhost_log_write(vq, vq_log, log, vhost_len);
873886
total_len += vhost_len;
@@ -878,9 +891,7 @@ static void handle_rx(struct vhost_net *net)
878891
}
879892
vhost_net_enable_vq(net, vq);
880893
out:
881-
if (nheads)
882-
vhost_add_used_and_signal_n(&net->dev, vq, vq->heads,
883-
nheads);
894+
vhost_rx_signal_used(nvq);
884895
mutex_unlock(&vq->mutex);
885896
}
886897

0 commit comments

Comments
 (0)