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