From d05a64ddd01fa11fed479a2e249ed46c93207f9e Mon Sep 17 00:00:00 2001 From: "Dr. David Alan Gilbert" 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 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 RH-Acked-by: Peter Xu RH-Acked-by: Laszlo Ersek From: "Dr. David Alan Gilbert" 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 Signed-off-by: Dr. David Alan Gilbert 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 --- 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