From patchwork Wed Dec 12 09:28:16 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jiangyiwen X-Patchwork-Id: 1011716 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=huawei.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43FBLw49tGz9s2P for ; Wed, 12 Dec 2018 20:28:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726791AbeLLJ2W (ORCPT ); Wed, 12 Dec 2018 04:28:22 -0500 Received: from szxga06-in.huawei.com ([45.249.212.32]:51888 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726519AbeLLJ2W (ORCPT ); Wed, 12 Dec 2018 04:28:22 -0500 Received: from DGGEMS410-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id 0FC25289DD323; Wed, 12 Dec 2018 17:28:20 +0800 (CST) Received: from [127.0.0.1] (10.177.16.168) by DGGEMS410-HUB.china.huawei.com (10.3.19.210) with Microsoft SMTP Server id 14.3.408.0; Wed, 12 Dec 2018 17:28:18 +0800 To: Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang CC: , , From: jiangyiwen Subject: [PATCH v2 1/5] VSOCK: support fill mergeable rx buffer in guest Message-ID: <5C10D4B0.8080504@huawei.com> Date: Wed, 12 Dec 2018 17:28:16 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-Originating-IP: [10.177.16.168] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org In driver probing, if virtio has VIRTIO_VSOCK_F_MRG_RXBUF feature, it will fill mergeable rx buffer, support for host send mergeable rx buffer. It will fill a fixed size(PAGE_SIZE) everytime to compact with small packet and big packet. In addition, it also add one optimizations copied from virtio-net.c. - Skb_page_frag_refill() which can use high order page and reduce the stress of page allocator. Signed-off-by: Yiwen Jiang --- include/linux/virtio_vsock.h | 3 ++ net/vmw_vsock/virtio_transport.c | 112 +++++++++++++++++++++++++++++++-------- 2 files changed, 92 insertions(+), 23 deletions(-) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index e223e26..bf84418 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -14,6 +14,9 @@ #define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL #define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64) +/* Virtio-vsock feature */ +#define VIRTIO_VSOCK_F_MRG_RXBUF 0 /* Host can merge receive buffers. */ + enum { VSOCK_VQ_RX = 0, /* for host to guest data */ VSOCK_VQ_TX = 1, /* for guest to host data */ diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 5d3cce9..c4a465c 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -64,6 +64,11 @@ struct virtio_vsock { struct virtio_vsock_event event_list[8]; u32 guest_cid; + + /* As mergeable rx buffer flag */ + bool mergeable; + /* Page frag for packet buffer allocation. */ + struct page_frag alloc_frag; }; static struct virtio_vsock *virtio_vsock_get(void) @@ -256,39 +261,89 @@ static int virtio_transport_send_pkt_loopback(struct virtio_vsock *vsock, return 0; } -static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) +/* This segment of codes are copied from virtio-net.c */ +static int fill_mergeable_rx_buff(struct virtio_vsock *vsock, + struct virtqueue *vq) +{ + struct page_frag *alloc_frag = &vsock->alloc_frag; + struct scatterlist sg; + /* Currently we don't use ewma len, use PAGE_SIZE instead, because too + * small size can't fill one full packet, sadly we only 128 vq num now. + */ + unsigned int len = PAGE_SIZE, hole; + void *buf; + int err; + + if (unlikely(!skb_page_frag_refill(len, alloc_frag, GFP_KERNEL))) + return -ENOMEM; + + buf = (void *)page_address(alloc_frag->page) + alloc_frag->offset; + get_page(alloc_frag->page); + alloc_frag->offset += len; + hole = alloc_frag->size - alloc_frag->offset; + if (hole < len) { + /* To avoid internal fragmentation, if there is very likely not + * enough space for another buffer, add the remaining space to + * the current buffer. + */ + len += hole; + alloc_frag->offset += hole; + } + + sg_init_one(&sg, buf, len); + err = virtqueue_add_inbuf(vq, &sg, 1, buf, GFP_KERNEL); + if (err < 0) + put_page(virt_to_head_page(buf)); + + return err; +} + +static int fill_old_rx_buff(struct virtqueue *vq) { int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; struct virtio_vsock_pkt *pkt; struct scatterlist hdr, buf, *sgs[2]; - struct virtqueue *vq; int ret; - vq = vsock->vqs[VSOCK_VQ_RX]; + pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); + if (!pkt) + return -ENOMEM; - do { - pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); - if (!pkt) - break; + pkt->buf = kmalloc(buf_len, GFP_KERNEL); + if (!pkt->buf) { + virtio_transport_free_pkt(pkt); + return -ENOMEM; + } - pkt->buf = kmalloc(buf_len, GFP_KERNEL); - if (!pkt->buf) { - virtio_transport_free_pkt(pkt); - break; - } + pkt->len = buf_len; - pkt->len = buf_len; + sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); + sgs[0] = &hdr; - sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); - sgs[0] = &hdr; + sg_init_one(&buf, pkt->buf, buf_len); + sgs[1] = &buf; + ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL); + if (ret) + virtio_transport_free_pkt(pkt); - sg_init_one(&buf, pkt->buf, buf_len); - sgs[1] = &buf; - ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL); - if (ret) { - virtio_transport_free_pkt(pkt); + return ret; +} + +static void virtio_vsock_rx_fill(struct virtio_vsock *vsock) +{ + struct virtqueue *vq; + int ret; + + vq = vsock->vqs[VSOCK_VQ_RX]; + + do { + if (vsock->mergeable) + ret = fill_mergeable_rx_buff(vsock, vq); + else + ret = fill_old_rx_buff(vq); + if (ret) break; - } + vsock->rx_buf_nr++; } while (vq->num_free); if (vsock->rx_buf_nr > vsock->rx_buf_max_nr) @@ -588,6 +643,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev) if (ret < 0) goto out_vqs; + if (virtio_has_feature(vdev, VIRTIO_VSOCK_F_MRG_RXBUF)) + vsock->mergeable = true; + vsock->rx_buf_nr = 0; vsock->rx_buf_max_nr = 0; atomic_set(&vsock->queued_replies, 0); @@ -640,8 +698,15 @@ static void virtio_vsock_remove(struct virtio_device *vdev) vdev->config->reset(vdev); mutex_lock(&vsock->rx_lock); - while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_RX]))) - virtio_transport_free_pkt(pkt); + while ((pkt = virtqueue_detach_unused_buf(vsock->vqs[VSOCK_VQ_RX]))) { + if (vsock->mergeable) + put_page(virt_to_head_page((void *)pkt)); + else + virtio_transport_free_pkt(pkt); + } + + if (vsock->alloc_frag.page) + put_page(vsock->alloc_frag.page); mutex_unlock(&vsock->rx_lock); mutex_lock(&vsock->tx_lock); @@ -683,6 +748,7 @@ static void virtio_vsock_remove(struct virtio_device *vdev) }; static unsigned int features[] = { + VIRTIO_VSOCK_F_MRG_RXBUF, }; static struct virtio_driver virtio_vsock_driver = { From patchwork Wed Dec 12 09:29:31 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jiangyiwen X-Patchwork-Id: 1011718 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=huawei.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43FBNP5pbWz9s2P for ; Wed, 12 Dec 2018 20:29:41 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726877AbeLLJ3k (ORCPT ); Wed, 12 Dec 2018 04:29:40 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:43272 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726525AbeLLJ3k (ORCPT ); Wed, 12 Dec 2018 04:29:40 -0500 Received: from DGGEMS411-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 8BBE6871642DA; Wed, 12 Dec 2018 17:29:36 +0800 (CST) Received: from [127.0.0.1] (10.177.16.168) by DGGEMS411-HUB.china.huawei.com (10.3.19.211) with Microsoft SMTP Server id 14.3.408.0; Wed, 12 Dec 2018 17:29:33 +0800 To: Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang CC: , , From: jiangyiwen Subject: [PATCH v2 2/5] VSOCK: support fill data to mergeable rx buffer in host Message-ID: <5C10D4FB.6070009@huawei.com> Date: Wed, 12 Dec 2018 17:29:31 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-Originating-IP: [10.177.16.168] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org When vhost support VIRTIO_VSOCK_F_MRG_RXBUF feature, it will merge big packet into rx vq. Signed-off-by: Yiwen Jiang --- drivers/vhost/vsock.c | 111 ++++++++++++++++++++++++++++++-------- include/linux/virtio_vsock.h | 1 + include/uapi/linux/virtio_vsock.h | 5 ++ 3 files changed, 94 insertions(+), 23 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 34bc3ab..dc52b0f 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -22,7 +22,8 @@ #define VHOST_VSOCK_DEFAULT_HOST_CID 2 enum { - VHOST_VSOCK_FEATURES = VHOST_FEATURES, + VHOST_VSOCK_FEATURES = VHOST_FEATURES | + (1ULL << VIRTIO_VSOCK_F_MRG_RXBUF), }; /* Used to track all the vhost_vsock instances on the system. */ @@ -80,6 +81,69 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) return vsock; } +/* This segment of codes are copied from drivers/vhost/net.c */ +static int get_rx_bufs(struct vhost_virtqueue *vq, + struct vring_used_elem *heads, int datalen, + unsigned *iovcount, unsigned int quota) +{ + unsigned int out, in; + int seg = 0; + int headcount = 0; + unsigned d; + int ret; + /* + * len is always initialized before use since we are always called with + * datalen > 0. + */ + u32 uninitialized_var(len); + + while (datalen > 0 && headcount < quota) { + if (unlikely(seg >= UIO_MAXIOV)) { + ret = -ENOBUFS; + goto err; + } + + ret = vhost_get_vq_desc(vq, vq->iov + seg, + ARRAY_SIZE(vq->iov) - seg, &out, + &in, NULL, NULL); + if (unlikely(ret < 0)) + goto err; + + d = ret; + if (d == vq->num) { + ret = 0; + goto err; + } + + if (unlikely(out || in <= 0)) { + vq_err(vq, "unexpected descriptor format for RX: " + "out %d, in %d\n", out, in); + ret = -EINVAL; + goto err; + } + + heads[headcount].id = cpu_to_vhost32(vq, d); + len = iov_length(vq->iov + seg, in); + heads[headcount].len = cpu_to_vhost32(vq, len); + datalen -= len; + ++headcount; + seg += in; + } + + heads[headcount - 1].len = cpu_to_vhost32(vq, len + datalen); + *iovcount = seg; + + /* Detect overrun */ + if (unlikely(datalen > 0)) { + ret = UIO_MAXIOV + 1; + goto err; + } + return headcount; +err: + vhost_discard_vq_desc(vq, headcount); + return ret; +} + static void vhost_transport_do_send_pkt(struct vhost_vsock *vsock, struct vhost_virtqueue *vq) @@ -87,22 +151,34 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; bool added = false; bool restart_tx = false; + int mergeable; + size_t vsock_hlen; mutex_lock(&vq->mutex); if (!vq->private_data) goto out; + mergeable = vhost_has_feature(vq, VIRTIO_VSOCK_F_MRG_RXBUF); + /* + * Guest fill page for rx vq in mergeable case, so it will not + * allocate pkt structure, we should reserve size of pkt in advance. + */ + if (likely(mergeable)) + vsock_hlen = sizeof(struct virtio_vsock_pkt); + else + vsock_hlen = sizeof(struct virtio_vsock_hdr); + /* Avoid further vmexits, we're already processing the virtqueue */ vhost_disable_notify(&vsock->dev, vq); for (;;) { struct virtio_vsock_pkt *pkt; struct iov_iter iov_iter; - unsigned out, in; + unsigned out = 0, in = 0; size_t nbytes; size_t len; - int head; + s16 headcount; spin_lock_bh(&vsock->send_pkt_list_lock); if (list_empty(&vsock->send_pkt_list)) { @@ -116,16 +192,9 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) list_del_init(&pkt->list); spin_unlock_bh(&vsock->send_pkt_list_lock); - head = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), - &out, &in, NULL, NULL); - if (head < 0) { - spin_lock_bh(&vsock->send_pkt_list_lock); - list_add(&pkt->list, &vsock->send_pkt_list); - spin_unlock_bh(&vsock->send_pkt_list_lock); - break; - } - - if (head == vq->num) { + headcount = get_rx_bufs(vq, vq->heads, vsock_hlen + pkt->len, + &in, likely(mergeable) ? UIO_MAXIOV : 1); + if (headcount <= 0) { spin_lock_bh(&vsock->send_pkt_list_lock); list_add(&pkt->list, &vsock->send_pkt_list); spin_unlock_bh(&vsock->send_pkt_list_lock); @@ -133,24 +202,20 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) /* We cannot finish yet if more buffers snuck in while * re-enabling notify. */ - if (unlikely(vhost_enable_notify(&vsock->dev, vq))) { + if (!headcount && unlikely(vhost_enable_notify(&vsock->dev, vq))) { vhost_disable_notify(&vsock->dev, vq); continue; } break; } - if (out) { - virtio_transport_free_pkt(pkt); - vq_err(vq, "Expected 0 output buffers, got %u\n", out); - break; - } - len = iov_length(&vq->iov[out], in); iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len); - nbytes = copy_to_iter(&pkt->hdr, sizeof(pkt->hdr), &iov_iter); - if (nbytes != sizeof(pkt->hdr)) { + if (likely(mergeable)) + pkt->mrg_rxbuf_hdr.num_buffers = cpu_to_le16(headcount); + nbytes = copy_to_iter(&pkt->hdr, vsock_hlen, &iov_iter); + if (nbytes != vsock_hlen) { virtio_transport_free_pkt(pkt); vq_err(vq, "Faulted on copying pkt hdr\n"); break; @@ -163,7 +228,7 @@ static struct vhost_vsock *vhost_vsock_get(u32 guest_cid) break; } - vhost_add_used(vq, head, sizeof(pkt->hdr) + pkt->len); + vhost_add_used_n(vq, vq->heads, headcount); added = true; if (pkt->reply) { diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index bf84418..da9e1fe 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -50,6 +50,7 @@ struct virtio_vsock_sock { struct virtio_vsock_pkt { struct virtio_vsock_hdr hdr; + struct virtio_vsock_mrg_rxbuf_hdr mrg_rxbuf_hdr; struct work_struct work; struct list_head list; /* socket refcnt not held, only use for cancellation */ diff --git a/include/uapi/linux/virtio_vsock.h b/include/uapi/linux/virtio_vsock.h index 1d57ed3..2292f30 100644 --- a/include/uapi/linux/virtio_vsock.h +++ b/include/uapi/linux/virtio_vsock.h @@ -63,6 +63,11 @@ struct virtio_vsock_hdr { __le32 fwd_cnt; } __attribute__((packed)); +/* It add mergeable rx buffers feature */ +struct virtio_vsock_mrg_rxbuf_hdr { + __le16 num_buffers; /* number of mergeable rx buffers */ +} __attribute__((packed)); + enum virtio_vsock_type { VIRTIO_VSOCK_TYPE_STREAM = 1, }; From patchwork Wed Dec 12 09:31:39 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jiangyiwen X-Patchwork-Id: 1011720 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=huawei.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43FBQt71k8z9sB7 for ; Wed, 12 Dec 2018 20:31:50 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726904AbeLLJbt (ORCPT ); Wed, 12 Dec 2018 04:31:49 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:44160 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726478AbeLLJbr (ORCPT ); Wed, 12 Dec 2018 04:31:47 -0500 Received: from DGGEMS411-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id 45E44B4082E94; Wed, 12 Dec 2018 17:31:43 +0800 (CST) Received: from [127.0.0.1] (10.177.16.168) by DGGEMS411-HUB.china.huawei.com (10.3.19.211) with Microsoft SMTP Server id 14.3.408.0; Wed, 12 Dec 2018 17:31:41 +0800 To: Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang CC: , , From: jiangyiwen Subject: [PATCH v2 3/5] VSOCK: support receive mergeable rx buffer in guest Message-ID: <5C10D57B.3070701@huawei.com> Date: Wed, 12 Dec 2018 17:31:39 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-Originating-IP: [10.177.16.168] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Guest receive mergeable rx buffer, it can merge scatter rx buffer into a big buffer and then copy to user space. In addition, it also use iovec to replace buf in struct virtio_vsock_pkt, keep tx and rx consistency. The only difference is now tx still uses a segment of continuous physical memory to implement. Signed-off-by: Yiwen Jiang --- drivers/vhost/vsock.c | 31 +++++++--- include/linux/virtio_vsock.h | 6 +- net/vmw_vsock/virtio_transport.c | 105 ++++++++++++++++++++++++++++---- net/vmw_vsock/virtio_transport_common.c | 59 ++++++++++++++---- 4 files changed, 166 insertions(+), 35 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index dc52b0f..c7ab0dd 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -179,6 +179,8 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, size_t nbytes; size_t len; s16 headcount; + size_t remain_len; + int i; spin_lock_bh(&vsock->send_pkt_list_lock); if (list_empty(&vsock->send_pkt_list)) { @@ -221,11 +223,19 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, break; } - nbytes = copy_to_iter(pkt->buf, pkt->len, &iov_iter); - if (nbytes != pkt->len) { - virtio_transport_free_pkt(pkt); - vq_err(vq, "Faulted on copying pkt buf\n"); - break; + remain_len = pkt->len; + for (i = 0; i < pkt->nr_vecs; i++) { + int tmp_len; + + tmp_len = min(remain_len, pkt->vec[i].iov_len); + nbytes = copy_to_iter(pkt->vec[i].iov_base, tmp_len, &iov_iter); + if (nbytes != tmp_len) { + virtio_transport_free_pkt(pkt); + vq_err(vq, "Faulted on copying pkt buf\n"); + break; + } + + remain_len -= tmp_len; } vhost_add_used_n(vq, vq->heads, headcount); @@ -341,6 +351,7 @@ static void vhost_transport_send_pkt_work(struct vhost_work *work) struct iov_iter iov_iter; size_t nbytes; size_t len; + void *buf; if (in != 0) { vq_err(vq, "Expected 0 input buffers, got %u\n", in); @@ -375,13 +386,17 @@ static void vhost_transport_send_pkt_work(struct vhost_work *work) return NULL; } - pkt->buf = kmalloc(pkt->len, GFP_KERNEL); - if (!pkt->buf) { + buf = kmalloc(pkt->len, GFP_KERNEL); + if (!buf) { kfree(pkt); return NULL; } - nbytes = copy_from_iter(pkt->buf, pkt->len, &iov_iter); + pkt->vec[0].iov_base = buf; + pkt->vec[0].iov_len = pkt->len; + pkt->nr_vecs = 1; + + nbytes = copy_from_iter(buf, pkt->len, &iov_iter); if (nbytes != pkt->len) { vq_err(vq, "Expected %u byte payload, got %zu bytes\n", pkt->len, nbytes); diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index da9e1fe..734eeed 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -13,6 +13,8 @@ #define VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE (1024 * 4) #define VIRTIO_VSOCK_MAX_BUF_SIZE 0xFFFFFFFFUL #define VIRTIO_VSOCK_MAX_PKT_BUF_SIZE (1024 * 64) +/* virtio_vsock_pkt + max_pkt_len(default MAX_PKT_BUF_SIZE) */ +#define VIRTIO_VSOCK_MAX_VEC_NUM ((VIRTIO_VSOCK_MAX_PKT_BUF_SIZE / PAGE_SIZE) + 1) /* Virtio-vsock feature */ #define VIRTIO_VSOCK_F_MRG_RXBUF 0 /* Host can merge receive buffers. */ @@ -55,10 +57,12 @@ struct virtio_vsock_pkt { struct list_head list; /* socket refcnt not held, only use for cancellation */ struct vsock_sock *vsk; - void *buf; + struct kvec vec[VIRTIO_VSOCK_MAX_VEC_NUM]; + int nr_vecs; u32 len; u32 off; bool reply; + bool mergeable; }; struct virtio_vsock_pkt_info { diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index c4a465c..148b58a 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -155,8 +155,10 @@ static int virtio_transport_send_pkt_loopback(struct virtio_vsock *vsock, sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); sgs[out_sg++] = &hdr; - if (pkt->buf) { - sg_init_one(&buf, pkt->buf, pkt->len); + if (pkt->len) { + /* Currently only support a segment of memory in tx */ + BUG_ON(pkt->vec[0].iov_len != pkt->len); + sg_init_one(&buf, pkt->vec[0].iov_base, pkt->vec[0].iov_len); sgs[out_sg++] = &buf; } @@ -304,23 +306,28 @@ static int fill_old_rx_buff(struct virtqueue *vq) struct virtio_vsock_pkt *pkt; struct scatterlist hdr, buf, *sgs[2]; int ret; + void *pkt_buf; pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); if (!pkt) return -ENOMEM; - pkt->buf = kmalloc(buf_len, GFP_KERNEL); - if (!pkt->buf) { + pkt_buf = kmalloc(buf_len, GFP_KERNEL); + if (!pkt_buf) { virtio_transport_free_pkt(pkt); return -ENOMEM; } + pkt->vec[0].iov_base = pkt_buf; + pkt->vec[0].iov_len = buf_len; + pkt->nr_vecs = 1; + pkt->len = buf_len; sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr)); sgs[0] = &hdr; - sg_init_one(&buf, pkt->buf, buf_len); + sg_init_one(&buf, pkt->vec[0].iov_base, buf_len); sgs[1] = &buf; ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL); if (ret) @@ -388,11 +395,78 @@ static bool virtio_transport_more_replies(struct virtio_vsock *vsock) return val < virtqueue_get_vring_size(vq); } +static struct virtio_vsock_pkt *receive_mergeable(struct virtqueue *vq, + struct virtio_vsock *vsock, unsigned int *total_len) +{ + struct virtio_vsock_pkt *pkt; + u16 num_buf; + void *buf; + unsigned int len; + size_t vsock_hlen = sizeof(struct virtio_vsock_pkt); + + buf = virtqueue_get_buf(vq, &len); + if (!buf) + return NULL; + + *total_len = len; + vsock->rx_buf_nr--; + + if (unlikely(len < vsock_hlen)) { + put_page(virt_to_head_page(buf)); + return NULL; + } + + pkt = buf; + num_buf = le16_to_cpu(pkt->mrg_rxbuf_hdr.num_buffers); + if (!num_buf || num_buf > VIRTIO_VSOCK_MAX_VEC_NUM) { + put_page(virt_to_head_page(buf)); + return NULL; + } + + /* Initialize pkt residual structure */ + memset(&pkt->work, 0, vsock_hlen - sizeof(struct virtio_vsock_hdr) - + sizeof(struct virtio_vsock_mrg_rxbuf_hdr)); + + pkt->mergeable = true; + pkt->len = le32_to_cpu(pkt->hdr.len); + if (!pkt->len) + return pkt; + + len -= vsock_hlen; + if (len) { + pkt->vec[pkt->nr_vecs].iov_base = buf + vsock_hlen; + pkt->vec[pkt->nr_vecs].iov_len = len; + /* Shared page with pkt, so get page in advance */ + get_page(virt_to_head_page(buf)); + pkt->nr_vecs++; + } + + while (--num_buf) { + buf = virtqueue_get_buf(vq, &len); + if (!buf) + goto err; + + *total_len += len; + vsock->rx_buf_nr--; + + pkt->vec[pkt->nr_vecs].iov_base = buf; + pkt->vec[pkt->nr_vecs].iov_len = len; + pkt->nr_vecs++; + } + + return pkt; +err: + virtio_transport_free_pkt(pkt); + return NULL; +} + static void virtio_transport_rx_work(struct work_struct *work) { struct virtio_vsock *vsock = container_of(work, struct virtio_vsock, rx_work); struct virtqueue *vq; + size_t vsock_hlen = vsock->mergeable ? sizeof(struct virtio_vsock_pkt) : + sizeof(struct virtio_vsock_hdr); vq = vsock->vqs[VSOCK_VQ_RX]; @@ -412,21 +486,26 @@ static void virtio_transport_rx_work(struct work_struct *work) goto out; } - pkt = virtqueue_get_buf(vq, &len); - if (!pkt) { - break; - } + if (likely(vsock->mergeable)) { + pkt = receive_mergeable(vq, vsock, &len); + if (!pkt) + break; + } else { + pkt = virtqueue_get_buf(vq, &len); + if (!pkt) + break; - vsock->rx_buf_nr--; + vsock->rx_buf_nr--; + } /* Drop short/long packets */ - if (unlikely(len < sizeof(pkt->hdr) || - len > sizeof(pkt->hdr) + pkt->len)) { + if (unlikely(len < vsock_hlen || + len > vsock_hlen + pkt->len)) { virtio_transport_free_pkt(pkt); continue; } - pkt->len = len - sizeof(pkt->hdr); + pkt->len = len - vsock_hlen; virtio_transport_deliver_tap_pkt(pkt); virtio_transport_recv_pkt(pkt); } diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 3ae3a33..123a8b6 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -44,6 +44,7 @@ static const struct virtio_transport *virtio_transport_get_ops(void) { struct virtio_vsock_pkt *pkt; int err; + void *buf = NULL; pkt = kzalloc(sizeof(*pkt), GFP_KERNEL); if (!pkt) @@ -62,12 +63,16 @@ static const struct virtio_transport *virtio_transport_get_ops(void) pkt->vsk = info->vsk; if (info->msg && len > 0) { - pkt->buf = kmalloc(len, GFP_KERNEL); - if (!pkt->buf) + buf = kmalloc(len, GFP_KERNEL); + if (!buf) goto out_pkt; - err = memcpy_from_msg(pkt->buf, info->msg, len); + err = memcpy_from_msg(buf, info->msg, len); if (err) goto out; + + pkt->vec[0].iov_base = buf; + pkt->vec[0].iov_len = len; + pkt->nr_vecs = 1; } trace_virtio_transport_alloc_pkt(src_cid, src_port, @@ -80,7 +85,7 @@ static const struct virtio_transport *virtio_transport_get_ops(void) return pkt; out: - kfree(pkt->buf); + kfree(buf); out_pkt: kfree(pkt); return NULL; @@ -92,6 +97,7 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) struct virtio_vsock_pkt *pkt = opaque; struct af_vsockmon_hdr *hdr; struct sk_buff *skb; + int i; skb = alloc_skb(sizeof(*hdr) + sizeof(pkt->hdr) + pkt->len, GFP_ATOMIC); @@ -134,7 +140,8 @@ static struct sk_buff *virtio_transport_build_skb(void *opaque) skb_put_data(skb, &pkt->hdr, sizeof(pkt->hdr)); if (pkt->len) { - skb_put_data(skb, pkt->buf, pkt->len); + for (i = 0; i < pkt->nr_vecs; i++) + skb_put_data(skb, pkt->vec[i].iov_base, pkt->vec[i].iov_len); } return skb; @@ -260,6 +267,9 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk, spin_lock_bh(&vvs->rx_lock); while (total < len && !list_empty(&vvs->rx_queue)) { + size_t copy_bytes, last_vec_total = 0, vec_off; + int i; + pkt = list_first_entry(&vvs->rx_queue, struct virtio_vsock_pkt, list); @@ -272,14 +282,28 @@ static int virtio_transport_send_credit_update(struct vsock_sock *vsk, */ spin_unlock_bh(&vvs->rx_lock); - err = memcpy_to_msg(msg, pkt->buf + pkt->off, bytes); - if (err) - goto out; + for (i = 0; i < pkt->nr_vecs; i++) { + if (pkt->off > last_vec_total + pkt->vec[i].iov_len) { + last_vec_total += pkt->vec[i].iov_len; + continue; + } + + vec_off = pkt->off - last_vec_total; + copy_bytes = min(pkt->vec[i].iov_len - vec_off, bytes); + err = memcpy_to_msg(msg, pkt->vec[i].iov_base + vec_off, + copy_bytes); + if (err) + goto out; + + bytes -= copy_bytes; + pkt->off += copy_bytes; + total += copy_bytes; + last_vec_total += pkt->vec[i].iov_len; + if (!bytes) + break; + } spin_lock_bh(&vvs->rx_lock); - - total += bytes; - pkt->off += bytes; if (pkt->off == pkt->len) { virtio_transport_dec_rx_pkt(vvs, pkt); list_del(&pkt->list); @@ -1050,8 +1074,17 @@ void virtio_transport_recv_pkt(struct virtio_vsock_pkt *pkt) void virtio_transport_free_pkt(struct virtio_vsock_pkt *pkt) { - kfree(pkt->buf); - kfree(pkt); + int i; + + if (pkt->mergeable) { + for (i = 0; i < pkt->nr_vecs; i++) + put_page(virt_to_head_page(pkt->vec[i].iov_base)); + put_page(virt_to_head_page((void *)pkt)); + } else { + for (i = 0; i < pkt->nr_vecs; i++) + kfree(pkt->vec[i].iov_base); + kfree(pkt); + } } EXPORT_SYMBOL_GPL(virtio_transport_free_pkt); From patchwork Wed Dec 12 09:34:05 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jiangyiwen X-Patchwork-Id: 1011722 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=huawei.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43FBTf0SkDz9s2P for ; Wed, 12 Dec 2018 20:34:14 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726863AbeLLJeM (ORCPT ); Wed, 12 Dec 2018 04:34:12 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:45152 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726525AbeLLJeM (ORCPT ); Wed, 12 Dec 2018 04:34:12 -0500 Received: from DGGEMS401-HUB.china.huawei.com (unknown [172.30.72.59]) by Forcepoint Email with ESMTP id E5B4075E41E05; Wed, 12 Dec 2018 17:34:07 +0800 (CST) Received: from [127.0.0.1] (10.177.16.168) by DGGEMS401-HUB.china.huawei.com (10.3.19.201) with Microsoft SMTP Server id 14.3.408.0; Wed, 12 Dec 2018 17:34:07 +0800 To: Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang CC: , , From: jiangyiwen Subject: [PATCH v2 4/5] VSOCK: increase send pkt len in mergeable mode to improve performance Message-ID: <5C10D60D.2010202@huawei.com> Date: Wed, 12 Dec 2018 17:34:05 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-Originating-IP: [10.177.16.168] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Since VSOCK already support mergeable rx buffer, so it can implement the balance with performance and guest memory, we can increase the sent pkt len to improve performance. And in order to be compatible with old version, so we still send max default rx buf size once. Signed-off-by: Yiwen Jiang --- drivers/vhost/vsock.c | 33 ++++++++++++++++++++++++++++----- include/linux/virtio_vsock.h | 3 +++ net/vmw_vsock/virtio_transport.c | 18 ++++++++++++++++++ net/vmw_vsock/virtio_transport_common.c | 7 ++++--- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index c7ab0dd..9600133 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -44,6 +44,8 @@ struct vhost_vsock { atomic_t queued_replies; u32 guest_cid; + + bool mergeable; }; static u32 vhost_transport_get_local_cid(void) @@ -151,7 +153,6 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; bool added = false; bool restart_tx = false; - int mergeable; size_t vsock_hlen; mutex_lock(&vq->mutex); @@ -159,12 +160,11 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, if (!vq->private_data) goto out; - mergeable = vhost_has_feature(vq, VIRTIO_VSOCK_F_MRG_RXBUF); /* * Guest fill page for rx vq in mergeable case, so it will not * allocate pkt structure, we should reserve size of pkt in advance. */ - if (likely(mergeable)) + if (likely(vsock->mergeable)) vsock_hlen = sizeof(struct virtio_vsock_pkt); else vsock_hlen = sizeof(struct virtio_vsock_hdr); @@ -195,7 +195,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, spin_unlock_bh(&vsock->send_pkt_list_lock); headcount = get_rx_bufs(vq, vq->heads, vsock_hlen + pkt->len, - &in, likely(mergeable) ? UIO_MAXIOV : 1); + &in, likely(vsock->mergeable) ? UIO_MAXIOV : 1); if (headcount <= 0) { spin_lock_bh(&vsock->send_pkt_list_lock); list_add(&pkt->list, &vsock->send_pkt_list); @@ -214,7 +214,7 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, len = iov_length(&vq->iov[out], in); iov_iter_init(&iov_iter, READ, &vq->iov[out], in, len); - if (likely(mergeable)) + if (likely(vsock->mergeable)) pkt->mrg_rxbuf_hdr.num_buffers = cpu_to_le16(headcount); nbytes = copy_to_iter(&pkt->hdr, vsock_hlen, &iov_iter); if (nbytes != vsock_hlen) { @@ -303,6 +303,22 @@ static void vhost_transport_send_pkt_work(struct vhost_work *work) return len; } +static u32 +vhost_transport_get_max_pkt_len(u32 guest_cid) +{ + int len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; + struct vhost_vsock *vsock; + + vsock = vhost_vsock_get(guest_cid); + if (!vsock) + return len; + + if (vsock->mergeable) + len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; + + return len; +} + static int vhost_transport_cancel_pkt(struct vsock_sock *vsk) { @@ -602,6 +618,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file) atomic_set(&vsock->queued_replies, 0); + vsock->mergeable = false; + vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX]; vqs[VSOCK_VQ_RX] = &vsock->vqs[VSOCK_VQ_RX]; vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick; @@ -726,6 +744,9 @@ static int vhost_vsock_set_features(struct vhost_vsock *vsock, u64 features) return -EFAULT; } + if (features & (1 << VIRTIO_VSOCK_F_MRG_RXBUF)) + vsock->mergeable = true; + for (i = 0; i < ARRAY_SIZE(vsock->vqs); i++) { vq = &vsock->vqs[i]; mutex_lock(&vq->mutex); @@ -848,6 +869,8 @@ static long vhost_vsock_dev_compat_ioctl(struct file *f, unsigned int ioctl, }, .send_pkt = vhost_transport_send_pkt, + + .max_pkt_len = vhost_transport_get_max_pkt_len, }; static int __init vhost_vsock_init(void) diff --git a/include/linux/virtio_vsock.h b/include/linux/virtio_vsock.h index 734eeed..ad95319 100644 --- a/include/linux/virtio_vsock.h +++ b/include/linux/virtio_vsock.h @@ -82,6 +82,9 @@ struct virtio_transport { /* Takes ownership of the packet */ int (*send_pkt)(struct virtio_vsock_pkt *pkt); + + /* Get max pkt len, cid only be used for Host */ + u32 (*max_pkt_len)(u32 cid); }; ssize_t diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index 148b58a..809085a 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -222,6 +222,22 @@ static int virtio_transport_send_pkt_loopback(struct virtio_vsock *vsock, return len; } +static u32 +virtio_transport_get_max_pkt_len(u32 cid) +{ + int len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; + struct virtio_vsock *vsock; + + vsock = virtio_vsock_get(); + if (!vsock) + return len; + + if (vsock->mergeable) + len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; + + return len; +} + static int virtio_transport_cancel_pkt(struct vsock_sock *vsk) { @@ -675,6 +691,8 @@ static void virtio_vsock_rx_done(struct virtqueue *vq) }, .send_pkt = virtio_transport_send_pkt, + + .max_pkt_len = virtio_transport_get_max_pkt_len, }; static int virtio_vsock_probe(struct virtio_device *vdev) diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 123a8b6..cc14ace 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -159,7 +159,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, u32 src_cid, src_port, dst_cid, dst_port; struct virtio_vsock_sock *vvs; struct virtio_vsock_pkt *pkt; - u32 pkt_len = info->pkt_len; + u32 pkt_len; + u32 max_pkt_len; src_cid = vm_sockets_get_local_cid(); src_port = vsk->local_addr.svm_port; @@ -174,8 +175,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, vvs = vsk->trans; /* we can send less than pkt_len bytes */ - if (pkt_len > VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE) - pkt_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE; + max_pkt_len = virtio_transport_get_ops()->max_pkt_len(dst_cid); + pkt_len = min(max_pkt_len, info->pkt_len); /* virtio_transport_get_credit might return less than pkt_len credit */ pkt_len = virtio_transport_get_credit(vvs, pkt_len); From patchwork Wed Dec 12 09:35:27 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jiangyiwen X-Patchwork-Id: 1011724 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=huawei.com Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 43FBWD0r0Pz9s2P for ; Wed, 12 Dec 2018 20:35:36 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726770AbeLLJfe (ORCPT ); Wed, 12 Dec 2018 04:35:34 -0500 Received: from szxga07-in.huawei.com ([45.249.212.35]:45663 "EHLO huawei.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1726478AbeLLJfe (ORCPT ); Wed, 12 Dec 2018 04:35:34 -0500 Received: from DGGEMS407-HUB.china.huawei.com (unknown [172.30.72.58]) by Forcepoint Email with ESMTP id DA1E23E960B4E; Wed, 12 Dec 2018 17:35:29 +0800 (CST) Received: from [127.0.0.1] (10.177.16.168) by DGGEMS407-HUB.china.huawei.com (10.3.19.207) with Microsoft SMTP Server id 14.3.408.0; Wed, 12 Dec 2018 17:35:29 +0800 To: Stefan Hajnoczi , "Michael S. Tsirkin" , Jason Wang CC: , , From: jiangyiwen Subject: [PATCH v2 5/5] VSOCK: batch sending rx buffer to increase bandwidth Message-ID: <5C10D65F.7030407@huawei.com> Date: Wed, 12 Dec 2018 17:35:27 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:38.0) Gecko/20100101 Thunderbird/38.5.1 MIME-Version: 1.0 X-Originating-IP: [10.177.16.168] X-CFilter-Loop: Reflected Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Batch sending rx buffer can improve total bandwidth. Signed-off-by: Yiwen Jiang --- drivers/vhost/vsock.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 9600133..a4bf0a1 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -151,9 +151,11 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, struct vhost_virtqueue *vq) { struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX]; - bool added = false; bool restart_tx = false; size_t vsock_hlen; + int batch_count = 0; + +#define VHOST_VSOCK_BATCH 16 mutex_lock(&vq->mutex); @@ -194,8 +196,9 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, list_del_init(&pkt->list); spin_unlock_bh(&vsock->send_pkt_list_lock); - headcount = get_rx_bufs(vq, vq->heads, vsock_hlen + pkt->len, - &in, likely(vsock->mergeable) ? UIO_MAXIOV : 1); + headcount = get_rx_bufs(vq, vq->heads + batch_count, + vsock_hlen + pkt->len, &in, + likely(vsock->mergeable) ? UIO_MAXIOV : 1); if (headcount <= 0) { spin_lock_bh(&vsock->send_pkt_list_lock); list_add(&pkt->list, &vsock->send_pkt_list); @@ -238,8 +241,12 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, remain_len -= tmp_len; } - vhost_add_used_n(vq, vq->heads, headcount); - added = true; + batch_count += headcount; + if (batch_count > VHOST_VSOCK_BATCH) { + vhost_add_used_and_signal_n(&vsock->dev, vq, + vq->heads, batch_count); + batch_count = 0; + } if (pkt->reply) { int val; @@ -258,8 +265,11 @@ static int get_rx_bufs(struct vhost_virtqueue *vq, virtio_transport_free_pkt(pkt); } - if (added) - vhost_signal(&vsock->dev, vq); + + if (batch_count) { + vhost_add_used_and_signal_n(&vsock->dev, vq, + vq->heads, batch_count); + } out: mutex_unlock(&vq->mutex);