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

[libvirt] [PATCH 1/4] virDomainIOError public API and remote protocol



We already provide ways to detect when a domain has been paused as a
result of I/O error, but there was no way of getting the exact error or
even the device that experienced it.  This new API may be used for both.
---
 include/libvirt/libvirt.h.in |   19 +++++++++++++++
 src/driver.h                 |    6 ++++
 src/libvirt.c                |   53 ++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms      |    5 ++++
 src/remote/remote_driver.c   |    1 +
 src/remote/remote_protocol.x |   13 +++++++++-
 src/remote_protocol-structs  |    9 +++++++
 7 files changed, 105 insertions(+), 1 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 958e5a6..2c3423a 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -3746,6 +3746,25 @@ int virConnectSetKeepAlive(virConnectPtr conn,
                            int interval,
                            unsigned int count);
 
+/**
+ * virDomainIoError:
+ *
+ * Disk I/O error.
+ */
+typedef enum {
+    VIR_DOMAIN_IOERROR_NONE     = 0, /* no error */
+    VIR_DOMAIN_IOERROR_NO_SPACE = 1, /* no space left on the device */
+    VIR_DOMAIN_IOERROR_UNSPEC   = 2, /* unspecified I/O error */
+
+#ifdef VIR_ENUM_SENTINELS
+    VIR_DOMAIN_IOERROR_LAST
+#endif
+} virDomainIoError;
+
+int virDomainGetIoError(virDomainPtr dom,
+                        const char *dev,
+                        unsigned int flags);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/driver.h b/src/driver.h
index 24636a4..1dd3760 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -794,6 +794,11 @@ typedef int
                                   int *nparams,
                                   unsigned int flags);
 
+typedef int
+    (*virDrvDomainGetIoError)(virDomainPtr dom,
+                              const char *dev,
+                              unsigned int flags);
+
 /**
  * _virDriver:
  *
@@ -962,6 +967,7 @@ struct _virDriver {
     virDrvNodeSuspendForDuration nodeSuspendForDuration;
     virDrvDomainSetBlockIoTune domainSetBlockIoTune;
     virDrvDomainGetBlockIoTune domainGetBlockIoTune;
+    virDrvDomainGetIoError domainGetIoError;
 };
 
 typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index 7b8adf7..99edca3 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -17882,3 +17882,56 @@ error:
     virDispatchError(dom->conn);
     return -1;
 }
+
+/**
+ * virDomainGetIoError:
+ * @dom: a domain object
+ * @dev: disk device to be inspected or NULL
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * The @disk parameter is either the device target (the dev attribute of
+ * target subelement), such as "vda", or NULL, in which case all disks will be
+ * inspected for errors. If only one disk experienced an I/O error, that error
+ * will be returned. However, if there are more disks with I/O errors, this
+ * function will fail and return -2, requiring the caller to check every
+ * device explicitly.
+ *
+ * Returns -2 if @dev is NULL and there are multiple disks with errors, -1 if
+ * the function fails to do its job, the I/O error (virDomainIoError) observed
+ * on the specified disk (or any disk if @dev is NULL). Namely, 0 is returned
+ * when there is no error on the disk.
+ */
+int
+virDomainGetIoError(virDomainPtr dom,
+                    const char *dev,
+                    unsigned int flags)
+{
+    VIR_DOMAIN_DEBUG(dom, "dev=%s, flags=%x",
+                     NULLSTR(dev), flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_DOMAIN(dom)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    if (dom->conn->flags & VIR_CONNECT_RO) {
+        virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+        goto error;
+    }
+
+    if (dom->conn->driver->domainGetIoError) {
+        int ret = dom->conn->driver->domainGetIoError(dom, dev, flags);
+        if (ret == -1)
+            goto error;
+        return ret;
+    }
+
+    virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(dom->conn);
+    return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4ca7216..d778fdc 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -516,4 +516,9 @@ LIBVIRT_0.9.9 {
         virDomainSetNumaParameters;
 } LIBVIRT_0.9.8;
 
+LIBVIRT_0.9.10 {
+    global:
+        virDomainGetIoError;
+} LIBVIRT_0.9.9;
+
 # .... define new API here using predicted next version number ....
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index e28840b..d89f45b 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -4750,6 +4750,7 @@ static virDriver remote_driver = {
     .domainGetBlockIoTune = remoteDomainGetBlockIoTune, /* 0.9.8 */
     .domainSetNumaParameters = remoteDomainSetNumaParameters, /* 0.9.9 */
     .domainGetNumaParameters = remoteDomainGetNumaParameters, /* 0.9.9 */
+    .domainGetIoError = remoteDomainGetIoError, /* 0.9.10 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 514b0cc..b1635fb 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -2349,6 +2349,16 @@ struct remote_node_suspend_for_duration_args {
     unsigned int flags;
 };
 
+struct remote_domain_get_io_error_args {
+    remote_nonnull_domain dom;
+    remote_string dev;
+    unsigned int flags;
+};
+
+struct remote_domain_get_io_error_ret {
+    int result;
+};
+
 
 /*----- Protocol. -----*/
 
@@ -2654,7 +2664,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_SET_NUMA_PARAMETERS = 254, /* autogen autogen */
     REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /* skipgen skipgen */
     REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /* autogen autogen */
-    REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257 /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /* skipgen skipgen */
+    REMOTE_PROC_DOMAIN_GET_IO_ERROR = 258 /* autogen autogen */
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs
index 2758315..1438485 100644
--- a/src/remote_protocol-structs
+++ b/src/remote_protocol-structs
@@ -1832,6 +1832,14 @@ struct remote_node_suspend_for_duration_args {
         uint64_t                   duration;
         u_int                      flags;
 };
+struct remote_domain_get_io_error_args {
+        remote_nonnull_domain      dom;
+        remote_string              dev;
+        u_int                      flags;
+};
+struct remote_domain_get_io_error_ret {
+        int                        result;
+};
 enum remote_procedure {
         REMOTE_PROC_OPEN = 1,
         REMOTE_PROC_CLOSE = 2,
@@ -2090,4 +2098,5 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255,
         REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256,
         REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257,
+        REMOTE_PROC_DOMAIN_GET_IO_ERROR = 258,
 };
-- 
1.7.8.4


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