From 34dcbbb470fb8b93232b8bd709e949f9012a7462 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 18 Mar 2010 19:37:44 +0000 Subject: [PATCH] Add support for another explicit IO error event 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 | 8 ++- 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, 313 insertions(+), 21 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 6dbe7eea49..c54565c895 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 984634fae3..86bd3b0ae9 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 4237b7b2ce..f296d168d6 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -2053,6 +2053,28 @@ typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, int action, 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: * @@ -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 cb38e3fae3..df39b79ac9 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 7c7682c630..b97445b5eb 100644 --- a/python/libvirt-override.c +++ b/python/libvirt-override.c @@ -3207,6 +3207,58 @@ libvirt_virConnectDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED return ret; } +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, @@ -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 e3ce5ba156..e5bd458347 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 f72ac5822f..e28293dab1 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 746327dfdc..09f3da118b 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 42a653a431..08cff00d8b 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 5e83afc276..fca8590784 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 ec848a8ed9..3fa83b7cf1 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 09a356217a..4e8fbfca6b 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -514,6 +514,7 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat { const char *device; const char *action; + const char *reason; int actionID; /* Throughout here we try our best to carry on upon errors, @@ -529,12 +530,17 @@ static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr dat VIR_WARN0("missing device in disk io error event"); } + if ((reason = virJSONValueObjectGetString(data, "reason")) == NULL) { + VIR_WARN0("missing reason in disk io error event"); + reason = ""; + } + if ((actionID = qemuMonitorIOErrorActionTypeFromString(action)) < 0) { VIR_WARN("unknown disk io error action '%s'", action); actionID = VIR_DOMAIN_EVENT_IO_ERROR_NONE; } - qemuMonitorEmitIOError(mon, device, actionID); + qemuMonitorEmitIOError(mon, device, actionID, reason); } diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index e589f8e4a4..317125fb92 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -7429,6 +7429,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) { @@ -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 71eed42447..187281d780 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3289,6 +3289,23 @@ xdr_remote_domain_event_io_error_msg (XDR *xdrs, remote_domain_event_io_error_ms return TRUE; } +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 8c4291f065..6f01da75ab 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 ae306d2d26..8000ee0dfd 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 ?