[libvirt] [PATCH 11/27] Add API for issuing 'info blockstats' command

Daniel P. Berrange berrange at redhat.com
Thu Sep 24 15:00:13 UTC 2009


* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h: Add a new
  qemuMonitorGetBlockStatsInfo() command
* src/qemu/qemu_driver.c: Remove directly use of blockstats in
  favour of calling qemuMonitorGetBlockStatsInfo()
---
 src/qemu/qemu_driver.c       |   95 +++----------------------------------
 src/qemu/qemu_monitor_text.c |  105 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor_text.h |    8 +++
 3 files changed, 121 insertions(+), 87 deletions(-)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 9c09024..f95c473 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5958,10 +5958,7 @@ qemudDomainBlockStats (virDomainPtr dom,
                        struct _virDomainBlockStats *stats)
 {
     struct qemud_driver *driver = dom->conn->privateData;
-    char *dummy, *info = NULL;
-    const char *p, *eol;
     const char *qemu_dev_name = NULL;
-    size_t len;
     int i, ret = -1;
     virDomainObjPtr vm;
     virDomainDiskDefPtr disk = NULL;
@@ -5998,95 +5995,19 @@ qemudDomainBlockStats (virDomainPtr dom,
     qemu_dev_name = qemudDiskDeviceName(dom->conn, disk);
     if (!qemu_dev_name)
         goto cleanup;
-    len = strlen (qemu_dev_name);
 
-    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
-        qemudReportError (dom->conn, dom, NULL, VIR_ERR_OPERATION_FAILED,
-                          "%s", _("'info blockstats' command failed"));
-        goto cleanup;
-    }
-    DEBUG ("%s: info blockstats reply: %s", vm->def->name, info);
-
-    /* If the command isn't supported then qemu prints the supported
-     * info commands, so the output starts "info ".  Since this is
-     * unlikely to be the name of a block device, we can use this
-     * to detect if qemu supports the command.
-     */
-    if (strstr(info, "\ninfo ")) {
-        qemudReportError (dom->conn, dom, NULL, VIR_ERR_NO_SUPPORT,
-                          "%s",
-                          _("'info blockstats' not supported by this qemu"));
+    if (qemuMonitorGetBlockStatsInfo(vm, qemu_dev_name,
+                                     &stats->rd_req,
+                                     &stats->rd_bytes,
+                                     &stats->wr_req,
+                                     &stats->wr_bytes,
+                                     &stats->errs) < 0)
         goto cleanup;
-    }
-
-    stats->rd_req = -1;
-    stats->rd_bytes = -1;
-    stats->wr_req = -1;
-    stats->wr_bytes = -1;
-    stats->errs = -1;
-
-    /* The output format for both qemu & KVM is:
-     *   blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
-     *   (repeated for each block device)
-     * where '%' is a 64 bit number.
-     */
-    p = info;
-
-    while (*p) {
-        if (STREQLEN (p, qemu_dev_name, len)
-            && p[len] == ':' && p[len+1] == ' ') {
-
-            eol = strchr (p, '\n');
-            if (!eol)
-                eol = p + strlen (p);
-
-            p += len+2;         /* Skip to first label. */
-
-            while (*p) {
-                if (STRPREFIX (p, "rd_bytes=")) {
-                    p += 9;
-                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_bytes) == -1)
-                        DEBUG ("%s: error reading rd_bytes: %s",
-                               vm->def->name, p);
-                } else if (STRPREFIX (p, "wr_bytes=")) {
-                    p += 9;
-                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_bytes) == -1)
-                        DEBUG ("%s: error reading wr_bytes: %s",
-                               vm->def->name, p);
-                } else if (STRPREFIX (p, "rd_operations=")) {
-                    p += 14;
-                    if (virStrToLong_ll (p, &dummy, 10, &stats->rd_req) == -1)
-                        DEBUG ("%s: error reading rd_req: %s",
-                               vm->def->name, p);
-                } else if (STRPREFIX (p, "wr_operations=")) {
-                    p += 14;
-                    if (virStrToLong_ll (p, &dummy, 10, &stats->wr_req) == -1)
-                        DEBUG ("%s: error reading wr_req: %s",
-                               vm->def->name, p);
-                } else
-                    DEBUG ("%s: unknown block stat near %s", vm->def->name, p);
-
-                /* Skip to next label. */
-                p = strchr (p, ' ');
-                if (!p || p >= eol) break;
-                p++;
-            }
-            ret = 0;
-            goto cleanup;
-        }
 
-        /* Skip to next line. */
-        p = strchr (p, '\n');
-        if (!p) break;
-        p++;
-    }
+    ret = 0;
 
-    /* If we reach here then the device was not found. */
-    qemudReportError (dom->conn, dom, NULL, VIR_ERR_INVALID_ARG,
-                      _("device not found: %s (%s)"), path, qemu_dev_name);
- cleanup:
+cleanup:
     VIR_FREE(qemu_dev_name);
