From nobody Sun Feb 8 22:58:12 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1560916221; cv=none; d=zoho.com; s=zohoarc; b=Kp2JjOICT0FYGJhAHrnrj+0sphlD2Y+JzLtIL/weVHf6Qa1wf3ZbPEg+rpPxeIdRL3P+qdJa81nwnB6TL8MkEHEewIhXVkIMMgAHx5JGfnBZqJOjdB0HSAg781IMtMZXJQ9lA5VJeQRavLFH4dbXeZBbB6lTOxFNNCrYGpWJa2A= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1560916221; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=9UijMoVJuN52dvF2cAvBss9OFsgXP/zyzyXr5BO3/cY=; b=BEYyN0uTy57zAgn0WlsujDT6rvluej5nZ72iPoWJM4RkQ9ipAb7Jtd/VMZAKLBpkOwbme4u2CzeEATOlk7G5FiIRGlCKd6ffe3MyGQasGsMO/IomaBkX+UlhYq36Uk28PtVbeioDpNkz5URvcVLrQWmyNBaAJzcKw1yCl5CoN+A= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1560916221885272.3892893623838; Tue, 18 Jun 2019 20:50:21 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 33BD9356E4; Wed, 19 Jun 2019 03:50:20 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 058B019C69; Wed, 19 Jun 2019 03:50:19 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 9F8611806B1A; Wed, 19 Jun 2019 03:50:17 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x5J3m88b017812 for ; Tue, 18 Jun 2019 23:48:08 -0400 Received: by smtp.corp.redhat.com (Postfix) id 92D557DFF3; Wed, 19 Jun 2019 03:48:08 +0000 (UTC) Received: from blue.redhat.com (ovpn-116-44.phx2.redhat.com [10.3.116.44]) by smtp.corp.redhat.com (Postfix) with ESMTP id 584757F481 for ; Wed, 19 Jun 2019 03:48:08 +0000 (UTC) From: Eric Blake To: libvir-list@redhat.com Date: Tue, 18 Jun 2019 22:47:54 -0500 Message-Id: <20190619034754.2708-14-eblake@redhat.com> In-Reply-To: <20190619034754.2708-1-eblake@redhat.com> References: <20190619034754.2708-1-eblake@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 13/13] backup: qemu: Implement VIR_DOMAIN_CHECKPOINT_XML_SIZE flag X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Wed, 19 Jun 2019 03:50:20 +0000 (UTC) Content-Type: text/plain; charset="utf-8" Once a checkpoint has been created, it is desirable to estimate the size of the disk delta that is represented between the checkpoint and the current operation. To do this, we have to scrape information out of QMP query-block on a request from the user. --- src/qemu/qemu_monitor.h | 4 ++ src/qemu/qemu_monitor_json.h | 3 ++ src/qemu/qemu_driver.c | 56 +++++++++++++++++++++++++- src/qemu/qemu_monitor.c | 11 ++++++ src/qemu/qemu_monitor_json.c | 76 ++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a19d6069c6..ac9726af39 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -25,6 +25,7 @@ # include "internal.h" # include "domain_conf.h" +# include "checkpoint_conf.h" # include "virbitmap.h" # include "virhash.h" # include "virjson.h" @@ -630,6 +631,9 @@ int qemuMonitorBlockStatsUpdateCapacity(qemuMonitorPtr = mon, int qemuMonitorBlockStatsUpdateCapacityBlockdev(qemuMonitorPtr mon, virHashTablePtr stats) ATTRIBUTE_NONNULL(2); +int qemuMonitorUpdateCheckpointSize(qemuMonitorPtr mon, + virDomainCheckpointDefPtr chk) + ATTRIBUTE_NONNULL(2); int qemuMonitorBlockResize(qemuMonitorPtr mon, const char *device, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 2a881fbddd..aa68b35003 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -98,6 +98,9 @@ int qemuMonitorJSONBlockResize(qemuMonitorPtr mon, const char *nodename, unsigned long long size); +int qemuMonitorJSONUpdateCheckpointSize(qemuMonitorPtr mon, + virDomainCheckpointDefPtr chk); + int qemuMonitorJSONSetPassword(qemuMonitorPtr mon, const char *protocol, const char *password, diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 0cdb2dd1e2..585a0203eb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -17384,10 +17384,14 @@ qemuDomainCheckpointGetXMLDesc(virDomainCheckpoin= tPtr checkpoint, virDomainObjPtr vm =3D NULL; char *xml =3D NULL; virDomainMomentObjPtr chk =3D NULL; + qemuDomainObjPrivatePtr priv; + int rc; + size_t i; virDomainCheckpointDefPtr chkdef; virCheckFlags(VIR_DOMAIN_CHECKPOINT_XML_SECURE | - VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN, NULL); + VIR_DOMAIN_CHECKPOINT_XML_NO_DOMAIN | + VIR_DOMAIN_CHECKPOINT_XML_SIZE, NULL); if (!(vm =3D qemuDomObjFromCheckpoint(checkpoint))) return NULL; @@ -17399,9 +17403,59 @@ qemuDomainCheckpointGetXMLDesc(virDomainCheckpoint= Ptr checkpoint, goto cleanup; chkdef =3D virDomainCheckpointObjGetDef(chk); + if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE) { + /* TODO: for non-current checkpoint, this requires a QMP sequence = per + disk, since the stat of one bitmap in isolation is too low, + and merely adding bitmap sizes may be too high: + block-dirty-bitmap-create tmp + for each bitmap from checkpoint to current: + add bitmap to src_list + block-dirty-bitmap-merge dst=3Dtmp src_list + query-block and read tmp size + block-dirty-bitmap-remove tmp + So for now, go with simpler query-blocks only for current. + */ + if (virDomainCheckpointGetCurrent(vm->checkpoints) !=3D chk) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, + _("cannot compute size for non-current checkpoi= nt '%s'"), + checkpoint->name); + goto cleanup; + } + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) + goto cleanup; + + if (virDomainObjCheckActive(vm) < 0) + goto endjob; + + if (qemuBlockNodeNamesDetect(driver, vm, QEMU_ASYNC_JOB_NONE) < 0) + goto endjob; + + /* TODO: Shouldn't need to recompute node names. */ + for (i =3D 0; i < chkdef->ndisks; i++) { + virDomainCheckpointDiskDef *disk =3D &chkdef->disks[i]; + + if (disk->type !=3D VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP) + continue; + VIR_FREE(chk->def->dom->disks[disk->idx]->src->nodeformat); + if (VIR_STRDUP(chk->def->dom->disks[disk->idx]->src->nodeforma= t, + qemuBlockNodeLookup(vm, disk->name)) < 0) + goto endjob; + } + + priv =3D vm->privateData; + qemuDomainObjEnterMonitor(driver, vm); + rc =3D qemuMonitorUpdateCheckpointSize(priv->mon, chkdef); + if (qemuDomainObjExitMonitor(driver, vm) < 0) + goto endjob; + if (rc < 0) + goto endjob; + } + xml =3D virDomainCheckpointDefFormat(chkdef, driver->caps, driver->xml= opt, flags); + endjob: if (flags & VIR_DOMAIN_CHECKPOINT_XML_SIZE) qemuDomainObjEndJob(driver, vm); diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index d9d076633d..ee3dce87ae 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2342,6 +2342,17 @@ qemuMonitorBlockStatsUpdateCapacityBlockdev(qemuMoni= torPtr mon, return qemuMonitorJSONBlockStatsUpdateCapacityBlockdev(mon, stats); } +/* Updates "chk" to fill in size of the associated bitmap */ +int qemuMonitorUpdateCheckpointSize(qemuMonitorPtr mon, + virDomainCheckpointDefPtr chk) +{ + VIR_DEBUG("chk=3D%p", chk); + + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONUpdateCheckpointSize(mon, chk); +} + int qemuMonitorBlockResize(qemuMonitorPtr mon, const char *device, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 2dcd65d86f..4c232105c2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -2760,6 +2760,82 @@ int qemuMonitorJSONBlockResize(qemuMonitorPtr mon, return ret; } +int qemuMonitorJSONUpdateCheckpointSize(qemuMonitorPtr mon, + virDomainCheckpointDefPtr chk) +{ + int ret =3D -1; + size_t i, j; + virJSONValuePtr devices; + + if (!(devices =3D qemuMonitorJSONQueryBlock(mon))) + return -1; + + for (i =3D 0; i < virJSONValueArraySize(devices); i++) { + virJSONValuePtr dev =3D virJSONValueArrayGet(devices, i); + virJSONValuePtr inserted; + virJSONValuePtr bitmaps =3D NULL; + const char *node; + virDomainCheckpointDiskDefPtr disk; + + if (!(dev =3D qemuMonitorJSONGetBlockDev(devices, i))) + goto cleanup; + + if (!(inserted =3D virJSONValueObjectGetObject(dev, "inserted"))) + continue; + if (!(node =3D virJSONValueObjectGetString(inserted, "node-name"))= ) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("query-block device entry was not in expected= format")); + goto cleanup; + } + + for (j =3D 0; j < chk->ndisks; j++) { + disk =3D &chk->disks[j]; + if (disk->type !=3D VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP) + continue; + if (STREQ(chk->parent.dom->disks[disk->idx]->src->nodeformat, = node)) + break; + } + if (j =3D=3D chk->ndisks) { + VIR_DEBUG("query-block did not find node %s", node); + continue; + } + if (!(bitmaps =3D virJSONValueObjectGetArray(dev, "dirty-bitmaps")= )) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("disk %s dirty bitmaps missing"), disk->name); + goto cleanup; + } + for (j =3D 0; j < virJSONValueArraySize(bitmaps); j++) { + virJSONValuePtr map =3D virJSONValueArrayGet(bitmaps, j); + const char *name; + + if (!(name =3D virJSONValueObjectGetString(map, "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("dirty bitmaps entry was not in expected form= at")); + goto cleanup; + } + if (STRNEQ(name, disk->bitmap)) + continue; + if (virJSONValueObjectGetNumberUlong(map, "count", &disk->size= ) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("invalid bitmap count")); + goto cleanup; + } + break; + } + if (j =3D=3D virJSONValueArraySize(bitmaps)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("disk %s dirty bitmap info missing"), disk->n= ame); + goto cleanup; + } + } + + ret =3D 0; + + cleanup: + virJSONValueFree(devices); + return ret; +} + int qemuMonitorJSONSetPassword(qemuMonitorPtr mon, const char *protocol, --=20 2.20.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list