Message ID | 2c52aa26-8181-d37a-bccd-a86bd3cbc6e1@sberdevices.ru |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:604a:0:0:0:0:0 with SMTP id j10csp262740wrt; Fri, 17 Mar 2023 03:44:11 -0700 (PDT) X-Google-Smtp-Source: AK7set/qIZxoNXk0UkfzSHiBvTiwc1PR0ZOl7Z1db4Et1racuU1RHy6jR+oljRcVqLqczsk454De X-Received: by 2002:a17:902:d3c9:b0:1a0:53ba:ff1f with SMTP id w9-20020a170902d3c900b001a053baff1fmr7036167plb.0.1679049851221; Fri, 17 Mar 2023 03:44:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1679049851; cv=none; d=google.com; s=arc-20160816; b=O99+fICgDkkzgp4hKok338mreVnM55MObdq9dKj3D9M5GDewQQKHYSisFWMAOxRfke Jl2Cw3F02NwQ5QPOJqq/T4c+5dbiJRcCkxxSAwadv5stNRQGy5Lb5nj69RZQzjYrMsKc EbZ9XdIeWQakHnE59K6Y0OBIPoZPEjsTjf2O0GyRp1Lio5pQJvC2VOffLpWFuDyZhyN/ OyboU40kBdw6yumlxO0P6cMQND1UIMyzvmZK6OtNkPcDRV4xoM+tSfmPD7ZzeXizWtk5 hAQkkKNY72frIZJ4jzDS6sqWi91Tu2Iege1QIZ/D3pgZuLBUH+HOyNtWsFSSYNWUvqdx 80Qg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:subject:from:cc:to :content-language:user-agent:mime-version:date:message-id :dkim-signature; bh=ud9QwJyCxtRqhWwZzbGgqbYviVFkVybpiPswGzZYdEM=; b=y01FWJh15tTTURf1nkPzrdbhfcjVZnROSU3vaV+puoOP/Xzp5BCPMpvVERwWDFDyqQ b4Uf216SSKxMYf69Vaa45Tqf4RD6PU3h9hAPJP+EmKU2DLXCvJKc0w6dPOQp38mwOU0e /mKu/TQDqv0t826WLKPTFRuuYTEvAnfyYXKTfxDFipb428Z1rbSVFZ33Gq9pmSi3LxJ7 xAnC7VICGkESEDeT63MEbqZ2ZdHx+VXB1FBMZ+bLfh4ZEYVkal2eTtbcf4BmLdo9hYHA U4q/SyfgmyMbtDf+n8QipnLuZN+qEf0WN7B1Xbihtd94H9XdvrQemHQqH/TxP9L88JMG UkQg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b=h4o6yqyn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id m13-20020a170902db0d00b0019e6a5cf724si2437386plx.203.2023.03.17.03.43.56; Fri, 17 Mar 2023 03:44:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@sberdevices.ru header.s=mail header.b=h4o6yqyn; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=sberdevices.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230084AbjCQKl7 (ORCPT <rfc822;chrisfriedt@gmail.com> + 99 others); Fri, 17 Mar 2023 06:41:59 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:60608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229651AbjCQKl6 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Fri, 17 Mar 2023 06:41:58 -0400 Received: from mx.sberdevices.ru (mx.sberdevices.ru [45.89.227.171]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3CF6AFF04; Fri, 17 Mar 2023 03:41:56 -0700 (PDT) Received: from s-lin-edge02.sberdevices.ru (localhost [127.0.0.1]) by mx.sberdevices.ru (Postfix) with ESMTP id 92D475FD3D; Fri, 17 Mar 2023 13:41:54 +0300 (MSK) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sberdevices.ru; s=mail; t=1679049714; bh=ud9QwJyCxtRqhWwZzbGgqbYviVFkVybpiPswGzZYdEM=; h=Message-ID:Date:MIME-Version:To:From:Subject:Content-Type; b=h4o6yqyn9pPRCyd9OOy6k0ZJrWdJDF1BLWZkoRdcB0r3qI4IQ2GwNpuPHQDfinJpk 1YrmML4bC/fYU1Fg9IKp3pPpakMXkcGgEbJQD4oDBmyM+O6geuDnj6HUeAS/LqmbPZ 5x4N1+nmNBhupfteEUE9NH4UIIFUo/LWacSQ90gtZOJwwyoMAFikjp1eQHQ7L7NXep KYvO/H9fjXk2r1ITjUJpp+AAlGpW+1i1kk/CoOz2SP09nXU0d2kDA+s/MVUl7fIXhE 1LmQate+tX3dJjW0GMT6dNwrVjFLX/AzMuVmvhy679Trx1MQMAnus7X1XA6FF0ngj7 kZj9wGVNpnyHg== Received: from S-MS-EXCH01.sberdevices.ru (S-MS-EXCH01.sberdevices.ru [172.16.1.4]) by mx.sberdevices.ru (Postfix) with ESMTP; Fri, 17 Mar 2023 13:41:54 +0300 (MSK) Message-ID: <2c52aa26-8181-d37a-bccd-a86bd3cbc6e1@sberdevices.ru> Date: Fri, 17 Mar 2023 13:38:39 +0300 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.7.1 Content-Language: en-US To: Stefan Hajnoczi <stefanha@redhat.com>, Stefano Garzarella <sgarzare@redhat.com>, "David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>, Bobby Eshleman <bobby.eshleman@bytedance.com> CC: <kvm@vger.kernel.org>, <virtualization@lists.linux-foundation.org>, <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>, <kernel@sberdevices.ru>, <oxffffaa@gmail.com>, <avkrasnov@sberdevices.ru> From: Arseniy Krasnov <avkrasnov@sberdevices.ru> Subject: [RFC PATCH v1] virtio/vsock: allocate multiple skbuffs on tx Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Originating-IP: [172.16.1.6] X-ClientProxiedBy: S-MS-EXCH01.sberdevices.ru (172.16.1.4) To S-MS-EXCH01.sberdevices.ru (172.16.1.4) X-KSMG-Rule-ID: 4 X-KSMG-Message-Action: clean X-KSMG-AntiSpam-Status: not scanned, disabled by settings X-KSMG-AntiSpam-Interceptor-Info: not scanned X-KSMG-AntiPhishing: not scanned, disabled by settings X-KSMG-AntiVirus: Kaspersky Secure Mail Gateway, version 1.1.2.30, bases: 2023/03/17 09:15:00 #20959649 X-KSMG-AntiVirus-Status: Clean, skipped X-Spam-Status: No, score=-2.1 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,SPF_HELO_NONE,SPF_PASS, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1760611376533990416?= X-GMAIL-MSGID: =?utf-8?q?1760611376533990416?= |
Series |
[RFC,v1] virtio/vsock: allocate multiple skbuffs on tx
|
|
Commit Message
Arseniy Krasnov
March 17, 2023, 10:38 a.m. UTC
This adds small optimization for tx path: instead of allocating single
skbuff on every call to transport, allocate multiple skbuffs until
credit space allows, thus trying to send as much as possible data without
return to af_vsock.c.
Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru>
---
net/vmw_vsock/virtio_transport_common.c | 45 +++++++++++++++++--------
1 file changed, 31 insertions(+), 14 deletions(-)
Comments
On Fri, Mar 17, 2023 at 01:38:39PM +0300, Arseniy Krasnov wrote: > This adds small optimization for tx path: instead of allocating single > skbuff on every call to transport, allocate multiple skbuffs until > credit space allows, thus trying to send as much as possible data without > return to af_vsock.c. Hey Arseniy, I really like this optimization. I have a few questions/comments below. > > Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> > --- > net/vmw_vsock/virtio_transport_common.c | 45 +++++++++++++++++-------- > 1 file changed, 31 insertions(+), 14 deletions(-) > > diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c > index 6564192e7f20..cda587196475 100644 > --- a/net/vmw_vsock/virtio_transport_common.c > +++ b/net/vmw_vsock/virtio_transport_common.c > @@ -196,7 +196,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, > const struct virtio_transport *t_ops; > struct virtio_vsock_sock *vvs; > u32 pkt_len = info->pkt_len; > - struct sk_buff *skb; > + u32 rest_len; > + int ret; > > info->type = virtio_transport_get_type(sk_vsock(vsk)); > > @@ -216,10 +217,6 @@ 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_MAX_PKT_BUF_SIZE) > - pkt_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; > - > /* virtio_transport_get_credit might return less than pkt_len credit */ > pkt_len = virtio_transport_get_credit(vvs, pkt_len); > > @@ -227,17 +224,37 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, > if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW) > return pkt_len; > > - skb = virtio_transport_alloc_skb(info, pkt_len, > - src_cid, src_port, > - dst_cid, dst_port); > - if (!skb) { > - virtio_transport_put_credit(vvs, pkt_len); > - return -ENOMEM; > - } > + rest_len = pkt_len; > > - virtio_transport_inc_tx_pkt(vvs, skb); > + do { > + struct sk_buff *skb; > + size_t skb_len; > + > + skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, rest_len); > + > + skb = virtio_transport_alloc_skb(info, skb_len, > + src_cid, src_port, > + dst_cid, dst_port); > + if (!skb) { > + ret = -ENOMEM; > + goto out; > + } In this case, if a previous round of the loop succeeded with send_pkt(), I think that we may still want to return the number of bytes that have successfully been sent so far? > > - return t_ops->send_pkt(skb); > + virtio_transport_inc_tx_pkt(vvs, skb); > + > + ret = t_ops->send_pkt(skb); > + > + if (ret < 0) > + goto out; Ditto here. > + > + rest_len -= skb_len; > + } while (rest_len); > + > + return pkt_len; > + > +out: > + virtio_transport_put_credit(vvs, rest_len); > + return ret; > } > > static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, > -- > 2.25.1
On 18.03.2023 00:52, Bobby Eshleman wrote: > On Fri, Mar 17, 2023 at 01:38:39PM +0300, Arseniy Krasnov wrote: >> This adds small optimization for tx path: instead of allocating single >> skbuff on every call to transport, allocate multiple skbuffs until >> credit space allows, thus trying to send as much as possible data without >> return to af_vsock.c. > > Hey Arseniy, I really like this optimization. I have a few > questions/comments below. > >> >> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >> --- >> net/vmw_vsock/virtio_transport_common.c | 45 +++++++++++++++++-------- >> 1 file changed, 31 insertions(+), 14 deletions(-) >> >> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c >> index 6564192e7f20..cda587196475 100644 >> --- a/net/vmw_vsock/virtio_transport_common.c >> +++ b/net/vmw_vsock/virtio_transport_common.c >> @@ -196,7 +196,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, >> const struct virtio_transport *t_ops; >> struct virtio_vsock_sock *vvs; >> u32 pkt_len = info->pkt_len; >> - struct sk_buff *skb; >> + u32 rest_len; >> + int ret; >> >> info->type = virtio_transport_get_type(sk_vsock(vsk)); >> >> @@ -216,10 +217,6 @@ 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_MAX_PKT_BUF_SIZE) >> - pkt_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; >> - >> /* virtio_transport_get_credit might return less than pkt_len credit */ >> pkt_len = virtio_transport_get_credit(vvs, pkt_len); >> >> @@ -227,17 +224,37 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, >> if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW) >> return pkt_len; >> >> - skb = virtio_transport_alloc_skb(info, pkt_len, >> - src_cid, src_port, >> - dst_cid, dst_port); >> - if (!skb) { >> - virtio_transport_put_credit(vvs, pkt_len); >> - return -ENOMEM; >> - } >> + rest_len = pkt_len; >> >> - virtio_transport_inc_tx_pkt(vvs, skb); >> + do { >> + struct sk_buff *skb; >> + size_t skb_len; >> + >> + skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, rest_len); >> + >> + skb = virtio_transport_alloc_skb(info, skb_len, >> + src_cid, src_port, >> + dst_cid, dst_port); >> + if (!skb) { >> + ret = -ENOMEM; >> + goto out; >> + } > > In this case, if a previous round of the loop succeeded with send_pkt(), > I think that we may still want to return the number of bytes that have > successfully been sent so far? > Hello! Thanks for review! Yes, You are right, seems this patch breaks partial send return value. For example for the following iov (suppose each '.iov_len' is 64Kb, e.g. max packet length): [0] = { .iov_base = ptr0, .iov_len = len0 }, [1] = { .iov_base = NULL, .iov_len = len1 }, [2] = { .iov_base = ptr2, .iov_len = len2 } transport callback will send element 0, but NULL iov_base of element 1 will cause tx failure. Transport callback returns error (no information about transmitted skbuffs), but element 0 was already passed to virtio/vhost path. Current logic will return length of element 0 (it will be accounted to return from send syscall), then calls transport again with invalid element 1 which triggers error. I'm not sure that it is correct (at least in this single patch) to return number of bytes sent, because tx loop in af_vsock.c compares length of user's buffer and number of bytes sent to break tx loop (or loop is terminated when transport returns error). For above iov, we return length of element 0 without length of invalid element 1, but not error (so loop exit condition never won't be true). Moreover, with this approach only first failed to tx skbuff will return error. For second, third, etc. skbuffs we get only number of bytes. I think may be we can use socket's 'sk_err' field here: when tx callback failed to send data(no matter it is first byte or last byte of middle byte), it returns number of bytes sent (it will be 0 if first skbuff was failed to sent) and sets 'sk_err'. Good thing here is that tx loop in af_vsock.c already has check for 'sk_err' value and break loop if error occurred. This way looks like 'errno' concept a little bit: transport returns number of bytes, 'sk_err' contains error. So in current patch it will look like this: instead of setting 'ret' with error, i set 'sk_err' with error, but callback returns number of bytes transmitted. May be we need review from some more experienced guy, Stefano Garzarella, what do You think? Thanks, Arseniy >> >> - return t_ops->send_pkt(skb); >> + virtio_transport_inc_tx_pkt(vvs, skb); >> + >> + ret = t_ops->send_pkt(skb); >> + >> + if (ret < 0) >> + goto out; > > Ditto here. > >> + >> + rest_len -= skb_len; >> + } while (rest_len); >> + >> + return pkt_len; >> + >> +out: >> + virtio_transport_put_credit(vvs, rest_len); >> + return ret; >> } >> >> static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, >> -- >> 2.25.1
On 18.03.2023 21:01, Arseniy Krasnov wrote: > > > On 18.03.2023 00:52, Bobby Eshleman wrote: >> On Fri, Mar 17, 2023 at 01:38:39PM +0300, Arseniy Krasnov wrote: >>> This adds small optimization for tx path: instead of allocating single >>> skbuff on every call to transport, allocate multiple skbuffs until >>> credit space allows, thus trying to send as much as possible data without >>> return to af_vsock.c. >> >> Hey Arseniy, I really like this optimization. I have a few >> questions/comments below. >> >>> >>> Signed-off-by: Arseniy Krasnov <AVKrasnov@sberdevices.ru> >>> --- >>> net/vmw_vsock/virtio_transport_common.c | 45 +++++++++++++++++-------- >>> 1 file changed, 31 insertions(+), 14 deletions(-) >>> >>> diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c >>> index 6564192e7f20..cda587196475 100644 >>> --- a/net/vmw_vsock/virtio_transport_common.c >>> +++ b/net/vmw_vsock/virtio_transport_common.c >>> @@ -196,7 +196,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, >>> const struct virtio_transport *t_ops; >>> struct virtio_vsock_sock *vvs; >>> u32 pkt_len = info->pkt_len; >>> - struct sk_buff *skb; >>> + u32 rest_len; >>> + int ret; >>> >>> info->type = virtio_transport_get_type(sk_vsock(vsk)); >>> >>> @@ -216,10 +217,6 @@ 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_MAX_PKT_BUF_SIZE) >>> - pkt_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; >>> - >>> /* virtio_transport_get_credit might return less than pkt_len credit */ >>> pkt_len = virtio_transport_get_credit(vvs, pkt_len); >>> >>> @@ -227,17 +224,37 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, >>> if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW) >>> return pkt_len; >>> >>> - skb = virtio_transport_alloc_skb(info, pkt_len, >>> - src_cid, src_port, >>> - dst_cid, dst_port); >>> - if (!skb) { >>> - virtio_transport_put_credit(vvs, pkt_len); >>> - return -ENOMEM; >>> - } >>> + rest_len = pkt_len; >>> >>> - virtio_transport_inc_tx_pkt(vvs, skb); >>> + do { >>> + struct sk_buff *skb; >>> + size_t skb_len; >>> + >>> + skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, rest_len); >>> + >>> + skb = virtio_transport_alloc_skb(info, skb_len, >>> + src_cid, src_port, >>> + dst_cid, dst_port); >>> + if (!skb) { >>> + ret = -ENOMEM; >>> + goto out; >>> + } >> >> In this case, if a previous round of the loop succeeded with send_pkt(), >> I think that we may still want to return the number of bytes that have >> successfully been sent so far? >> > Hello! Thanks for review! > > Yes, You are right, seems this patch breaks partial send return value. For example for the > following iov (suppose each '.iov_len' is 64Kb, e.g. max packet length): > > [0] = { .iov_base = ptr0, .iov_len = len0 }, > [1] = { .iov_base = NULL, .iov_len = len1 }, > [2] = { .iov_base = ptr2, .iov_len = len2 } > > transport callback will send element 0, but NULL iov_base of element 1 will cause tx failure. > Transport callback returns error (no information about transmitted skbuffs), but element 0 was > already passed to virtio/vhost path. > > Current logic will return length of element 0 (it will be accounted to return from send syscall), > then calls transport again with invalid element 1 which triggers error. > > I'm not sure that it is correct (at least in this single patch) to return number of bytes sent, > because tx loop in af_vsock.c compares length of user's buffer and number of bytes sent to break > tx loop (or loop is terminated when transport returns error). For above iov, we return length of > element 0 without length of invalid element 1, but not error (so loop exit condition never won't > be true). Moreover, with this approach only first failed to tx skbuff will return error. For second, > third, etc. skbuffs we get only number of bytes. > > I think may be we can use socket's 'sk_err' field here: when tx callback failed to send data(no > matter it is first byte or last byte of middle byte), it returns number of bytes sent (it will be > 0 if first skbuff was failed to sent) and sets 'sk_err'. Good thing here is that tx loop in af_vsock.c > already has check for 'sk_err' value and break loop if error occurred. This way looks like 'errno' > concept a little bit: transport returns number of bytes, 'sk_err' contains error. So in current > patch it will look like this: instead of setting 'ret' with error, i set 'sk_err' with error, > but callback returns number of bytes transmitted. > > May be we need review from some more experienced guy, Stefano Garzarella, what do You think? Ahhhh, i see, sorry, my misunderstanding. Don't read long text above :) I can return error if nothing was sent, otherwise return number of bytes. I'll prepare v2. Thanks, Arseniy > > Thanks, Arseniy >>> >>> - return t_ops->send_pkt(skb); >>> + virtio_transport_inc_tx_pkt(vvs, skb); >>> + >>> + ret = t_ops->send_pkt(skb); >>> + >>> + if (ret < 0) >>> + goto out; >> >> Ditto here. >> >>> + >>> + rest_len -= skb_len; >>> + } while (rest_len); >>> + >>> + return pkt_len; >>> + >>> +out: >>> + virtio_transport_put_credit(vvs, rest_len); >>> + return ret; >>> } >>> >>> static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs, >>> -- >>> 2.25.1
diff --git a/net/vmw_vsock/virtio_transport_common.c b/net/vmw_vsock/virtio_transport_common.c index 6564192e7f20..cda587196475 100644 --- a/net/vmw_vsock/virtio_transport_common.c +++ b/net/vmw_vsock/virtio_transport_common.c @@ -196,7 +196,8 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, const struct virtio_transport *t_ops; struct virtio_vsock_sock *vvs; u32 pkt_len = info->pkt_len; - struct sk_buff *skb; + u32 rest_len; + int ret; info->type = virtio_transport_get_type(sk_vsock(vsk)); @@ -216,10 +217,6 @@ 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_MAX_PKT_BUF_SIZE) - pkt_len = VIRTIO_VSOCK_MAX_PKT_BUF_SIZE; - /* virtio_transport_get_credit might return less than pkt_len credit */ pkt_len = virtio_transport_get_credit(vvs, pkt_len); @@ -227,17 +224,37 @@ static int virtio_transport_send_pkt_info(struct vsock_sock *vsk, if (pkt_len == 0 && info->op == VIRTIO_VSOCK_OP_RW) return pkt_len; - skb = virtio_transport_alloc_skb(info, pkt_len, - src_cid, src_port, - dst_cid, dst_port); - if (!skb) { - virtio_transport_put_credit(vvs, pkt_len); - return -ENOMEM; - } + rest_len = pkt_len; - virtio_transport_inc_tx_pkt(vvs, skb); + do { + struct sk_buff *skb; + size_t skb_len; + + skb_len = min_t(u32, VIRTIO_VSOCK_MAX_PKT_BUF_SIZE, rest_len); + + skb = virtio_transport_alloc_skb(info, skb_len, + src_cid, src_port, + dst_cid, dst_port); + if (!skb) { + ret = -ENOMEM; + goto out; + } - return t_ops->send_pkt(skb); + virtio_transport_inc_tx_pkt(vvs, skb); + + ret = t_ops->send_pkt(skb); + + if (ret < 0) + goto out; + + rest_len -= skb_len; + } while (rest_len); + + return pkt_len; + +out: + virtio_transport_put_credit(vvs, rest_len); + return ret; } static bool virtio_transport_inc_rx_pkt(struct virtio_vsock_sock *vvs,