Blob Blame History Raw
From d05a64ddd01fa11fed479a2e249ed46c93207f9e Mon Sep 17 00:00:00 2001
From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>
Date: Thu, 18 May 2017 11:17:26 +0200
Subject: [PATCH 19/27] migration: Fix non-multiple of page size migration

RH-Author: Dr. David Alan Gilbert <dgilbert@redhat.com>
Message-id: <20170518111727.7433-2-dgilbert@redhat.com>
Patchwork-id: 75314
O-Subject: [RHEL-7.4 qemu-kvm-rhev PATCH 1/2] migration: Fix non-multiple of page size migration
Bugzilla: 1449037
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Peter Xu <peterx@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

From: "Dr. David Alan Gilbert" <dgilbert@redhat.com>

Unfortunately it's legal to create a VM with a RAM size that's
not a multiple of the underlying host page or huge page size.
Recently I'd changed things to always send host sized pages,
and that breaks if we have say a 1025MB guest on 2MB hugepages.

Unfortunately we can't just make that illegal since it would break
migration from/to existing oddly configured VMs.

Symptom: qemu-system-x86_64: Illegal RAM offset 40100000
     as it transmits the fraction of the hugepage after the end
     of the RAMBlock (may also cause a crash on the source
     - possibly due to clearing bits after the bitmap)

Reported-by:  Yumei Huang <yuhuang@redhat.com>
Signed-off-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
Conflicts
     Cleanup in HEAD got rid of pss->offset; so use pss->offset
     in our 2.9 world

Upstream URL:
http://lists.nongnu.org/archive/html/qemu-devel/2017-05/msg04392.html
Upstream Message-Id: <20170518172453.32599-2-quintela@redhat.com>

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 migration/ram.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/migration/ram.c b/migration/ram.c
index de1e0a3..3661bc8 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1304,6 +1304,13 @@ static int ram_save_target_page(MigrationState *ms, QEMUFile *f,
  *                     block.
  *
  * Returns: Number of pages written.
+ * Starting at *offset send pages up to the end of the current host
+ * page. It's valid for the initial offset to point into the middle of
+ * a host page in which case the remainder of the hostpage is sent.
+ * Only dirty target pages are sent. Note that the host page size may
+ * be a huge page for this block.
+ * The saving stops at the boundary of the used_length of the block
+ * if the RAMBlock isn't a multiple of the host page size.
  *
  * @f: QEMUFile where to send the data
  * @block: pointer to block that contains the page we want to send
@@ -1332,7 +1339,8 @@ static int ram_save_host_page(MigrationState *ms, QEMUFile *f,
         pages += tmppages;
         pss->offset += TARGET_PAGE_SIZE;
         dirty_ram_abs += TARGET_PAGE_SIZE;
-    } while (pss->offset & (pagesize - 1));
+    } while ((pss->offset & (pagesize - 1)) &&
+             offset_in_ramblock(pss->block, pss->offset));
 
     /* The offset we leave with is the last one we looked at */
     pss->offset -= TARGET_PAGE_SIZE;
-- 
1.8.3.1