]> xenbits.xensource.com Git - people/liuw/libxenctrl-split/libvirt.git/commitdiff
qemu: Refactor qemuMonitorGetBlockInfo
authorJiri Denemark <jdenemar@redhat.com>
Wed, 18 Jan 2012 21:01:30 +0000 (22:01 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Fri, 27 Jan 2012 12:07:56 +0000 (13:07 +0100)
QEMU always sends details about all available block devices as an answer
for "info block"/"query-block" command. On the other hand, our
qemuMonitorGetBlockInfo was made for a single block devices queries
only. Thus, when asking for multiple devices, we asked qemu multiple
times to always get the same answer from which different parts were
filtered. This patch makes qemuMonitorGetBlockInfo return a hash table
of all block devices, which may later be used for getting details about
specific devices.

src/qemu/qemu_hotplug.c
src/qemu/qemu_monitor.c
src/qemu/qemu_monitor.h
src/qemu/qemu_monitor_json.c
src/qemu/qemu_monitor_json.h
src/qemu/qemu_monitor_text.c
src/qemu/qemu_monitor_text.h

index 4b608397ac69ecd54afd7a40701f88a6a2ec7bc5..b4870beb11bd96084e0d3a63b1134cd60de7b1ad 100644 (file)
@@ -155,34 +155,38 @@ qemuDomainCheckEjectableMedia(struct qemud_driver *driver,
                              virDomainObjPtr vm)
 {
     qemuDomainObjPrivatePtr priv = vm->privateData;
+    virHashTablePtr table;
     int ret = -1;
     int i;
 
+    qemuDomainObjEnterMonitor(driver, vm);
+    table = qemuMonitorGetBlockInfo(priv->mon);
+    qemuDomainObjExitMonitor(driver, vm);
+
+    if (!table)
+        goto cleanup;
+
     for (i = 0; i < vm->def->ndisks; i++) {
         virDomainDiskDefPtr disk = vm->def->disks[i];
-        struct qemuDomainDiskInfo info;
+        struct qemuDomainDiskInfo *info;
 
         if (disk->device == VIR_DOMAIN_DISK_DEVICE_DISK ||
             disk->device == VIR_DOMAIN_DISK_DEVICE_LUN) {
                  continue;
         }
 
-        memset(&info, 0, sizeof(info));
-
-        qemuDomainObjEnterMonitor(driver, vm);
-        if (qemuMonitorGetBlockInfo(priv->mon, disk->info.alias, &info) < 0) {
-            qemuDomainObjExitMonitor(driver, vm);
+        info = qemuMonitorBlockInfoLookup(table, disk->info.alias);
+        if (!info)
             goto cleanup;
-        }
-        qemuDomainObjExitMonitor(driver, vm);
 
-        if (info.tray_open && disk->src)
+        if (info->tray_open && disk->src)
             VIR_FREE(disk->src);
     }
 
     ret = 0;
 
 cleanup:
+    virHashFree(table);
     return ret;
 }
 
index ad7e2a554d56dca0edbf77202c41b6a29cda5171..dda0521731d29c328ae57426f51436d5198ea817 100644 (file)
@@ -1227,24 +1227,51 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
     return ret;
 }
 
-int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
-                            const char *devname,
-                            struct qemuDomainDiskInfo *info)
+virHashTablePtr
+qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
 {
     int ret;
+    virHashTablePtr table;
+
+    VIR_DEBUG("mon=%p", mon);
 
-    VIR_DEBUG("mon=%p dev=%p info=%p", mon, devname, info);
     if (!mon) {
         qemuReportError(VIR_ERR_INVALID_ARG, "%s",
                         _("monitor must not be NULL"));
-        return -1;
+        return NULL;
     }
 
+    if (!(table = virHashCreate(32, (virHashDataFree) free)))
+        return NULL;
+
     if (mon->json)
-        ret = qemuMonitorJSONGetBlockInfo(mon, devname, info);
+        ret = qemuMonitorJSONGetBlockInfo(mon, table);
     else
-        ret = qemuMonitorTextGetBlockInfo(mon, devname, info);
-    return ret;
+        ret = qemuMonitorTextGetBlockInfo(mon, table);
+
+    if (ret < 0) {
+        virHashFree(table);
+        return NULL;
+    }
+
+    return table;
+}
+
+struct qemuDomainDiskInfo *
+qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
+                           const char *devname)
+{
+    struct qemuDomainDiskInfo *info;
+
+    VIR_DEBUG("blockInfo=%p dev=%s", blockInfo, NULLSTR(devname));
+
+    if (!(info = virHashLookup(blockInfo, devname))) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("cannot find info for device '%s'"),
+                        NULLSTR(devname));
+    }
+
+    return info;
 }
 
 int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
index 88ce303dd90d9441df41e69f0e641ec43f7628fd..a9471fe85e297b431893bd357b1f46d03f5b456b 100644 (file)
@@ -235,9 +235,12 @@ int qemuMonitorGetBalloonInfo(qemuMonitorPtr mon,
 int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
                               virDomainMemoryStatPtr stats,
                               unsigned int nr_stats);
