From d400b8fb1868c5ef685c88e7de1fb7260434ad52 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Fri, 30 Mar 2012 14:45:48 -0600 Subject: [PATCH] conf: allow fuzz in XML with cur balloon > max Commit 1b1402b introduced a regression. Since older libvirt versions would silently round memory up (until the previous patch), but populated current memory based on querying the guest, it was possible to have dumpxml show cur > max by the amount of the rounding. For example, if a user requested 1048570 KiB memory (just shy of 1GiB), the qemu driver would actually run with 1048576 KiB, and libvirt 0.9.10 would output a current that was 6KiB larger than the maximum. Situations where this could have an impact include, but are not limited to, migration from old to new libvirt, managedsave in old libvirt and start in new libvirt, snapshot creation in old libvirt and revert in new libvirt - without this patch, the new libvirt would reject the VM because of the rounding discrepancy. Fix things by adding a fuzz factor, and silently clamp current down to maximum in that case, rather than failing to reparse XML for an existing VM. From a practical standpoint, this has no user impact: 'virsh dumpxml' will continue to query the running guest rather than rely on the incoming xml, which will see the currect current value, and even if clamping down occurs during parsing, it will be by at most the fuzz factor of a megabyte alignment, and rounded back up when passed back to the hypervisor. Meanwhile, we continue to reject cur > max if the difference is beyond the fuzz factor of nearest megabyte. But this is not a real change in behavior, since with 0.9.10, even though the parser allowed it, later in the processing stream we would reject it at the qemu layer; so rejecting it in the parser just moves error detection to a nicer place. * src/conf/domain_conf.c (virDomainDefParseXML): Don't reject existing XML. Based on a report by Zhou Peng. --- src/conf/domain_conf.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7ea57b9cef..c800160441 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -7769,10 +7769,21 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, goto error; if (def->mem.cur_balloon > def->mem.max_balloon) { - virDomainReportError(VIR_ERR_XML_ERROR, - _("current memory '%lluk' exceeds maximum '%lluk'"), - def->mem.cur_balloon, def->mem.max_balloon); - goto error; + /* Older libvirt could get into this situation due to + * rounding; if the discrepancy is less than 1MiB, we silently + * round down, otherwise we flag the issue. */ + if (VIR_DIV_UP(def->mem.cur_balloon, 1024) > + VIR_DIV_UP(def->mem.max_balloon, 1024)) { + virDomainReportError(VIR_ERR_XML_ERROR, + _("current memory '%lluk' exceeds " + "maximum '%lluk'"), + def->mem.cur_balloon, def->mem.max_balloon); + goto error; + } else { + VIR_DEBUG("Truncating current %lluk to maximum %lluk", + def->mem.cur_balloon, def->mem.max_balloon); + def->mem.cur_balloon = def->mem.max_balloon; + } } else if (def->mem.cur_balloon == 0) { def->mem.cur_balloon = def->mem.max_balloon; }