[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 4/4] qemu: Implement virDomainIOError



---
 src/qemu/qemu_conf.h         |    1 +
 src/qemu/qemu_driver.c       |   82 ++++++++++++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c      |   40 ++++++++++++++++++++
 src/qemu/qemu_monitor.h      |    1 +
 src/qemu/qemu_monitor_json.c |    8 ++++
 src/qemu/qemu_monitor_text.c |   15 ++++++++
 6 files changed, 147 insertions(+), 0 deletions(-)

diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h
index 7d79823..0b65d7d 100644
--- a/src/qemu/qemu_conf.h
+++ b/src/qemu/qemu_conf.h
@@ -175,6 +175,7 @@ struct qemuDomainDiskInfo {
     bool removable;
     bool locked;
     bool tray_open;
+    int io_status;
 };
 
 #endif /* __QEMUD_CONF_H */
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 608e82a..c696489 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -11605,6 +11605,87 @@ cleanup:
     return ret;
 }
 
+static int
+qemuDomainGetIoError(virDomainPtr dom,
+                     const char *dev,
+                     unsigned int flags)
+{
+    struct qemud_driver *driver = dom->conn->privateData;
+    virDomainObjPtr vm = NULL;
+    qemuDomainObjPrivatePtr priv;
+    char uuidstr[VIR_UUID_STRING_BUFLEN];
+    virHashTablePtr table = NULL;
+    virDomainDiskDefPtr *disks;
+    int ndisks;
+    int ret = -1;
+    int i;
+
+    virCheckFlags(0, -1);
+
+    qemuDriverLock(driver);
+    virUUIDFormat(dom->uuid, uuidstr);
+    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
+    qemuDriverUnlock(driver);
+
+    if (!vm) {
+        qemuReportError(VIR_ERR_NO_DOMAIN,
+                        _("no domain with matching uuid '%s'"), uuidstr);
+        goto cleanup;
+    }
+    priv = vm->privateData;
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+        goto cleanup;
+
+    if (!virDomainObjIsActive(vm)) {
+        qemuReportError(VIR_ERR_OPERATION_INVALID,
+                        "%s", _("domain is not running"));
+        goto endjob;
+    }
+
+    if (dev) {
+        if ((i = virDomainDiskIndexByName(vm->def, dev, false)) < 0)
+            goto endjob;
+        disks = vm->def->disks + i;
+        ndisks = 1;
+    } else {
+        disks = vm->def->disks;
+        ndisks = vm->def->ndisks;
+    }
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    table = qemuMonitorGetBlockInfo(priv->mon);
+    qemuDomainObjExitMonitor(driver, vm);
+    if (!table)
+        goto endjob;
+
+    ret = 0;
+    for (i = 0; i < ndisks; i++) {
+        struct qemuDomainDiskInfo *info;
+        info = qemuMonitorBlockInfoLookup(table, disks[i]->info.alias);
+        if (!info)
+            goto endjob;
+
+        if (info->io_status > 0) {
+            if (ret > 0) {
+                ret = -2;
+                goto endjob;
+            }
+            ret = info->io_status;
+        }
+    }
+
+endjob:
+    if (qemuDomainObjEndJob(driver, vm) == 0)
+        vm = NULL;
+
+cleanup:
+    if (vm)
+        virDomainObjUnlock(vm);
+    virHashFree(table);
+    return ret;
+}
+
 static virDriver qemuDriver = {
     .no = VIR_DRV_QEMU,
     .name = "QEMU",
@@ -11757,6 +11838,7 @@ static virDriver qemuDriver = {
     .domainGetNumaParameters = qemuDomainGetNumaParameters, /* 0.9.9 */
     .domainGetInterfaceParameters = qemuDomainGetInterfaceParameters, /* 0.9.9 */
     .domainSetInterfaceParameters = qemuDomainSetInterfaceParameters, /* 0.9.9 */
+    .domainGetIoError = qemuDomainGetIoError, /* 0.9.10 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index dda0521..94eb913 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -87,6 +87,20 @@ VIR_ENUM_IMPL(qemuMonitorVMStatus,
               "postmigrate", "prelaunch", "finish-migrate", "restore-vm",
               "running", "save-vm", "shutdown", "watchdog")
 
+typedef enum {
+    QEMU_MONITOR_BLOCK_IO_STATUS_OK,
+    QEMU_MONITOR_BLOCK_IO_STATUS_FAILED,
+    QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE,
+
+    QEMU_MONITOR_BLOCK_IO_STATUS_LAST
+} qemuMonitorBlockIOStatus;
+
+VIR_ENUM_DECL(qemuMonitorBlockIOStatus)
+
+VIR_ENUM_IMPL(qemuMonitorBlockIOStatus,
+              QEMU_MONITOR_BLOCK_IO_STATUS_LAST,
+              "ok", "failed", "nospace")
+
 char *qemuMonitorEscapeArg(const char *in)
 {
     int len = 0;
@@ -1227,6 +1241,32 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
     return ret;
 }
 
+int
+qemuMonitorBlockIOStatusToError(const char *status)
+{
+    int st = qemuMonitorBlockIOStatusTypeFromString(status);
+
+    if (st < 0) {
+        qemuReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("unknown block IO status: %s"), status);
+        return -1;
+    }
+
+    switch ((qemuMonitorBlockIOStatus) st) {
+    case QEMU_MONITOR_BLOCK_IO_STATUS_OK:
+        return VIR_DOMAIN_IOERROR_NONE;
+    case QEMU_MONITOR_BLOCK_IO_STATUS_FAILED:
+        return VIR_DOMAIN_IOERROR_UNSPEC;
+    case QEMU_MONITOR_BLOCK_IO_STATUS_NOSPACE:
+        return VIR_DOMAIN_IOERROR_NO_SPACE;
+
+    /* unreachable */
+    case QEMU_MONITOR_BLOCK_IO_STATUS_LAST:
+        break;
+    }
+    return -1;
+}
+
 virHashTablePtr
 qemuMonitorGetBlockInfo(qemuMonitorPtr mon)
 {
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 4d52f06..bb68a41 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -236,6 +236,7 @@ int qemuMonitorGetMemoryStats(qemuMonitorPtr mon,
                               virDomainMemoryStatPtr stats,
                               unsigned int nr_stats);
 
+int qemuMonitorBlockIOStatusToError(const char *status);
 virHashTablePtr qemuMonitorGetBlockInfo(qemuMonitorPtr mon);
 struct qemuDomainDiskInfo *
 qemuMonitorBlockInfoLookup(virHashTablePtr blockInfo,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 3afcff3..3be2705 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -1389,6 +1389,7 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
         virJSONValuePtr dev = virJSONValueArrayGet(devices, i);
         struct qemuDomainDiskInfo *info;
         const char *thisdev;
+        const char *status;
 
         if (!dev || dev->type != VIR_JSON_TYPE_OBJECT) {
             qemuReportError(VIR_ERR_INTERNAL_ERROR, "%s",
@@ -1434,6 +1435,13 @@ int qemuMonitorJSONGetBlockInfo(qemuMonitorPtr mon,
          */
         ignore_value(virJSONValueObjectGetBoolean(dev, "tray-open",
                                                   &info->tray_open));
+
+        /* Missing io-status indicates no error */
+        if ((status = virJSONValueObjectGetString(dev, "io-status"))) {
+            info->io_status = qemuMonitorBlockIOStatusToError(status);
+            if (info->io_status < 0)
+                goto cleanup;
+        }
     }
 
     ret = 0;
diff --git a/src/qemu/qemu_monitor_text.c b/src/qemu/qemu_monitor_text.c
index a33d192..2146a03 100644
--- a/src/qemu/qemu_monitor_text.c
+++ b/src/qemu/qemu_monitor_text.c
@@ -839,6 +839,21 @@ int qemuMonitorTextGetBlockInfo(qemuMonitorPtr mon,
                         VIR_DEBUG("error reading tray_open: %s", p);
                     else
                         info->tray_open = (tmp != 0);
+                } else if (STRPREFIX(p, "io-status=")) {
+                    char *end;
+                    char c;
+
+                    p += strlen("io-status=");
+                    end = strchr(p, ' ');
+                    if (!end || end > eol)
+                        end = eol;
+
+                    c = *end;
+                    *end = '\0';
+                    info->io_status = qemuMonitorBlockIOStatusToError(p);
+                    *end = c;
+                    if (info->io_status < 0)
+                        goto cleanup;
                 } else {
                     /* ignore because we don't parse all options */
                 }
-- 
1.7.8.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]