-    VIR_FREE(info);
     if (vm)
         virDomainObjUnlock(vm);
     return ret;
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index a5f43c5..f35b1ef 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -671,6 +671,111 @@ cleanup:
 }
 
 
+int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm,
+                                 const char *devname,
+                                 long long *rd_req,
+                                 long long *rd_bytes,
+                                 long long *wr_req,
+                                 long long *wr_bytes,
+                                 long long *errs)
+{
+    char *info = NULL;
+    int ret = -1;
+    char *dummy;
+    const char *p, *eol;
+    int devnamelen = strlen(devname);
+
+    if (qemudMonitorCommand (vm, "info blockstats", &info) < 0) {
+        qemudReportError (NULL, NULL, NULL, VIR_ERR_OPERATION_FAILED,
+                          "%s", _("'info blockstats' command failed"));
+        goto cleanup;
+    }
+    DEBUG ("%s: info blockstats reply: %s", vm->def->name, info);
+
+    /* If the command isn't supported then qemu prints the supported
+     * info commands, so the output starts "info ".  Since this is
+     * unlikely to be the name of a block device, we can use this
+     * to detect if qemu supports the command.
+     */
+    if (strstr(info, "\ninfo ")) {
+        qemudReportError (NULL, NULL, NULL, VIR_ERR_NO_SUPPORT,
+                          "%s",
+                          _("'info blockstats' not supported by this qemu"));
+        goto cleanup;
+    }
+
+    *rd_req = -1;
+    *rd_bytes = -1;
+    *wr_req = -1;
+    *wr_bytes = -1;
+    *errs = -1;
+
+    /* The output format for both qemu & KVM is:
+     *   blockdevice: rd_bytes=% wr_bytes=% rd_operations=% wr_operations=%
+     *   (repeated for each block device)
+     * where '%' is a 64 bit number.
+     */
+    p = info;
+
+    while (*p) {
+        if (STREQLEN (p, devname, devnamelen)
+            && p[devnamelen] == ':' && p[devnamelen+1] == ' ') {
+
+            eol = strchr (p, '\n');
+            if (!eol)
+                eol = p + strlen (p);
+
+            p += devnamelen+2;         /* Skip to first label. */
+
+            while (*p) {
+                if (STRPREFIX (p, "rd_bytes=")) {
+                    p += 9;
+                    if (virStrToLong_ll (p, &dummy, 10, rd_bytes) == -1)
+                        DEBUG ("%s: error reading rd_bytes: %s",
+                               vm->def->name, p);
+                } else if (STRPREFIX (p, "wr_bytes=")) {
+                    p += 9;
+                    if (virStrToLong_ll (p, &dummy, 10, wr_bytes) == -1)
+                        DEBUG ("%s: error reading wr_bytes: %s",
+                               vm->def->name, p);
+                } else if (STRPREFIX (p, "rd_operations=")) {
+                    p += 14;
+                    if (virStrToLong_ll (p, &dummy, 10, rd_req) == -1)
+                        DEBUG ("%s: error reading rd_req: %s",
+                               vm->def->name, p);
+                } else if (STRPREFIX (p, "wr_operations=")) {
+                    p += 14;
+                    if (virStrToLong_ll (p, &dummy, 10, wr_req) == -1)
+                        DEBUG ("%s: error reading wr_req: %s",
+                               vm->def->name, p);
+                } else
+                    DEBUG ("%s: unknown block stat near %s", vm->def->name, p);
+
+                /* Skip to next label. */
+                p = strchr (p, ' ');
+                if (!p || p >= eol) break;
+                p++;
+            }
+            ret = 0;
+            goto cleanup;
+        }
+
+        /* Skip to next line. */
+        p = strchr (p, '\n');
+        if (!p) break;
+        p++;
+    }
+
+    /* If we reach here then the device was not found. */
+    qemudReportError (NULL, NULL, NULL, VIR_ERR_INVALID_ARG,
+                      _("no stats found for device %s"), devname);
+
+ cleanup:
+    VIR_FREE(info);
+    return ret;
+}
+
+
 int qemuMonitorSetVNCPassword(const virDomainObjPtr vm,
                               const char *password)
 {
diff --git a/src/qemu/qemu_monitor_text.h b/src/qemu/qemu_monitor_text.h
index dfe3445..a047eba 100644
--- a/src/qemu/qemu_monitor_text.h
+++ b/src/qemu/qemu_monitor_text.h
@@ -75,6 +75,14 @@ int qemuMonitorGetCPUInfo(const virDomainObjPtr vm,
                           int **pids);
 int qemuMonitorGetBalloonInfo(const virDomainObjPtr vm,
                               unsigned long *currmem);
+int qemuMonitorGetBlockStatsInfo(const virDomainObjPtr vm,
+                                 const char *devname,
+                                 long long *rd_req,
+                                 long long *rd_bytes,
+                                 long long *wr_req,
+                                 long long *wr_bytes,
+                                 long long *errs);
+
 
 int qemuMonitorSetVNCPassword(const virDomainObjPtr vm,
                               const char *password);
-- 
1.6.2.5




More information about the libvir-list mailing list