[libvirt] [PATCH] Add support for another explicit IO error event

Daniel P. Berrange berrange at redhat.com
Thu Apr 29 16:44:28 UTC 2010


This introduces a new event type

   VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON

This event is the same as the previous VIR_DOMAIN_ID_IO_ERROR
event, but also includes a string describing the cause of
the event.

Thus there is a new callback definition for this event type

typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
                                                           virDomainPtr dom,
                                                           const char *srcPath,
                                                           const char *devAlias,
                                                           int action,
                                                           const char *reason,
                                                           void *opaque);

This is currently wired up to the QEMU block IO error events

* daemon/remote.c: Dispatch IO error events to client
* examples/domain-events/events-c/event-test.c: Watch for
  IO error events
* include/libvirt/libvirt.h.in: Define new IO error event ID
  and callback signature
* src/conf/domain_event.c, src/conf/domain_event.h,
  src/libvirt_private.syms: Extend API to handle IO error events
* src/qemu/qemu_driver.c: Connect to the QEMU monitor event
  for block IO errors and emit a libvirt IO error event
* src/remote/remote_driver.c: Receive and dispatch IO error
  events to application
* src/remote/remote_protocol.x: Wire protocol definition for
  IO error events
* src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h,
  src/qemu/qemu_monitor_json.c: Watch for BLOCK_IO_ERROR event
  from QEMU monitor
---
 daemon/remote.c                       |   38 +++++++++++++++
 daemon/remote_dispatch_table.h        |    5 ++
 include/libvirt/libvirt.h.in          |   23 +++++++++
 python/libvirt-override-virConnect.py |   14 +++++-
 python/libvirt-override.c             |   55 +++++++++++++++++++++
 src/conf/domain_event.c               |   84 ++++++++++++++++++++++++++++-----
 src/conf/domain_event.h               |   10 ++++
 src/libvirt_private.syms              |    2 +
 src/qemu/qemu_driver.c                |    9 +++-
 src/qemu/qemu_monitor.c               |    5 +-
 src/qemu/qemu_monitor.h               |    6 ++-
 src/qemu/qemu_monitor_json.c          |    2 +-
 src/remote/remote_driver.c            |   35 ++++++++++++++
 src/remote/remote_protocol.c          |   17 +++++++
 src/remote/remote_protocol.h          |   12 +++++
 src/remote/remote_protocol.x          |   11 ++++-
 16 files changed, 307 insertions(+), 21 deletions(-)

diff --git a/daemon/remote.c b/daemon/remote.c
index 6dbe7ee..c54565c 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -256,6 +256,43 @@ static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED,
 }
 
 
+static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                               virDomainPtr dom,
+                                               const char *srcPath,
+                                               const char *devAlias,
+                                               int action,
+                                               const char *reason,
+                                               void *opaque)
+{
+    struct qemud_client *client = opaque;
+    remote_domain_event_io_error_reason_msg data;
+
+    if (!client)
+        return -1;
+
+    REMOTE_DEBUG("Relaying domain io error %s %d %s %s %d %s",
+                 dom->name, dom->id, srcPath, devAlias, action, reason);
+
+    virMutexLock(&client->lock);
+
+    /* build return data */
+    memset(&data, 0, sizeof data);
+    make_nonnull_domain (&data.dom, dom);
+    data.srcPath = (char*)srcPath;
+    data.devAlias = (char*)devAlias;
+    data.action = action;
+    data.reason = (char*)reason;
+
+    remoteDispatchDomainEventSend (client,
+                                   REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON,
+                                   (xdrproc_t)xdr_remote_domain_event_io_error_reason_msg, &data);
+
+    virMutexUnlock(&client->lock);
+
+    return 0;
+}
+
+
 static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED,
                                           virDomainPtr dom,
                                           int phase,
@@ -327,6 +364,7 @@ static virConnectDomainEventGenericCallback domainEventCallbacks[] = {
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError),
     VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventGraphics),
+    VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOErrorReason),
 };
 
 verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST);
diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h
index 984634f..86bd3b0 100644
--- a/daemon/remote_dispatch_table.h
+++ b/daemon/remote_dispatch_table.h
@@ -977,3 +977,8 @@
     .args_filter = (xdrproc_t) xdr_remote_domain_get_block_info_args,
     .ret_filter = (xdrproc_t) xdr_remote_domain_get_block_info_ret,
 },
