[libvirt] [PATCH v8 15/21] backup: Add new qemu monitor interactions
Peter Krempa
pkrempa at redhat.com
Fri Apr 26 12:02:56 UTC 2019
On Wed, Apr 17, 2019 at 09:09:15 -0500, Eric Blake wrote:
> Add some monitor commands to be used during backup/checkpoint
> operations:
> - another facet to query-block for learning bitmap size
> - new export and bitmap parameters to nbd-server-add
> - new block-dirty-bitmap-{add,enable,disable,merge} functions
>
> Also add two capabilities for testing that they are supported;
> using block-dirty-bitmap-merge as the generic witness of checkpoint
> support (since all of the functionalities were added in the same
> qemu 4.0 release), and the bitmap parameter to nbd-server-add for
> pull-mode backup support. Even though both capabilities are
> likely to be present or absent together (that is, it is unlikely
> to encounter a qemu that backports only one of the two), it still
> makes sense to keep two capabilities as the two uses are
> orthogonal (full backups don't require checkpoints, push mode
> backups don't require NBD bitmap support, and checkpoints can
> be used for more than just incremental backups).
I'd suggest you split the capabilities, new QMP APIs, changes to
existing QMP apis and block job handling changes each into a separate
commit.
>
> Signed-off-by: Eric Blake <eblake at redhat.com>
> ---
> src/qemu/qemu_capabilities.h | 2 +
> src/qemu/qemu_monitor.h | 21 +-
> src/qemu/qemu_monitor_json.h | 19 +-
> src/qemu/qemu_capabilities.c | 4 +
> src/qemu/qemu_migration.c | 2 +-
> src/qemu/qemu_monitor.c | 65 +++++-
> src/qemu/qemu_monitor_json.c | 199 +++++++++++++++++-
> .../caps_4.0.0.riscv32.xml | 2 +
> .../caps_4.0.0.riscv64.xml | 2 +
> .../caps_4.0.0.x86_64.xml | 2 +
> tests/qemumonitorjsontest.c | 2 +-
> 11 files changed, 312 insertions(+), 8 deletions(-)
[...]
> diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
> index 1237c14a84..aaf8f1df26 100644
> --- a/src/qemu/qemu_monitor.h
> +++ b/src/qemu/qemu_monitor.h
[...]
> @@ -646,6 +650,19 @@ int qemuMonitorSetBalloon(qemuMonitorPtr mon,
> unsigned long long newmem);
> int qemuMonitorSetCPU(qemuMonitorPtr mon, int cpu, bool online);
>
> +int qemuMonitorAddBitmap(qemuMonitorPtr mon, const char *node,
> + const char *bitmap, bool persistent)
Usually it's one argument per line.
> + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
> +int qemuMonitorEnableBitmap(qemuMonitorPtr mon, const char *node,
> + const char *bitmap)
> + ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
> +int qemuMonitorMergeBitmaps(qemuMonitorPtr mon, const char *node,
> + const char *dst, virJSONValuePtr *src)
[...]
> diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
> index 694ed90622..9b4a5c01ab 100644
> --- a/src/qemu/qemu_monitor.c
> +++ b/src/qemu/qemu_monitor.c
[...]
> @@ -4471,3 +4486,47 @@ qemuMonitorGetPRManagerInfo(qemuMonitorPtr mon,
> virHashFree(info);
> return ret;
> }
> +
> +int
> +qemuMonitorAddBitmap(qemuMonitorPtr mon, const char *node,
> + const char *bitmap, bool persistent)
One argument per line.
> +{
> + VIR_DEBUG("node=%s bitmap=%s persistent=%d", node, bitmap, persistent);
Should 'node' be declared as NONNULL? it's used without NULLSTR here.
> +
> + QEMU_CHECK_MONITOR(mon);
> +
> + return qemuMonitorJSONAddBitmap(mon, node, bitmap, persistent);
> +}
> +
> +int
> +qemuMonitorEnableBitmap(qemuMonitorPtr mon, const char *node,
> + const char *bitmap)
> +{
> + VIR_DEBUG("node=%s bitmap=%s", node, bitmap);
> +
> + QEMU_CHECK_MONITOR(mon);
> +
> + return qemuMonitorJSONEnableBitmap(mon, node, bitmap);
> +}
> +
> +int
> +qemuMonitorMergeBitmaps(qemuMonitorPtr mon, const char *node,
> + const char *dst, virJSONValuePtr *src)
> +{
> + VIR_DEBUG("node=%s dst=%s src=%p", node, dst, *src);
Logging 'src' as pointer does not have much value. I'd just drop it as
it does not have a simple way to access it.
> +
> + QEMU_CHECK_MONITOR(mon);
> +
> + return qemuMonitorJSONMergeBitmaps(mon, node, dst, src);
> +}
> +
> +int
> +qemuMonitorDeleteBitmap(qemuMonitorPtr mon, const char *node,
> + const char *bitmap)
> +{
> + VIR_DEBUG("node=%s bitmap=%s", node, bitmap);
> +
> + QEMU_CHECK_MONITOR(mon);
> +
> + return qemuMonitorJSONDeleteBitmap(mon, node, bitmap);
> +}
> diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
> index fc2d193ae2..801433826f 100644
> --- a/src/qemu/qemu_monitor_json.c
> +++ b/src/qemu/qemu_monitor_json.c
> @@ -1011,6 +1011,8 @@ qemuMonitorJSONHandleBlockJobImpl(qemuMonitorPtr mon,
> type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
> else if (STREQ(type_str, "mirror"))
> type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
> + else if (STREQ(type_str, "backup"))
> + type = VIR_DOMAIN_BLOCK_JOB_TYPE_BACKUP;
As I've pointed out in previous responses, we need to clarify whether
the backup job is a blockjob, general job or we need a new job API in
libvirt.
>
> switch ((virConnectDomainEventBlockJobStatus) event) {
> case VIR_DOMAIN_BLOCK_JOB_COMPLETED:
> @@ -2755,6 +2757,82 @@ int qemuMonitorJSONBlockResize(qemuMonitorPtr mon,
> return ret;
> }
>
> +int qemuMonitorJSONUpdateCheckpointSize(qemuMonitorPtr mon,
> + virDomainCheckpointDefPtr chk)
> +{
> + int ret = -1;
> + size_t i, j;
> + virJSONValuePtr devices;
> +
> + if (!(devices = qemuMonitorJSONQueryBlock(mon)))
> + return -1;
> +
> + for (i = 0; i < virJSONValueArraySize(devices); i++) {
> + virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
> + virJSONValuePtr inserted;
> + virJSONValuePtr bitmaps = NULL;
> + const char *node;
> + virDomainCheckpointDiskDefPtr disk;
> +
> + if (!(dev = qemuMonitorJSONGetBlockDev(devices, i)))
> + goto cleanup;
> +
> + if (!(inserted = virJSONValueObjectGetObject(dev, "inserted")))
> + continue;
> + if (!(node = virJSONValueObjectGetString(inserted, "node-name"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("query-block device entry was not in expected format"));
> + goto cleanup;
> + }
> +
> + for (j = 0; j < chk->ndisks; j++) {
> + disk = &chk->disks[j];
> + if (disk->type != VIR_DOMAIN_CHECKPOINT_TYPE_BITMAP)
> + continue;
> + if (STREQ(chk->common.dom->disks[disk->idx]->src->nodeformat, node))
This will access stale data after you unplug a disk. Caching disk
indexes is a bad idea.
> + break;
> + }
> + if (j == chk->ndisks) {
> + VIR_DEBUG("query-block did not find node %s", node);
> + continue;
> + }
> + if (!(bitmaps = virJSONValueObjectGetArray(dev, "dirty-bitmaps"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("disk %s dirty bitmaps missing"), disk->name);
> + goto cleanup;
> + }
> + for (j = 0; j < virJSONValueArraySize(bitmaps); j++) {
> + virJSONValuePtr map = virJSONValueArrayGet(bitmaps, j);
> + const char *name;
> +
> + if (!(name = virJSONValueObjectGetString(map, "name"))) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("dirty bitmaps entry was not in expected format"));
> + 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 == virJSONValueArraySize(bitmaps)) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("disk %s dirty bitmap info missing"), disk->name);
> + goto cleanup;
> + }
> + }
> +
> + ret = 0;
> +
> + cleanup:
> + virJSONValueFree(devices);
> + return ret;
> +}
> +
>
> int qemuMonitorJSONSetPassword(qemuMonitorPtr mon,
> const char *protocol,
> @@ -4706,6 +4784,8 @@ qemuMonitorJSONParseBlockJobInfo(virHashTablePtr blockJobs,
> info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT;
> else if (STREQ(type, "mirror"))
> info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_COPY;
> + else if (STREQ(type, "backup"))
> + info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_BACKUP;
> else
> info->type = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN;
>
[...]
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20190426/21afa9cc/attachment-0001.sig>
More information about the libvir-list
mailing list