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