+{   /* Async event DomainEventIoErrorReason => 195 */
+    .fn = NULL,
+    .args_filter = (xdrproc_t) xdr_void,
+    .ret_filter = (xdrproc_t) xdr_void,
+},
diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in
index 4237b7b..f296d16 100644
--- a/include/libvirt/libvirt.h.in
+++ b/include/libvirt/libvirt.h.in
@@ -2054,6 +2054,28 @@ typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn,
                                                      void *opaque);
 
 /**
+ * virConnectDomainEventWatchdogCallback:
+ * @conn: connection object
+ * @dom: domain on which the event occurred
+ * @srcPath: The host file on which the IO error occurred
+ * @devAlias: The guest device alias associated with the path
+ * @action: action that is to be taken due to the IO error
+ * @reason: the cause of the IO error
+ * @opaque: application specified data
+ *
+ * The callback signature to use when registering for an event of type
+ * VIR_DOMAIN_EVENT_ID_IO_ERROR with virConnectDomainEventRegisterAny()
+ *
+ */
+typedef void (*virConnectDomainEventIOErrorReasonCallback)(virConnectPtr conn,
+                                                           virDomainPtr dom,
+                                                           const char *srcPath,
+                                                           const char *devAlias,
+                                                           int action,
+                                                           const char *reason,
+                                                           void *opaque);
+
+/**
  * virDomainEventGraphicsPhase:
  *
  * The phase of the graphics client connection
@@ -2161,6 +2183,7 @@ typedef enum {
     VIR_DOMAIN_EVENT_ID_WATCHDOG = 3,        /* virConnectDomainEventWatchdogCallback */
     VIR_DOMAIN_EVENT_ID_IO_ERROR = 4,        /* virConnectDomainEventIOErrorCallback */
     VIR_DOMAIN_EVENT_ID_GRAPHICS = 5,        /* virConnectDomainEventGraphicsCallback */
+    VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON = 6, /* virConnectDomainEventIOErrorReasonCallback */
 
     /*
      * NB: this enum value will increase over time as new events are
diff --git a/python/libvirt-override-virConnect.py b/python/libvirt-override-virConnect.py
index cb38e3f..df39b79 100644
--- a/python/libvirt-override-virConnect.py
+++ b/python/libvirt-override-virConnect.py
@@ -94,7 +94,19 @@
             cb = cbData["cb"]
             opaque = cbData["opaque"]
 
-            cb(self, virDomain(self, _obj=dom), opaque)
+            cb(self, virDomain(self, _obj=dom), srcPath, devAlias, opaque)
+            return 0
+        except AttributeError:
+            pass
+
+    def dispatchDomainEventIOErrorReasonCallback(self, dom, srcPath, devAlias, action, reason, cbData):
+        """Dispatches events to python user domain IO error event callbacks
+        """
+        try:
+            cb = cbData["cb"]
+            opaque = cbData["opaque"]
+
+            cb(self, virDomain(self, _obj=dom), srcPath, devAlias, action, reason, opaque)
             return 0
         except AttributeError:
             pass
diff --git a/python/libvirt-override.c b/python/libvirt-override.c
index 7c7682c..b97445b 100644
--- a/python/libvirt-override.c
+++ b/python/libvirt-override.c
@@ -3208,6 +3208,58 @@ libvirt_virConnectDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED
 }
 
 static int
+libvirt_virConnectDomainEventIOErrorReasonCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
+                                                   virDomainPtr dom,
+                                                   const char *srcPath,
+                                                   const char *devAlias,
+                                                   int action,
+                                                   const char *reason,
+                                                   void *opaque)
+{
+    PyObject *pyobj_cbData = (PyObject*)opaque;
+    PyObject *pyobj_dom;
+    PyObject *pyobj_ret;
+    PyObject *pyobj_conn;
+    PyObject *dictKey;
+    int ret = -1;
+
+    LIBVIRT_ENSURE_THREAD_STATE;
+
+    /* Create a python instance of this virDomainPtr */
+    virDomainRef(dom);
+    pyobj_dom = libvirt_virDomainPtrWrap(dom);
+    Py_INCREF(pyobj_cbData);
+
+    dictKey = libvirt_constcharPtrWrap("conn");
+    pyobj_conn = PyDict_GetItem(pyobj_cbData, dictKey);
+    Py_DECREF(dictKey);
+
+    /* Call the Callback Dispatcher */
+    pyobj_ret = PyObject_CallMethod(pyobj_conn,
+                                    (char*)"dispatchDomainEventIOErrorCallback",
+                                    (char*)"OssisO",
+                                    pyobj_dom,
+                                    srcPath, devAlias, action, reason,
+                                    pyobj_cbData);
+
+    Py_DECREF(pyobj_cbData);
+    Py_DECREF(pyobj_dom);
+
+    if(!pyobj_ret) {
+#if DEBUG_ERROR
+        printf("%s - ret:%p\n", __FUNCTION__, pyobj_ret);
+#endif
+        PyErr_Print();
+    } else {
+        Py_DECREF(pyobj_ret);
+        ret = 0;
+    }
+
+    LIBVIRT_RELEASE_THREAD_STATE;
+    return ret;
+}
+
+static int
 libvirt_virConnectDomainEventGraphicsCallback(virConnectPtr conn ATTRIBUTE_UNUSED,
                                               virDomainPtr dom,
                                               int phase,
@@ -3345,6 +3397,9 @@ libvirt_virConnectDomainEventRegisterAny(ATTRIBUTE_UNUSED PyObject * self,
     case VIR_DOMAIN_EVENT_ID_IO_ERROR:
         cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorCallback);
         break;
+    case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
+        cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventIOErrorReasonCallback);
+        break;
     case VIR_DOMAIN_EVENT_ID_GRAPHICS:
         cb = VIR_DOMAIN_EVENT_CALLBACK(libvirt_virConnectDomainEventGraphicsCallback);
         break;
diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c
index e3ce5ba..e5bd458 100644
--- a/src/conf/domain_event.c
+++ b/src/conf/domain_event.c
@@ -74,6 +74,7 @@ struct _virDomainEvent {
             char *srcPath;
             char *devAlias;
             int action;
+            char *reason;
         } ioError;
         struct {
             int phase;
@@ -474,6 +475,7 @@ void virDomainEventFree(virDomainEventPtr event)
     case VIR_DOMAIN_EVENT_ID_IO_ERROR:
         VIR_FREE(event->data.ioError.srcPath);
         VIR_FREE(event->data.ioError.devAlias);
+        VIR_FREE(event->data.ioError.reason);
         break;
 
     case VIR_DOMAIN_EVENT_ID_GRAPHICS:
@@ -630,19 +632,22 @@ virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj,
     return ev;
 }
 
-virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
-                                                  const char *srcPath,
-                                                  const char *devAlias,
-                                                  int action)
+static virDomainEventPtr virDomainEventIOErrorNewFromDomImpl(int event,
+                                                             virDomainPtr dom,
+                                                             const char *srcPath,
+                                                             const char *devAlias,
+                                                             int action,
+                                                             const char *reason)
 {
     virDomainEventPtr ev =
-        virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+        virDomainEventNewInternal(event,
                                   dom->id, dom->name, dom->uuid);
 
     if (ev) {
         ev->data.ioError.action = action;
         if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
-            !(ev->data.ioError.devAlias = strdup(devAlias))) {
+            !(ev->data.ioError.devAlias = strdup(devAlias)) ||
+            (reason && !(ev->data.ioError.reason = strdup(reason)))) {
             virDomainEventFree(ev);
             ev = NULL;
         }
@@ -650,19 +655,23 @@ virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
 
     return ev;
 }
-virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
-                                                  const char *srcPath,
-                                                  const char *devAlias,
-                                                  int action)
+
+static virDomainEventPtr virDomainEventIOErrorNewFromObjImpl(int event,
+                                                             virDomainObjPtr obj,
+                                                             const char *srcPath,
+                                                             const char *devAlias,
+                                                             int action,
+                                                             const char *reason)
 {
     virDomainEventPtr ev =
-        virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+        virDomainEventNewInternal(event,
                                   obj->def->id, obj->def->name, obj->def->uuid);
 
     if (ev) {
         ev->data.ioError.action = action;
         if (!(ev->data.ioError.srcPath = strdup(srcPath)) ||
-            !(ev->data.ioError.devAlias = strdup(devAlias))) {
+            !(ev->data.ioError.devAlias = strdup(devAlias)) ||
+            !(ev->data.ioError.reason = strdup(reason))) {
             virDomainEventFree(ev);
             ev = NULL;
         }
@@ -671,6 +680,48 @@ virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
     return ev;
 }
 
+virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom,
+                                                  const char *srcPath,
+                                                  const char *devAlias,
+                                                  int action)
+{
+    return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+                                               dom, srcPath, devAlias,
+                                               action, NULL);
+}
+
+virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
+                                                  const char *srcPath,
+                                                  const char *devAlias,
+                                                  int action)
+{
+    return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR,
+                                               obj, srcPath, devAlias,
+                                               action, NULL);
+}
+
+virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
+                                                        const char *srcPath,
+                                                        const char *devAlias,
+                                                        int action,
+                                                        const char *reason)
+{
+    return virDomainEventIOErrorNewFromDomImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
+                                               dom, srcPath, devAlias,
+                                               action, reason);
+}
+
+virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
+                                                        const char *srcPath,
+                                                        const char *devAlias,
+                                                        int action,
+                                                        const char *reason)
+{
+    return virDomainEventIOErrorNewFromObjImpl(VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON,
+                                               obj, srcPath, devAlias,
+                                               action, reason);
+}
+
 
 virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
                                                    int phase,
@@ -853,6 +904,15 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn,
                                                    cbopaque);
         break;
 
+    case VIR_DOMAIN_EVENT_ID_IO_ERROR_REASON:
+        ((virConnectDomainEventIOErrorReasonCallback)cb)(conn, dom,
+                                                         event->data.ioError.srcPath,
+                                                         event->data.ioError.devAlias,
+                                                         event->data.ioError.action,
+                                                         event->data.ioError.reason,
+                                                         cbopaque);
+        break;
+
     case VIR_DOMAIN_EVENT_ID_GRAPHICS:
         ((virConnectDomainEventGraphicsCallback)cb)(conn, dom,
                                                     event->data.graphics.phase,
diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h
index f72ac58..e28293d 100644
--- a/src/conf/domain_event.h
+++ b/src/conf/domain_event.h
@@ -129,6 +129,16 @@ virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj,
                                                   const char *srcPath,
                                                   const char *devAlias,
                                                   int action);
+virDomainEventPtr virDomainEventIOErrorReasonNewFromDom(virDomainPtr dom,
+                                                        const char *srcPath,
+                                                        const char *devAlias,
+                                                        int action,
+                                                        const char *reason);
+virDomainEventPtr virDomainEventIOErrorReasonNewFromObj(virDomainObjPtr obj,
+                                                        const char *srcPath,
+                                                        const char *devAlias,
+                                                        int action,
+                                                        const char *reason);
 
 virDomainEventPtr virDomainEventGraphicsNewFromDom(virDomainPtr dom,
                                                    int phase,
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 746327d..09f3da1 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -246,6 +246,8 @@ virDomainEventWatchdogNewFromDom;
 virDomainEventWatchdogNewFromObj;
 virDomainEventIOErrorNewFromDom;
 virDomainEventIOErrorNewFromObj;
+virDomainEventIOErrorReasonNewFromDom;
+virDomainEventIOErrorReasonNewFromObj;
 virDomainEventGraphicsNewFromDom;
 virDomainEventGraphicsNewFromObj;
 virDomainEventFree;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c2902ac..52f2df8 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -1015,10 +1015,12 @@ static int
 qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                         virDomainObjPtr vm,
                         const char *diskAlias,
-                        int action)
+                        int action,
+                        const char *reason)
 {
     struct qemud_driver *driver = qemu_driver;
     virDomainEventPtr ioErrorEvent = NULL;
+    virDomainEventPtr ioErrorEvent2 = NULL;
     virDomainEventPtr lifecycleEvent = NULL;
     const char *srcPath;
     const char *devAlias;
@@ -1036,6 +1038,7 @@ qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     }
 
     ioErrorEvent = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action);
+    ioErrorEvent2 = virDomainEventIOErrorReasonNewFromObj(vm, srcPath, devAlias, action, reason);
 
     if (action == VIR_DOMAIN_EVENT_IO_ERROR_PAUSE &&
         vm->state == VIR_DOMAIN_RUNNING) {
@@ -1051,10 +1054,12 @@ qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     }
     virDomainObjUnlock(vm);
 
