Blame SOURCES/kvm-multifd-Use-normal-pages-array-on-the-send-side.patch

1be5c7
From 3b57c876e1eaca34fb5bd9067553de945013d4be Mon Sep 17 00:00:00 2001
1be5c7
From: Juan Quintela <quintela@redhat.com>
1be5c7
Date: Wed, 18 May 2022 02:52:24 -0300
1be5c7
Subject: [PATCH 16/37] multifd: Use normal pages array on the send side
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: [16/26] 1c48806474daf48fe93920ac361311af95c6a6f3
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
We are only sending normal pages through multifd channels.
1be5c7
Later on this series, we are going to also send zero pages.
1be5c7
We are going to detect if a page is zero or non zero in the multifd
1be5c7
channel thread, not on the main thread.
1be5c7
1be5c7
So we receive an array of pages page->offset[N]
1be5c7
1be5c7
And we will end with:
1be5c7
1be5c7
p->normal[N - zero_pages]
1be5c7
p->zero[zero_pages].
1be5c7
1be5c7
In this patch, we just copy all the pages in offset to normal.
1be5c7
1be5c7
for (i = 0; i < pages->num; i++) {
1be5c7
    p->narmal[p->normal_num] = pages->offset[i];
1be5c7
    p->normal_num++:
1be5c7
}
1be5c7
1be5c7
Later in the series this becomes:
1be5c7
1be5c7
for (i = 0; i < pages->num; i++) {
1be5c7
    if (buffer_is_zero(page->offset[i])) {
1be5c7
        p->zerol[p->zero_num] = pages->offset[i];
1be5c7
        p->zero_num++:
1be5c7
    } else {
1be5c7
        p->narmal[p->normal_num] = pages->offset[i];
1be5c7
        p->normal_num++:
1be5c7
    }
1be5c7
}
1be5c7
1be5c7
Signed-off-by: Juan Quintela <quintela@redhat.com>
1be5c7
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
1be5c7
1be5c7
---
1be5c7
1be5c7
Improving comment (dave)
1be5c7
Renaming num_normal_pages to total_normal_pages (peter)
1be5c7
1be5c7
(cherry picked from commit 815956f03902980c771da64b17f7f791c1cb57b0)
1be5c7
Signed-off-by: Leonardo Bras <leobras@redhat.com>
1be5c7
---
1be5c7
 migration/multifd-zlib.c |  6 +++---
1be5c7
 migration/multifd-zstd.c |  6 +++---
1be5c7
 migration/multifd.c      | 30 +++++++++++++++++++-----------
1be5c7
 migration/multifd.h      |  8 ++++++--
1be5c7
 migration/trace-events   |  4 ++--
1be5c7
 5 files changed, 33 insertions(+), 21 deletions(-)
1be5c7
1be5c7
diff --git a/migration/multifd-zlib.c b/migration/multifd-zlib.c
1be5c7
index 8ed29b9633..8508f26adf 100644
1be5c7
--- a/migration/multifd-zlib.c
1be5c7
+++ b/migration/multifd-zlib.c
1be5c7
@@ -108,16 +108,16 @@ static int zlib_send_prepare(MultiFDSendParams *p, Error **errp)
1be5c7
     int ret;
1be5c7
     uint32_t i;
1be5c7
 
