[libvirt] [PATCHv3 06/10] threshold: learn a node name for a given qcow2 disk

Eric Blake eblake at redhat.com
Mon Jun 22 23:06:42 UTC 2015


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 at 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(-)

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




More information about the libvir-list mailing list