29b115
From 5ea59b17866add54e5ae8c76d3cb472c67e1fa91 Mon Sep 17 00:00:00 2001
29b115
From: Thomas Huth <thuth@redhat.com>
29b115
Date: Tue, 2 Aug 2022 08:19:49 +0200
29b115
Subject: [PATCH 32/32] Revert "migration: Simplify unqueue_page()"
29b115
29b115
RH-Author: Thomas Huth <thuth@redhat.com>
29b115
RH-MergeRequest: 112: Fix postcopy migration on s390x
29b115
RH-Commit: [2/2] 3913c9ed3f27f4b66245913da29d0c46db0c6567 (thuth/qemu-kvm-cs9)
29b115
RH-Bugzilla: 2099934
29b115
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
29b115
RH-Acked-by: Cornelia Huck <cohuck@redhat.com>
29b115
RH-Acked-by: David Hildenbrand <david@redhat.com>
29b115
RH-Acked-by: Peter Xu <peterx@redhat.com>
29b115
29b115
This reverts commit cfd66f30fb0f735df06ff4220e5000290a43dad3.
29b115
29b115
The simplification of unqueue_page() introduced a bug that sometimes
29b115
breaks migration on s390x hosts.
29b115
29b115
The problem is not fully understood yet, but since we are already in
29b115
the freeze for QEMU 7.1 and we need something working there, let's
29b115
revert this patch for the upcoming release. The optimization can be
29b115
redone later again in a proper way if necessary.
29b115
29b115
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2099934
29b115
Signed-off-by: Thomas Huth <thuth@redhat.com>
29b115
Message-Id: <20220802061949.331576-1-thuth@redhat.com>
29b115
Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
29b115
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
29b115
(cherry picked from commit 777f53c75983dd10756f5dbfc8af50fe11da81c1)
29b115
Conflicts:
29b115
	migration/trace-events
29b115
	(trivial contextual conflict)
29b115
Signed-off-by: Thomas Huth <thuth@redhat.com>
29b115
---
29b115
 migration/ram.c        | 37 ++++++++++++++++++++++++++-----------
29b115
 migration/trace-events |  3 ++-
29b115
 2 files changed, 28 insertions(+), 12 deletions(-)
29b115
29b115
diff --git a/migration/ram.c b/migration/ram.c
29b115
index fb6db54642..ee40e4a718 100644
29b115
--- a/migration/ram.c
29b115
+++ b/migration/ram.c
29b115
@@ -1548,7 +1548,6 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset)
29b115
 {
29b115
     struct RAMSrcPageRequest *entry;
29b115
     RAMBlock *block = NULL;
29b115
-    size_t page_size;
29b115
 
29b115
     if (!postcopy_has_request(rs)) {
29b115
         return NULL;
29b115
@@ -1565,13 +1564,10 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset)
29b115
     entry = QSIMPLEQ_FIRST(&rs->src_page_requests);
29b115
     block = entry->rb;
29b115
     *offset = entry->offset;
29b115
-    page_size = qemu_ram_pagesize(block);
29b115
-    /* Each page request should only be multiple page size of the ramblock */
29b115
-    assert((entry->len % page_size) == 0);
29b115
 
29b115
-    if (entry->len > page_size) {
29b115
-        entry->len -= page_size;
29b115
-        entry->offset += page_size;
29b115
+    if (entry->len > TARGET_PAGE_SIZE) {
29b115
+        entry->len -= TARGET_PAGE_SIZE;
29b115
+        entry->offset += TARGET_PAGE_SIZE;
29b115
     } else {
29b115
         memory_region_unref(block->mr);
29b115
         QSIMPLEQ_REMOVE_HEAD(&rs->src_page_requests, next_req);
29b115
@@ -1579,9 +1575,6 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset)
29b115
         migration_consume_urgent_request();
29b115
     }
29b115
 
29b115
-    trace_unqueue_page(block->idstr, *offset,
29b115
-                       test_bit((*offset >> TARGET_PAGE_BITS), block->bmap));
29b115
-
29b115
     return block;
29b115
 }
29b115
 
29b115
@@ -1956,8 +1949,30 @@ static bool get_queued_page(RAMState *rs, PageSearchStatus *pss)
29b115
 {
29b115
     RAMBlock  *block;
29b115
     ram_addr_t offset;
29b115
+    bool dirty;
29b115
+
29b115
+    do {
29b115
+        block = unqueue_page(rs, &offset);
29b115
+        /*
29b115
+         * We're sending this page, and since it's postcopy nothing else
29b115
+         * will dirty it, and we must make sure it doesn't get sent again
29b115
+         * even if this queue request was received after the background
29b115
+         * search already sent it.
29b115
+         */
29b115
+        if (block) {
29b115
+            unsigned long page;
29b115
+
29b115
+            page = offset >> TARGET_PAGE_BITS;
29b115
+            dirty = test_bit(page, block->bmap);
29b115
+            if (!dirty) {
29b115
+                trace_get_queued_page_not_dirty(block->idstr, (uint64_t)offset,
29b115
+                                                page);
29b115
+            } else {
29b115
+                trace_get_queued_page(block->idstr, (uint64_t)offset, page);
29b115
+            }
29b115
+        }
29b115
 
29b115
-    block = unqueue_page(rs, &offset);
29b115
+    } while (block && !dirty);
29b115
 
29b115
     if (!block) {
29b115
         /*
29b115
diff --git a/migration/trace-events b/migration/trace-events
29b115
index 1aec580e92..09d61ed1f4 100644
29b115
--- a/migration/trace-events
29b115
+++ b/migration/trace-events
29b115
@@ -85,6 +85,8 @@ put_qlist_end(const char *field_name, const char *vmsd_name) "%s(%s)"
29b115
 qemu_file_fclose(void) ""
29b115
 
29b115
 # ram.c
29b115
+get_queued_page(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx"
29b115
+get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/0x%" PRIx64 " page_abs=0x%lx"
29b115
 migration_bitmap_sync_start(void) ""
29b115
 migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
29b115
 migration_bitmap_clear_dirty(char *str, uint64_t start, uint64_t size, unsigned long page) "rb %s start 0x%"PRIx64" size 0x%"PRIx64" page 0x%lx"
29b115
@@ -110,7 +112,6 @@ ram_save_iterate_big_wait(uint64_t milliconds, int iterations) "big wait: %" PRI
29b115
 ram_load_complete(int ret, uint64_t seq_iter) "exit_code %d seq iteration %" PRIu64
29b115
 ram_write_tracking_ramblock_start(const char *block_id, size_t page_size, void *addr, size_t length) "%s: page_size: %zu addr: %p length: %zu"
29b115
 ram_write_tracking_ramblock_stop(const char *block_id, size_t page_size, void *addr, size_t length) "%s: page_size: %zu addr: %p length: %zu"
29b115
-unqueue_page(char *block, uint64_t offset, bool dirty) "ramblock '%s' offset 0x%"PRIx64" dirty %d"
29b115
 
29b115
 # multifd.c
29b115
 multifd_new_send_channel_async(uint8_t id) "channel %u"
29b115
-- 
29b115
2.31.1
29b115