1be5c7
-    for (i = 0; i < p->pages->num; i++) {
1be5c7
+    for (i = 0; i < p->normal_num; i++) {
1be5c7
         uint32_t available = z->zbuff_len - out_size;
1be5c7
         int flush = Z_NO_FLUSH;
1be5c7
 
1be5c7
-        if (i == p->pages->num - 1) {
1be5c7
+        if (i == p->normal_num - 1) {
1be5c7
             flush = Z_SYNC_FLUSH;
1be5c7
         }
1be5c7
 
1be5c7
         zs->avail_in = page_size;
1be5c7
-        zs->next_in = p->pages->block->host + p->pages->offset[i];
1be5c7
+        zs->next_in = p->pages->block->host + p->normal[i];
1be5c7
 
1be5c7
         zs->avail_out = available;
1be5c7
         zs->next_out = z->zbuff + out_size;
1be5c7
diff --git a/migration/multifd-zstd.c b/migration/multifd-zstd.c
1be5c7
index 25e1f517b5..693af3a140 100644
1be5c7
--- a/migration/multifd-zstd.c
1be5c7
+++ b/migration/multifd-zstd.c
1be5c7
@@ -123,13 +123,13 @@ static int zstd_send_prepare(MultiFDSendParams *p, Error **errp)
1be5c7
     z->out.size = z->zbuff_len;
1be5c7
     z->out.pos = 0;
1be5c7
 
1be5c7
-    for (i = 0; i < p->pages->num; i++) {
1be5c7
+    for (i = 0; i < p->normal_num; i++) {
1be5c7
         ZSTD_EndDirective flush = ZSTD_e_continue;
1be5c7
 
1be5c7
-        if (i == p->pages->num - 1) {
1be5c7
+        if (i == p->normal_num - 1) {
1be5c7
             flush = ZSTD_e_flush;
1be5c7
         }
1be5c7
-        z->in.src = p->pages->block->host + p->pages->offset[i];
1be5c7
+        z->in.src = p->pages->block->host + p->normal[i];
1be5c7
         z->in.size = page_size;
1be5c7
         z->in.pos = 0;
1be5c7
 
1be5c7
diff --git a/migration/multifd.c b/migration/multifd.c
1be5c7
index d0f86542b1..3725226400 100644
1be5c7
--- a/migration/multifd.c
1be5c7
+++ b/migration/multifd.c
1be5c7
@@ -89,13 +89,13 @@ static int nocomp_send_prepare(MultiFDSendParams *p, Error **errp)
1be5c7
     MultiFDPages_t *pages = p->pages;
1be5c7
     size_t page_size = qemu_target_page_size();
1be5c7
 
1be5c7
-    for (int i = 0; i < p->pages->num; i++) {
1be5c7
-        p->iov[p->iovs_num].iov_base = pages->block->host + pages->offset[i];
1be5c7
+    for (int i = 0; i < p->normal_num; i++) {
1be5c7
+        p->iov[p->iovs_num].iov_base = pages->block->host + p->normal[i];
1be5c7
         p->iov[p->iovs_num].iov_len = page_size;
1be5c7
         p->iovs_num++;
1be5c7
     }
1be5c7
 
1be5c7
-    p->next_packet_size = p->pages->num * page_size;
1be5c7
+    p->next_packet_size = p->normal_num * page_size;
1be5c7
     p->flags |= MULTIFD_FLAG_NOCOMP;
1be5c7
     return 0;
1be5c7
 }
1be5c7
@@ -262,7 +262,7 @@ static void multifd_send_fill_packet(MultiFDSendParams *p)
1be5c7
 
1be5c7
     packet->flags = cpu_to_be32(p->flags);
1be5c7
     packet->pages_alloc = cpu_to_be32(p->pages->allocated);
1be5c7
-    packet->pages_used = cpu_to_be32(p->pages->num);
1be5c7
+    packet->pages_used = cpu_to_be32(p->normal_num);
1be5c7
     packet->next_packet_size = cpu_to_be32(p->next_packet_size);
1be5c7
     packet->packet_num = cpu_to_be64(p->packet_num);
1be5c7
 
1be5c7
@@ -270,9 +270,9 @@ static void multifd_send_fill_packet(MultiFDSendParams *p)
1be5c7
         strncpy(packet->ramblock, p->pages->block->idstr, 256);
1be5c7
     }
1be5c7
 
1be5c7
-    for (i = 0; i < p->pages->num; i++) {
1be5c7
+    for (i = 0; i < p->normal_num; i++) {
1be5c7
         /* there are architectures where ram_addr_t is 32 bit */
1be5c7
-        uint64_t temp = p->pages->offset[i];
1be5c7
+        uint64_t temp = p->normal[i];
1be5c7
 
1be5c7
         packet->offset[i] = cpu_to_be64(temp);
1be5c7
     }
1be5c7
@@ -556,6 +556,8 @@ void multifd_save_cleanup(void)
1be5c7
         p->packet = NULL;
1be5c7
         g_free(p->iov);
1be5c7
         p->iov = NULL;
1be5c7
+        g_free(p->normal);
1be5c7
+        p->normal = NULL;
1be5c7
         multifd_send_state->ops->send_cleanup(p, &local_err);
1be5c7
         if (local_err) {
1be5c7
             migrate_set_error(migrate_get_current(), local_err);
1be5c7
@@ -640,12 +642,17 @@ static void *multifd_send_thread(void *opaque)
1be5c7
         qemu_mutex_lock(&p->mutex);
1be5c7
 
1be5c7
         if (p->pending_job) {
1be5c7
-            uint32_t used = p->pages->num;
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
+            for (int i = 0; i < p->pages->num; i++) {
1be5c7
+                p->normal[p->normal_num] = p->pages->offset[i];
1be5c7
+                p->normal_num++;
1be5c7
+            }
1be5c7
 
1be5c7
-            if (used) {
1be5c7
+            if (p->normal_num) {
1be5c7
                 ret = multifd_send_state->ops->send_prepare(p, &local_err);
1be5c7
                 if (ret != 0) {
1be5c7
                     qemu_mutex_unlock(&p->mutex);
1be5c7
@@ -655,12 +662,12 @@ static void *multifd_send_thread(void *opaque)
1be5c7
             multifd_send_fill_packet(p);
1be5c7
             p->flags = 0;
1be5c7
             p->num_packets++;
1be5c7
-            p->num_pages += used;
1be5c7
+            p->total_normal_pages += p->normal_num;
1be5c7
             p->pages->num = 0;
1be5c7
             p->pages->block = NULL;
1be5c7
             qemu_mutex_unlock(&p->mutex);
1be5c7
 
1be5c7
-            trace_multifd_send(p->id, packet_num, used, flags,
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
@@ -710,7 +717,7 @@ out:
1be5c7
     qemu_mutex_unlock(&p->mutex);
1be5c7
 
1be5c7
     rcu_unregister_thread();
1be5c7
-    trace_multifd_send_thread_end(p->id, p->num_packets, p->num_pages);
1be5c7
+    trace_multifd_send_thread_end(p->id, p->num_packets, p->total_normal_pages);
1be5c7
 
1be5c7
     return NULL;
1be5c7
 }
1be5c7
@@ -910,6 +917,7 @@ int multifd_save_setup(Error **errp)
1be5c7
         p->tls_hostname = g_strdup(s->hostname);
1be5c7
         /* We need one extra place for the packet header */
1be5c7
         p->iov = g_new0(struct iovec, page_count + 1);
1be5c7
+        p->normal = g_new0(ram_addr_t, page_count);
1be5c7
         socket_send_channel_create(multifd_new_send_channel_async, p);
1be5c7
     }
1be5c7
 
1be5c7
diff --git a/migration/multifd.h b/migration/multifd.h
1be5c7
index 7496f951a7..7823199dbe 100644
1be5c7
--- a/migration/multifd.h
1be5c7
+++ b/migration/multifd.h
1be5c7
@@ -104,14 +104,18 @@ typedef struct {
1be5c7
     /* thread local variables */
1be5c7
     /* packets sent through this channel */
1be5c7
     uint64_t num_packets;
1be5c7
-    /* pages sent through this channel */
1be5c7
-    uint64_t num_pages;
1be5c7
+    /* non zero pages sent through this channel */
1be5c7
+    uint64_t total_normal_pages;
1be5c7
     /* syncs main thread and channels */
1be5c7
     QemuSemaphore sem_sync;
1be5c7
     /* buffers to send */
1be5c7
     struct iovec *iov;
1be5c7
     /* number of iovs used */
1be5c7
     uint32_t iovs_num;
1be5c7
+    /* Pages that are not zero */
1be5c7
+    ram_addr_t *normal;
1be5c7
+    /* num of non zero pages */
1be5c7
+    uint32_t normal_num;
1be5c7
     /* used for compression methods */
1be5c7
     void *data;
1be5c7
 }  MultiFDSendParams;
1be5c7
diff --git a/migration/trace-events b/migration/trace-events
1be5c7
index 5172cb3b3d..171a83a55d 100644
1be5c7
--- a/migration/trace-events
1be5c7
+++ b/migration/trace-events
1be5c7
@@ -124,13 +124,13 @@ multifd_recv_sync_main_wait(uint8_t id) "channel %u"
1be5c7
 multifd_recv_terminate_threads(bool error) "error %d"
1be5c7
 multifd_recv_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %u packets %" PRIu64 " pages %" PRIu64
1be5c7
 multifd_recv_thread_start(uint8_t id) "%u"
1be5c7
-multifd_send(uint8_t id, uint64_t packet_num, uint32_t used, uint32_t flags, uint32_t next_packet_size) "channel %u packet_num %" PRIu64 " pages %u flags 0x%x next packet size %u"
1be5c7
+multifd_send(uint8_t id, uint64_t packet_num, uint32_t normal, uint32_t flags, uint32_t next_packet_size) "channel %u packet_num %" PRIu64 " normal pages %u flags 0x%x next packet size %u"
1be5c7
 multifd_send_error(uint8_t id) "channel %u"
1be5c7
 multifd_send_sync_main(long packet_num) "packet num %ld"
1be5c7
 multifd_send_sync_main_signal(uint8_t id) "channel %u"
1be5c7
 multifd_send_sync_main_wait(uint8_t id) "channel %u"
1be5c7
 multifd_send_terminate_threads(bool error) "error %d"
1be5c7
-multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t pages) "channel %u packets %" PRIu64 " pages %"  PRIu64
1be5c7
+multifd_send_thread_end(uint8_t id, uint64_t packets, uint64_t normal_pages) "channel %u packets %" PRIu64 " normal pages %"  PRIu64
1be5c7
 multifd_send_thread_start(uint8_t id) "%u"
1be5c7
 multifd_tls_outgoing_handshake_start(void *ioc, void *tioc, const char *hostname) "ioc=%p tioc=%p hostname=%s"
1be5c7
 multifd_tls_outgoing_handshake_error(void *ioc, const char *err) "ioc=%p err=%s"
1be5c7
-- 
1be5c7
2.35.3
1be5c7