Implement the QMP side of asking qemu what node name it assigned to an arbitrary top-level device node. Assumes that the caller will have already validated that the device is qcow2 backed by a block device, and that qemu auto-assigns node names. * src/qemu/qemu_monitor.h (qemuMonitorNodeNameLookup): New function. * src/qemu/qemu_monitor.c (qemuMonitorNodeNameLookup): Likewise. * src/qemu/qemu_monitor_json.h (qemuMonitorJSONNodeNameLookup): Likewise. * src/qemu/qemu_monitor_json.c (qemuMonitorJSONNodeNameLookup): Likewise. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- src/qemu/qemu_monitor.c | 15 ++++++++- src/qemu/qemu_monitor.h | 3 ++ src/qemu/qemu_monitor_json.c | 77 ++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 3 ++ 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2e9e2de..5612491 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3094,7 +3094,7 @@ qemuMonitorSupportsNodeNames(qemuMonitorPtr mon) } -/* Determine the name that qemu is using for tracking the backing +/* Determine the path name that qemu is using for tracking the backing * element TARGET within the chain starting at TOP. */ char * qemuMonitorDiskNameLookup(qemuMonitorPtr mon, @@ -3108,6 +3108,19 @@ qemuMonitorDiskNameLookup(qemuMonitorPtr mon, } +/* Determine the node name that qemu is using for tracking the raw + * file of the qcow2 protocol at DEVICE. */ +char * +qemuMonitorNodeNameLookup(qemuMonitorPtr mon, + const char *device) +{ + /* TODO - change signature to allow backing file lookups */ + QEMU_CHECK_MONITOR_JSON_NULL(mon); + + return qemuMonitorJSONNodeNameLookup(mon, device); +} + + /* Use the block-job-complete monitor command to pivot a block copy job. */ int qemuMonitorDrivePivot(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index e198c06..826835b 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -745,6 +745,9 @@ char *qemuMonitorDiskNameLookup(qemuMonitorPtr mon, virStorageSourcePtr top, virStorageSourcePtr target) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +char *qemuMonitorNodeNameLookup(qemuMonitorPtr mon, + const char *device) + ATTRIBUTE_NONNULL(2); int qemuMonitorArbitraryCommand(qemuMonitorPtr mon, const char *cmd, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index e4701aa..32b2719 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -3835,6 +3835,8 @@ qemuMonitorJSONDiskNameLookupOne(virJSONValuePtr image, } +/* Look up the image name that qemu is using for a member in a backing + * chain. */ char * qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon, const char *device, @@ -3900,6 +3902,81 @@ qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon, } +/* Look up the node name of the file underneath a qcow2 image. */ +char * +qemuMonitorJSONNodeNameLookup(qemuMonitorPtr mon, + const char *device) +{ + char *ret = NULL; + virJSONValuePtr cmd = NULL; + virJSONValuePtr reply = NULL; + virJSONValuePtr devices; + size_t i; + + cmd = qemuMonitorJSONMakeCommand("query-blockstats", NULL); + if (!cmd) + return NULL; + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + + if (!(devices = virJSONValueObjectGetArray(reply, "return"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("blockstats reply was missing device list")); + goto cleanup; + } + + for (i = 0; i < virJSONValueArraySize(devices); i++) { + virJSONValuePtr dev = virJSONValueArrayGet(devices, i); + virJSONValuePtr parent; + const char *thisdev; + const char *node; + + if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("blockstats entry was not in expected format")); + goto cleanup; + } + + if (!(thisdev = virJSONValueObjectGetString(dev, "device"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("blockstats entry was not in expected format")); + goto cleanup; + } + + if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX)) + thisdev += strlen(QEMU_DRIVE_HOST_PREFIX); + if (STRNEQ(thisdev, device)) + continue; + + if (!(parent = virJSONValueObjectGetObject(dev, "parent"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("blockstats device %s missing parent node"), + device); + goto cleanup; + } + + if (!(node = virJSONValueObjectGetString(parent, "node-name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("node name missing for device %s"), device); + goto cleanup; + } + ignore_value(VIR_STRDUP(ret, node)); + goto cleanup; + } + + /* If we get here, we didn't find the device. */ + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to find node name for device %s"), + device); + + cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + + return ret; +} + + /* Used only for capability probing. Assumes that fd set 0 is already * connected to /dev/null and that we have no existing nodes; we then * try to add the fd as a block device, and see if the new device has diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index a8ae411..f18295b 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -281,6 +281,9 @@ char *qemuMonitorJSONDiskNameLookup(qemuMonitorPtr mon, virStorageSourcePtr target) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) ATTRIBUTE_NONNULL(4); +char *qemuMonitorJSONNodeNameLookup(qemuMonitorPtr mon, + const char *device) + ATTRIBUTE_NONNULL(2); bool qemuMonitorJSONSupportsNodeNames(qemuMonitorPtr mon) ATTRIBUTE_NONNULL(1); -- 2.4.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list