-    if (ioErrorEvent || lifecycleEvent) {
+    if (ioErrorEvent || ioErrorEvent2 || lifecycleEvent) {
         qemuDriverLock(driver);
         if (ioErrorEvent)
             qemuDomainEventQueue(driver, ioErrorEvent);
+        if (ioErrorEvent2)
+            qemuDomainEventQueue(driver, ioErrorEvent2);
         if (lifecycleEvent)
             qemuDomainEventQueue(driver, lifecycleEvent);
         qemuDriverUnlock(driver);
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 5e83afc..fca8590 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -833,7 +833,8 @@ int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action)
 
 int qemuMonitorEmitIOError(qemuMonitorPtr mon,
                            const char *diskAlias,
-                           int action)
+                           int action,
+                           const char *reason)
 {
     int ret = -1;
     VIR_DEBUG("mon=%p", mon);
@@ -841,7 +842,7 @@ int qemuMonitorEmitIOError(qemuMonitorPtr mon,
     qemuMonitorRef(mon);
     qemuMonitorUnlock(mon);
     if (mon->cb && mon->cb->domainIOError)
-        ret = mon->cb->domainIOError(mon, mon->vm, diskAlias, action);
+        ret = mon->cb->domainIOError(mon, mon->vm, diskAlias, action, reason);
     qemuMonitorLock(mon);
     qemuMonitorUnref(mon);
     return ret;
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index ec848a8..3fa83b7 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -95,7 +95,8 @@ struct _qemuMonitorCallbacks {
     int (*domainIOError)(qemuMonitorPtr mon,
                          virDomainObjPtr vm,
                          const char *diskAlias,
-                         int action);
+                         int action,
+                         const char *reason);
     int (*domainGraphics)(qemuMonitorPtr mon,
                           virDomainObjPtr vm,
                           int phase,
@@ -148,7 +149,8 @@ int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset);
 int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action);
 int qemuMonitorEmitIOError(qemuMonitorPtr mon,
                            const char *diskAlias,
-                           int action);
+                           int action,
+                           const char *reason);
 int qemuMonitorEmitGraphics(qemuMonitorPtr mon,
                             int phase,
                             int localFamily,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 09a3562..8c77ab1 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -534,7 +534,7 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat
         actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE;
     }
 
-    qemuMonitorEmitIOError(mon, device, actionID);
+    qemuMonitorEmitIOError(mon, device, actionID, "");
 }
 
 
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index e589f8e..317125f 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -7430,6 +7430,37 @@ remoteDomainReadEventIOError(virConnectPtr conn, XDR *xdr)
 
 
 static virDomainEventPtr
