Blame SOURCES/kvm-multifd-Send-header-packet-without-flags-if-zero-cop.patch

586cba
From 63255c13492f42a3236d96e706e5f8e70bb4e219 Mon Sep 17 00:00:00 2001
586cba
From: Leonardo Bras <leobras@redhat.com>
586cba
Date: Fri, 13 May 2022 03:28:36 -0300
586cba
Subject: [PATCH 13/18] multifd: Send header packet without flags if
586cba
 zero-copy-send is enabled
586cba
MIME-Version: 1.0
586cba
Content-Type: text/plain; charset=UTF-8
586cba
Content-Transfer-Encoding: 8bit
586cba
586cba
RH-Author: Leonardo Brás <leobras@redhat.com>
586cba
RH-MergeRequest: 95: MSG_ZEROCOPY + Multifd
586cba
RH-Commit: [7/11] 137eea685e387d3d6aff187ec3fcac05bc16b6e3 (LeoBras/centos-qemu-kvm)
586cba
RH-Bugzilla: 1968509
586cba
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
586cba
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
586cba
RH-Acked-by: Peter Xu <peterx@redhat.com>
586cba
586cba
Since d48c3a0445 ("multifd: Use a single writev on the send side"),
586cba
sending the header packet and the memory pages happens in the same
586cba
writev, which can potentially make the migration faster.
586cba
586cba
Using channel-socket as example, this works well with the default copying
586cba
mechanism of sendmsg(), but with zero-copy-send=true, it will cause
586cba
the migration to often break.
586cba
586cba
This happens because the header packet buffer gets reused quite often,
586cba
and there is a high chance that by the time the MSG_ZEROCOPY mechanism get
586cba
to send the buffer, it has already changed, sending the wrong data and
586cba
causing the migration to abort.
586cba
586cba
It means that, as it is, the buffer for the header packet is not suitable
586cba
for sending with MSG_ZEROCOPY.
586cba
586cba
In order to enable zero copy for multifd, send the header packet on an
586cba
individual write(), without any flags, and the remanining pages with a
586cba
writev(), as it was happening before. This only changes how a migration
586cba
with zero-copy-send=true works, not changing any current behavior for
586cba
migrations with zero-copy-send=false.
586cba
586cba
Signed-off-by: Leonardo Bras <leobras@redhat.com>
586cba
Reviewed-by: Peter Xu <peterx@redhat.com>
586cba
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
586cba
Message-Id: <20220513062836.965425-8-leobras@redhat.com>
586cba
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
586cba
(cherry picked from commit b7dbdd8e76cd03453c234dbb9578d20969859d74)
586cba
Signed-off-by: Leonardo Bras <leobras@redhat.com>
586cba
---
586cba
 migration/multifd.c | 22 +++++++++++++++++++---
586cba
 1 file changed, 19 insertions(+), 3 deletions(-)
586cba
586cba
diff --git a/migration/multifd.c b/migration/multifd.c
586cba
index cdb57439a7..8fca6c970e 100644
586cba
--- a/migration/multifd.c
586cba
+++ b/migration/multifd.c
586cba
@@ -619,6 +619,7 @@ static void *multifd_send_thread(void *opaque)
586cba
     MultiFDSendParams *p = opaque;
586cba
     Error *local_err = NULL;
586cba
     int ret = 0;
586cba
+    bool use_zero_copy_send = migrate_use_zero_copy_send();
586cba
 
586cba
     trace_multifd_send_thread_start(p->id);
586cba
     rcu_register_thread();
586cba
@@ -641,9 +642,14 @@ static void *multifd_send_thread(void *opaque)
586cba
         if (p->pending_job) {
586cba
             uint64_t packet_num = p->packet_num;
586cba
             uint32_t flags = p->flags;
586cba
-            p->iovs_num = 1;
586cba
             p->normal_num = 0;
586cba
 
586cba
+            if (use_zero_copy_send) {
586cba
+                p->iovs_num = 0;
586cba
+            } else {
586cba
+                p->iovs_num = 1;
586cba
+            }
586cba
+
586cba
             for (int i = 0; i < p->pages->num; i++) {
586cba
                 p->normal[p->normal_num] = p->pages->offset[i];
586cba
                 p->normal_num++;
586cba
@@ -667,8 +673,18 @@ static void *multifd_send_thread(void *opaque)
586cba
             trace_multifd_send(p->id, packet_num, p->normal_num, flags,
586cba
                                p->next_packet_size);
586cba
 
586cba
-            p->iov[0].iov_len = p->packet_len;
586cba
-            p->iov[0].iov_base = p->packet;
586cba
+            if (use_zero_copy_send) {
586cba
+                /* Send header first, without zerocopy */
586cba
+                ret = qio_channel_write_all(p->c, (void *)p->packet,
586cba
+                                            p->packet_len, &local_err);
586cba
+                if (ret != 0) {
586cba
+                    break;
586cba
+                }
586cba
+            } else {
586cba
+                /* Send header using the same writev call */
586cba
+                p->iov[0].iov_len = p->packet_len;
586cba
+                p->iov[0].iov_base = p->packet;
586cba
+            }
586cba
 
586cba
             ret = qio_channel_writev_all(p->c, p->iov, p->iovs_num,
586cba
                                          &local_err);
586cba
-- 
586cba
2.35.3
586cba