
On Mon, Jun 22, 2015 at 17:06:42 -0600, Eric Blake wrote:
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@redhat.com> --- 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(-)
...
@@ -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);
Since this is yet another function that would call query-blockstats ...
+ 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);
... and works only on one device and thus needs to be re-called for every single disk I'd rather see us fold this code into qemuMonitorJSONGetOneBlockStatsInfo so that all the info can be returned via qemuMonitorJSONGetAllBlockStatsInfo. I'll post a series that kills qemuMonitorJSONGetBlockExtent since it's basically the same instance. Peter