-int qemuMonitorGetBlockInfo(qemuMonitorPtr mon,
-                            const char *devname,
-                            struct qemuDomainDiskInfo *info);
+
+virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
+struct qemuDomainDiskInfo *
+qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
+                           const char *devname);
+
 int qemuMonitorGetBlockStatsInfo(qemuMonitorPtr mon,
                                  const char *dev_name,
                                  long long *rd_req,
index 11fdc0d792c78b13f5fb4d7c8bb4898820ef034c..0bd9f462404ad052f1fc57c7ab2d67bacccc5244 100644 (file)
@@ -1357,11 +1357,9 @@ cleanup:
 
 
 int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
-                                const char *devname,
-                                struct qemuDomainDiskInfo *info)
+                                virHashTablePtr table)
 {
-    int ret = 0;
-    bool found = false;
+    int ret;
     int i;
 
     virJSONValuePtr cmd = qemuMonitorJSONMakeCommand("query-block",
@@ -1389,6 +1387,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
 
     for (i = 0; i < virJSONValueArraySize(devices); i++) {
         virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
+        struct qemuDomainDiskInfo *info;
         const char *thisdev;
 
         if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
@@ -1406,10 +1405,16 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
         if (STRPREFIX(thisdev, QEMU_DRIVE_HOST_PREFIX))
             thisdev += strlen(QEMU_DRIVE_HOST_PREFIX);
 
-        if (STRNEQ(thisdev, devname))
-            continue;
+        if (VIR_ALLOC(info) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        if (virHashAddEntry(table, thisdev, info) < 0) {
+            VIR_FREE(info);
+            goto cleanup;
+        }
 
-        found = true;
         if (virJSONValueObjectGetBoolean(dev, "removable", &info->removable) < 0) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR,
                             _("cannot read %s value"),
@@ -1429,15 +1434,6 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
          */
         ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
                                                   &info->tray_open));
-
-        break;
-    }
-
-    if (!found) {
-        qemuReportError(VIR_ERR_INTERNAL_ERROR,
-                        _("cannot find info for device '%s'"),
-                        devname);
-        goto cleanup;
     }
 
     ret = 0;
index 5991790b8266c791e9507090d2e95f791c17153a..d221e59661bce17e1ccf24164d9b155f7ff5db1a 100644 (file)
@@ -63,8 +63,7 @@ int qemuMonitorJSONGetMemoryStats(qemuMonitorPtr mon,
                                   virDomainMemoryStatPtr stats,
                                   unsigned int nr_stats);
 int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
-                                const char *devname,
-                                struct qemuDomainDiskInfo *info);
+                                virHashTablePtr table);
 int qemuMonitorJSONGetBlockStatsInfo(qemuMonitorPtr mon,
                                      const char *dev_name,
                                      long long *rd_req,
index 2c68be8efd1a67050ce8a4e7058dd82b14fbb5a8..a33d192c2db9cea8a06bfdeb66438555b98cabb0 100644 (file)
@@ -772,14 +772,14 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
 
 
 int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
-                                const char *devname,
-                                struct qemuDomainDiskInfo *info)
+                                virHashTablePtr table)
 {
+    struct qemuDomainDiskInfo *info;
     char *reply = NULL;
     int ret = -1;
     char *dummy;
-    const char *p, *eol;
-    int devnamelen = strlen(devname);
+    char *p, *eol;
+    char *dev;
     int tmp;
 
     if (qemuMonitorHMPCommand(mon, "info block", &reply) < 0) {
@@ -805,16 +805,22 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
         if (STRPREFIX(p, QEMU_DRIVE_HOST_PREFIX))
             p += strlen(QEMU_DRIVE_HOST_PREFIX);
 
-        if (STREQLEN(p, devname, devnamelen) &&
-            p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
+        eol = strchr(p, '\n');
+        if (!eol)
+            eol = p + strlen(p) - 1;
 
-            eol = strchr(p, '\n');
-            if (!eol)
-                eol = p + strlen(p);
+        dev = p;
+        p = strchr(p, ':');
+        if (p && p < eol && *(p + 1) == ' ') {
+            if (VIR_ALLOC(info) < 0) {
+                virReportOOMError();
+                goto cleanup;
+            }
 
-            p += devnamelen + 2; /* Skip to first label. */
+            *p = '\0';
+            p += 2;
 
-            while (*p) {
+            while (p < eol) {
                 if (STRPREFIX(p, "removable=")) {
                     p += strlen("removable=");
                     if (virStrToLong_i(p, &dummy, 10, &tmp) == -1)
@@ -839,24 +845,25 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
 
                 /* skip to next label */
                 p = strchr(p, ' ');
-                if (!p || p >= eol) break;
+                if (!p)
+                    break;
                 p++;
             }
 
-            ret = 0;
-            goto cleanup;
+            if (virHashAddEntry(table, dev, info) < 0)
+                goto cleanup;
+            else
+                info = NULL;
         }
 
-        /* skip to next line */
-        p = strchr(p, '\n');
-        if (!p) break;
-        p++;
+        /* skip to the next line */
+        p = eol + 1;
     }
 
-    qemuReportError(VIR_ERR_INVALID_ARG,
-                    _("no info for device '%s'"), devname);
+    ret = 0;
 
 cleanup:
+    VIR_FREE(info);
     VIR_FREE(reply);
     return ret;
 }
index 47a946d292351fbb63784a755362febed56fc6af..050c30e418cabd63ead438739d605d58aedc2581 100644 (file)
@@ -59,8 +59,7 @@ int qemuMonitorTextGetMemoryStats(qemuMonitorPtr mon,
                                   virDomainMemoryStatPtr stats,
                                   unsigned int nr_stats);
 int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
-                                const char *devname,
-                                struct qemuDomainDiskInfo *info);
+                                virHashTablePtr table);
 int qemuMonitorTextGetBlockStatsInfo(qemuMonitorPtr mon,
                                      const char *dev_name,
                                      long long *rd_req,