[libvirt] [PATCH v3 1/5] virDomainGetDiskErrors public API

Jiri Denemark jdenemar at redhat.com
Tue Jan 31 19:26:10 UTC 2012


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 |   32 ++++++++++++++++++++
 python/generator.py          |    3 +-
 src/driver.h                 |    7 ++++
 src/libvirt.c                |   65 ++++++++++++++++++++++++++++++++++++++++++
 src/libvirt_public.syms      |    1 +
 5 files changed, 107 insertions(+), 1 deletions(-)

diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index d9b9b95..cf53cf2 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -1967,6 +1967,38 @@ virDomainGetBlockIoTune(virDomainPtr dom,
                         int *nparams,
                         unsigned int flags);
 
+/**
+ * virDomainDiskErrorCode:
+ *
+ * Disk I/O error.
+ */
+typedef enum {
+    VIR_DOMAIN_DISK_ERROR_NONE      = 0, /* no error */
+    VIR_DOMAIN_DISK_ERROR_UNSPEC    = 1, /* unspecified I/O error */
+    VIR_DOMAIN_DISK_ERROR_NO_SPACE  = 2, /* no space left on the device */
+
+#ifdef VIR_ENUM_SENTINELS
+    VIR_DOMAIN_DISK_ERROR_LAST
+#endif
+} virDomainDiskErrorCode;
+
+/**
+ * virDomainDiskError:
+ *
+ */
+typedef struct _virDomainDiskError virDomainDiskError;
+typedef virDomainDiskError *virDomainDiskErrorPtr;
+
+struct _virDomainDiskError {
+    char *disk; /* disk target */
+    int error;  /* virDomainDiskErrorCode */
+};
+
+int virDomainGetDiskErrors(virDomainPtr dom,
+                           virDomainDiskErrorPtr errors,
+                           unsigned int maxerrors,
+                           unsigned int flags);
+
 
 /*
  * NUMA support
diff --git a/python/generator.py b/python/generator.py
index 6f813ae..b514af5 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -423,7 +423,8 @@ skip_impl = (
     'virDomainGetBlockIoTune',
     'virDomainSetInterfaceParameters',
     'virDomainGetInterfaceParameters',
-    'virDomainGetCPUStats'  # not implemented now.
+    'virDomainGetCPUStats',  # not implemented now.
+    'virDomainGetDiskErrors',
 )
 
 qemu_skip_impl = (
diff --git a/src/driver.h b/src/driver.h
index 2e2042e..9ff5edf 100644
--- a/src/driver.h
+++ b/src/driver.h
@@ -810,6 +810,12 @@ typedef int
                                unsigned int ncpus,
                                unsigned int flags);
 
+typedef int
+    (*virDrvDomainGetDiskErrors)(virDomainPtr dom,
+                                 virDomainDiskErrorPtr errors,
+                                 unsigned int maxerrors,
+                                 unsigned int flags);
+
 /**
  * _virDriver:
  *
@@ -981,6 +987,7 @@ struct _virDriver {
     virDrvDomainSetBlockIoTune domainSetBlockIoTune;
     virDrvDomainGetBlockIoTune domainGetBlockIoTune;
     virDrvDomainGetCPUStats domainGetCPUStats;
+    virDrvDomainGetDiskErrors domainGetDiskErrors;
 };
 
 typedef int
diff --git a/src/libvirt.c b/src/libvirt.c
index c609202..e84447e 100644
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -18282,3 +18282,68 @@ error:
     virDispatchError(domain->conn);
     return -1;
 }
+
+/**
+ * virDomainGetDiskErrors:
+ * @dom: a domain object
+ * @errors: array to populate on output
+ * @maxerrors: size of @errors array
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * The function populates @errors array with all disks that encountered an
+ * I/O error.  Disks with no error will not be returned in the @errors array.
+ * Each disk is identified by its target (the dev attribute of target
+ * subelement in domain XML), such as "vda", and accompanied with the error
+ * that was seen on it.  The caller is also responsible for calling free()
+ * on each disk name returned.
+ *
+ * In a special case when @errors is NULL and @maxerrors is 0, the function
+ * returns preferred size of @errors that the caller should use to get all
+ * disk errors.
+ *
+ * Since calling virDomainGetDiskErrors(dom, NULL, 0, 0) to get preferred size
+ * of @errors array and getting the errors are two separate operations, new
+ * disks may be hotplugged to the domain and new errors may be encountered
+ * between the two calls.  Thus, this function may not return all disk errors
+ * because the supplied array is not large enough.  Such errors may, however,
+ * be detected by listening to domain events.
+ *
+ * Returns number of disks with errors filled in the @errors array or -1 on
+ * error.
+ */
+int
+virDomainGetDiskErrors(virDomainPtr dom,
+                       virDomainDiskErrorPtr errors,
+                       unsigned int maxerrors,
+                       unsigned int flags)
+{
+    VIR_DOMAIN_DEBUG(dom, "errors=%p, maxerrors=%u, flags=%x",
+                     errors, maxerrors, flags);
+
+    virResetLastError();
+
+    if (!VIR_IS_DOMAIN(dom)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        virDispatchError(NULL);
+        return -1;
+    }
+
+    if ((!errors && maxerrors) || (errors && !maxerrors)) {
+        virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+        goto error;
+    }
+
+    if (dom->conn->driver->domainGetDiskErrors) {
+        int ret = dom->conn->driver->domainGetDiskErrors(dom, errors,
+                                                         maxerrors, flags);
+        if (ret < 0)
+            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 1c4e0a3..ced9fb3 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -519,6 +519,7 @@ LIBVIRT_0.9.9 {
 LIBVIRT_0.9.10 {
     global:
         virDomainGetCPUStats;
+        virDomainGetDiskErrors;
         virDomainPMSuspendForDuration;
         virDomainShutdownFlags;
         virStorageVolResize;
-- 
1.7.8.4




More information about the libvir-list mailing list