+remoteDomainReadEventIOErrorReason(virConnectPtr conn, XDR *xdr)
+{
+    remote_domain_event_io_error_reason_msg msg;
+    virDomainPtr dom;
+    virDomainEventPtr event = NULL;
+    memset (&msg, 0, sizeof msg);
+
+    /* unmarshall parameters, and process it*/
+    if (! xdr_remote_domain_event_io_error_reason_msg(xdr, &msg) ) {
+        remoteError(VIR_ERR_RPC, "%s",
+                    _("unable to demarshall reboot event"));
+        return NULL;
+    }
+
+    dom = get_nonnull_domain(conn,msg.dom);
+    if (!dom)
+        return NULL;
+
+    event = virDomainEventIOErrorReasonNewFromDom(dom,
+                                                  msg.srcPath,
+                                                  msg.devAlias,
+                                                  msg.action,
+                                                  msg.reason);
+    xdr_free ((xdrproc_t) &xdr_remote_domain_event_io_error_reason_msg, (char *) &msg);
+
+    virDomainFree(dom);
+    return event;
+}
+
+
+static virDomainEventPtr
 remoteDomainReadEventGraphics(virConnectPtr conn, XDR *xdr)
 {
     remote_domain_event_graphics_msg msg;
@@ -9327,6 +9358,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv,
         event = remoteDomainReadEventIOError(conn, xdr);
         break;
 
+    case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON:
+        event = remoteDomainReadEventIOErrorReason(conn, xdr);
+        break;
+
     case REMOTE_PROC_DOMAIN_EVENT_GRAPHICS:
         event = remoteDomainReadEventGraphics(conn, xdr);
         break;
diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c
index 71eed42..187281d 100644
--- a/src/remote/remote_protocol.c
+++ b/src/remote/remote_protocol.c
@@ -3290,6 +3290,23 @@ xdr_remote_domain_event_io_error_msg (XDR *xdrs, remote_domain_event_io_error_ms
 }
 
 bool_t
+xdr_remote_domain_event_io_error_reason_msg (XDR *xdrs, remote_domain_event_io_error_reason_msg *objp)
+{
+
+         if (!xdr_remote_nonnull_domain (xdrs, &objp->dom))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->srcPath))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->devAlias))
+                 return FALSE;
+         if (!xdr_int (xdrs, &objp->action))
+                 return FALSE;
+         if (!xdr_remote_nonnull_string (xdrs, &objp->reason))
+                 return FALSE;
+        return TRUE;
+}
+
+bool_t
 xdr_remote_domain_event_graphics_address (XDR *xdrs, remote_domain_event_graphics_address *objp)
 {
 
diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h
index 8c4291f..6f01da7 100644
--- a/src/remote/remote_protocol.h
+++ b/src/remote/remote_protocol.h
@@ -1864,6 +1864,15 @@ struct remote_domain_event_io_error_msg {
 };
 typedef struct remote_domain_event_io_error_msg remote_domain_event_io_error_msg;
 
+struct remote_domain_event_io_error_reason_msg {
+        remote_nonnull_domain dom;
+        remote_nonnull_string srcPath;
+        remote_nonnull_string devAlias;
+        int action;
+        remote_nonnull_string reason;
+};
+typedef struct remote_domain_event_io_error_reason_msg remote_domain_event_io_error_reason_msg;
+
 struct remote_domain_event_graphics_address {
         int family;
         remote_nonnull_string node;
@@ -2206,6 +2215,7 @@ enum remote_procedure {
         REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
         REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
         REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
+        REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195,
 };
 typedef enum remote_procedure remote_procedure;
 
@@ -2541,6 +2551,7 @@ extern  bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_re
 extern  bool_t xdr_remote_domain_event_rtc_change_msg (XDR *, remote_domain_event_rtc_change_msg*);
 extern  bool_t xdr_remote_domain_event_watchdog_msg (XDR *, remote_domain_event_watchdog_msg*);
 extern  bool_t xdr_remote_domain_event_io_error_msg (XDR *, remote_domain_event_io_error_msg*);
+extern  bool_t xdr_remote_domain_event_io_error_reason_msg (XDR *, remote_domain_event_io_error_reason_msg*);
 extern  bool_t xdr_remote_domain_event_graphics_address (XDR *, remote_domain_event_graphics_address*);
 extern  bool_t xdr_remote_domain_event_graphics_identity (XDR *, remote_domain_event_graphics_identity*);
 extern  bool_t xdr_remote_domain_event_graphics_msg (XDR *, remote_domain_event_graphics_msg*);
@@ -2873,6 +2884,7 @@ extern bool_t xdr_remote_domain_event_reboot_msg ();
 extern bool_t xdr_remote_domain_event_rtc_change_msg ();
 extern bool_t xdr_remote_domain_event_watchdog_msg ();
 extern bool_t xdr_remote_domain_event_io_error_msg ();
+extern bool_t xdr_remote_domain_event_io_error_reason_msg ();
 extern bool_t xdr_remote_domain_event_graphics_address ();
 extern bool_t xdr_remote_domain_event_graphics_identity ();
 extern bool_t xdr_remote_domain_event_graphics_msg ();
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index ae306d2..8000ee0 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -1659,6 +1659,14 @@ struct remote_domain_event_io_error_msg {
     int action;
 };
 
+struct remote_domain_event_io_error_reason_msg {
+    remote_nonnull_domain dom;
+    remote_nonnull_string srcPath;
+    remote_nonnull_string devAlias;
+    int action;
+    remote_nonnull_string reason;
+};
+
 struct remote_domain_event_graphics_address {
     int family;
     remote_nonnull_string node;
@@ -1996,7 +2004,8 @@ enum remote_procedure {
     REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191,
     REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192,
     REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193,
-    REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194
+    REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194,
+    REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195
 
     /*
      * Notice how the entries are grouped in sets of 10 ?
-- 
1.6.6.1




More information about the libvir-list mailing list