From 71d793faaf698f6c3a0546e516c48c1086cad58c 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 an explicit IO error event This introduces a new event type VIR_DOMAIN_EVENT_ID_IO_ERROR This event includes the action that is about to be taken as a result of the watchdog triggering typedef enum { VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0, VIR_DOMAIN_EVENT_IO_ERROR_PAUSE, VIR_DOMAIN_EVENT_IO_ERROR_REPORT, } virDomainEventIOErrorAction; In addition it has the source path of the disk that had the error and its unique device alias. It does not include the target device name (/dev/sda), since this would preclude triggering IO errors from other file backed devices (eg serial ports connected to a file) Thus there is a new callback definition for this event type typedef void (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, virDomainPtr dom, const char *srcPath, const char *devAlias, int action, 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 | 35 ++++++++++++ daemon/remote_dispatch_table.h | 5 ++ examples/domain-events/events-c/event-test.c | 23 +++++++- include/libvirt/libvirt.h.in | 33 +++++++++++ python/generator.py | 1 + src/conf/domain_event.c | 59 ++++++++++++++++++++ src/conf/domain_event.h | 9 +++ src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 57 +++++++++++++++++++ src/qemu/qemu_monitor.c | 17 ++++++ src/qemu/qemu_monitor.h | 7 +++ src/qemu/qemu_monitor_json.c | 38 ++++++++++++- src/remote/remote_driver.c | 34 +++++++++++ src/remote/remote_protocol.c | 15 +++++ src/remote/remote_protocol.h | 11 ++++ src/remote/remote_protocol.x | 10 +++- 16 files changed, 352 insertions(+), 4 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index 4bc7a45fc6..885e9d4bf5 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -217,11 +217,46 @@ static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, } +static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque) +{ + struct qemud_client *client = opaque; + remote_domain_event_io_error_msg data; + + if (!client) + return -1; + + REMOTE_DEBUG("Relaying domain io error %s %d %s %s %d", dom->name, dom->id, srcPath, devAlias, action); + + 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; + + remoteDispatchDomainEventSend (client, + REMOTE_PROC_DOMAIN_EVENT_IO_ERROR, + (xdrproc_t)xdr_remote_domain_event_io_error_msg, &data); + + virMutexUnlock(&client->lock); + + return 0; +} + + static virConnectDomainEventGenericCallback domainEventCallbacks[] = { VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventLifecycle), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventReboot), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventRTCChange), VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventWatchdog), + VIR_DOMAIN_EVENT_CALLBACK(remoteRelayDomainEventIOError), }; verify(ARRAY_CARDINALITY(domainEventCallbacks) == VIR_DOMAIN_EVENT_ID_LAST); diff --git a/daemon/remote_dispatch_table.h b/daemon/remote_dispatch_table.h index a0a74fe711..019212d61c 100644 --- a/daemon/remote_dispatch_table.h +++ b/daemon/remote_dispatch_table.h @@ -862,3 +862,8 @@ .args_filter = (xdrproc_t) xdr_void, .ret_filter = (xdrproc_t) xdr_void, }, +{ /* Async event DomainEventIoError => 172 */ + .fn = NULL, + .args_filter = (xdrproc_t) xdr_void, + .ret_filter = (xdrproc_t) xdr_void, +}, diff --git a/examples/domain-events/events-c/event-test.c b/examples/domain-events/events-c/event-test.c index 997af63e9f..bb3c7bbda6 100644 --- a/examples/domain-events/events-c/event-test.c +++ b/examples/domain-events/events-c/event-test.c @@ -204,6 +204,19 @@ static int myDomainEventWatchdogCallback(virConnectPtr conn ATTRIBUTE_UNUSED, return 0; } +static int myDomainEventIOErrorCallback(virConnectPtr conn ATTRIBUTE_UNUSED, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque ATTRIBUTE_UNUSED) +{ + printf("%s EVENT: Domain %s(%d) io error path=%s alias=%s action=%d\n", __func__, virDomainGetName(dom), + virDomainGetID(dom), srcPath, devAlias, action); + + return 0; +} + static void myFreeFunc(void *opaque) { char *str = opaque; @@ -324,6 +337,7 @@ int main(int argc, char **argv) int callback3ret = -1; int callback4ret = -1; int callback5ret = -1; + int callback6ret = -1; struct sigaction action_stop = { .sa_handler = stop @@ -376,12 +390,18 @@ int main(int argc, char **argv) VIR_DOMAIN_EVENT_ID_WATCHDOG, VIR_DOMAIN_EVENT_CALLBACK(myDomainEventWatchdogCallback), strdup("callback watchdog"), myFreeFunc); + callback6ret = virConnectDomainEventRegisterAny(dconn, + NULL, + VIR_DOMAIN_EVENT_ID_IO_ERROR, + VIR_DOMAIN_EVENT_CALLBACK(myDomainEventIOErrorCallback), + strdup("callback io error"), myFreeFunc); if ((callback1ret != -1) && (callback2ret != -1) && (callback3ret != -1) && (callback4ret != -1) && - (callback5ret != -1)) { + (callback5ret != -1) && + (callback6ret != -1)) { while(run) { struct pollfd pfd = { .fd = h_fd, .events = h_event, @@ -422,6 +442,7 @@ int main(int argc, char **argv) virConnectDomainEventDeregisterAny(dconn, callback3ret); virConnectDomainEventDeregisterAny(dconn, callback4ret); virConnectDomainEventDeregisterAny(dconn, callback5ret); + virConnectDomainEventDeregisterAny(dconn, callback6ret); } DEBUG0("Closing connection"); diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in index dace68fe3f..9c90768147 100644 --- a/include/libvirt/libvirt.h.in +++ b/include/libvirt/libvirt.h.in @@ -1908,6 +1908,38 @@ typedef void (*virConnectDomainEventWatchdogCallback)(virConnectPtr conn, int action, void *opaque); +/** + * virDomainEventIOErrorAction: + * + * The action that is to be taken due to an IO error occuring + */ +typedef enum { + VIR_DOMAIN_EVENT_IO_ERROR_NONE = 0, /* No action, IO error ignored */ + VIR_DOMAIN_EVENT_IO_ERROR_PAUSE, /* Guest CPUs are pausde */ + VIR_DOMAIN_EVENT_IO_ERROR_REPORT, /* IO error reported to guest OS */ +} virDomainEventIOErrorAction; + + +/** + * 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 + * @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 (*virConnectDomainEventIOErrorCallback)(virConnectPtr conn, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque); + /** * VIR_DOMAIN_EVENT_CALLBACK: * @@ -1922,6 +1954,7 @@ typedef enum { VIR_DOMAIN_EVENT_ID_REBOOT = 1, /* virConnectDomainEventGenericCallback */ VIR_DOMAIN_EVENT_ID_RTC_CHANGE = 2, /* virConnectDomainEventRTCChangeCallback */ VIR_DOMAIN_EVENT_ID_WATCHDOG = 3, /* virConnectDomainEventWatchdogCallback */ + VIR_DOMAIN_EVENT_ID_IO_ERROR = 4, /* virConnectDomainEventIOErrorCallback */ /* * NB: this enum value will increase over time as new events are diff --git a/python/generator.py b/python/generator.py index 95884464b4..73a8b2b8a5 100755 --- a/python/generator.py +++ b/python/generator.py @@ -172,6 +172,7 @@ skipped_types = { 'virConnectDomainEventGenericCallback': "No function types in python", 'virConnectDomainEventRTCChangeCallback': "No function types in python", 'virConnectDomainEventWatchdogCallback': "No function types in python", + 'virConnectDomainEventIOErrorCallback': "No function types in python", 'virEventAddHandleFunc': "No function types in python", } diff --git a/src/conf/domain_event.c b/src/conf/domain_event.c index 8e4678d96d..839c99bc03 100644 --- a/src/conf/domain_event.c +++ b/src/conf/domain_event.c @@ -70,6 +70,11 @@ struct _virDomainEvent { struct { int action; } watchdog; + struct { + char *srcPath; + char *devAlias; + int action; + } ioError; } data; }; @@ -458,6 +463,11 @@ void virDomainEventFree(virDomainEventPtr event) if (!event) return; + if (event->eventID == VIR_DOMAIN_EVENT_ID_IO_ERROR) { + VIR_FREE(event->data.ioError.srcPath); + VIR_FREE(event->data.ioError.devAlias); + } + VIR_FREE(event->dom.name); VIR_FREE(event); } @@ -590,6 +600,47 @@ virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, return ev; } +virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action) +{ + virDomainEventPtr ev = + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR, + 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))) { + virDomainEventFree(ev); + ev = NULL; + } + } + + return ev; +} +virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action) +{ + virDomainEventPtr ev = + virDomainEventNewInternal(VIR_DOMAIN_EVENT_ID_IO_ERROR, + obj->def->id, obj->def->name, obj->def->uuid); + + if (ev) { + ev->data.watchdog.action = action; + if (!(ev->data.ioError.srcPath = strdup(srcPath)) || + !(ev->data.ioError.devAlias = strdup(devAlias))) { + virDomainEventFree(ev); + ev = NULL; + } + } + + return ev; +} + /** * virDomainEventQueueFree: * @queue: pointer to the queue @@ -712,6 +763,14 @@ void virDomainEventDispatchDefaultFunc(virConnectPtr conn, cbopaque); break; + case VIR_DOMAIN_EVENT_ID_IO_ERROR: + ((virConnectDomainEventIOErrorCallback)cb)(conn, dom, + event->data.ioError.srcPath, + event->data.ioError.devAlias, + event->data.ioError.action, + cbopaque); + break; + default: VIR_WARN("Unexpected event ID %d", event->eventID); break; diff --git a/src/conf/domain_event.h b/src/conf/domain_event.h index 8f6a764c58..652c93744e 100644 --- a/src/conf/domain_event.h +++ b/src/conf/domain_event.h @@ -121,6 +121,15 @@ virDomainEventPtr virDomainEventRTCChangeNewFromObj(virDomainObjPtr obj, long lo virDomainEventPtr virDomainEventWatchdogNewFromDom(virDomainPtr dom, int action); virDomainEventPtr virDomainEventWatchdogNewFromObj(virDomainObjPtr obj, int action); +virDomainEventPtr virDomainEventIOErrorNewFromDom(virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action); +virDomainEventPtr virDomainEventIOErrorNewFromObj(virDomainObjPtr obj, + const char *srcPath, + const char *devAlias, + int action); + int virDomainEventQueuePush(virDomainEventQueuePtr evtQueue, virDomainEventPtr event); diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index ebe029b6be..f3dccd8812 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -220,6 +220,8 @@ virDomainEventRTCChangeNewFromDom; virDomainEventRTCChangeNewFromObj; virDomainEventWatchdogNewFromDom; virDomainEventWatchdogNewFromObj; +virDomainEventIOErrorNewFromDom; +virDomainEventIOErrorNewFromObj; virDomainEventFree; virDomainEventDispatchDefaultFunc; virDomainEventDispatch; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 9e6d7470a2..5898eda71c 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -756,6 +756,26 @@ findDomainDiskByPath(virDomainObjPtr vm, return NULL; } +static virDomainDiskDefPtr +findDomainDiskByAlias(virDomainObjPtr vm, + const char *alias) +{ + int i; + + for (i = 0; i < vm->def->ndisks; i++) { + virDomainDiskDefPtr disk; + + disk = vm->def->disks[i]; + if (disk->info.alias != NULL && STREQ(disk->info.alias, alias)) + return disk; + } + + qemuReportError(VIR_ERR_INTERNAL_ERROR, + _("no disk found with alias %s"), + alias); + return NULL; +} + static int getVolumeQcowPassphrase(virConnectPtr conn, virDomainDiskDefPtr disk, @@ -937,12 +957,49 @@ qemuHandleDomainWatchdog(qemuMonitorPtr mon ATTRIBUTE_UNUSED, } +static int +qemuHandleDomainIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, + virDomainObjPtr vm, + const char *diskAlias, + int action) +{ + struct qemud_driver *driver = qemu_driver; + virDomainEventPtr event; + const char *srcPath; + const char *devAlias; + virDomainDiskDefPtr disk; + + virDomainObjLock(vm); + disk = findDomainDiskByAlias(vm, diskAlias); + + if (disk) { + srcPath = disk->src; + devAlias = disk->info.alias; + } else { + srcPath = ""; + devAlias = ""; + } + + event = virDomainEventIOErrorNewFromObj(vm, srcPath, devAlias, action); + virDomainObjUnlock(vm); + + if (event) { + qemuDriverLock(driver); + qemuDomainEventQueue(driver, event); + qemuDriverUnlock(driver); + } + + return 0; +} + + static qemuMonitorCallbacks monitorCallbacks = { .eofNotify = qemuHandleMonitorEOF, .diskSecretLookup = findVolumeQcowPassphrase, .domainReset = qemuHandleDomainReset, .domainRTCChange = qemuHandleDomainRTCChange, .domainWatchdog = qemuHandleDomainWatchdog, + .domainIOError = qemuHandleDomainIOError, }; static int diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 8e2eb00ace..baf5bd8e4d 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -821,6 +821,23 @@ int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action) } +int qemuMonitorEmitIOError(qemuMonitorPtr mon, + const char *diskAlias, + int action) +{ + int ret = -1; + VIR_DEBUG("mon=%p", mon); + + qemuMonitorRef(mon); + qemuMonitorUnlock(mon); + if (mon->cb && mon->cb->domainIOError) + ret = mon->cb->domainIOError(mon, mon->vm, diskAlias, action); + qemuMonitorLock(mon); + qemuMonitorUnref(mon); + return ret; +} + + int qemuMonitorSetCapabilities(qemuMonitorPtr mon) { int ret; diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 9349eaa41b..ad5316f853 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -92,6 +92,10 @@ struct _qemuMonitorCallbacks { int (*domainWatchdog)(qemuMonitorPtr mon, virDomainObjPtr vm, int action); + int (*domainIOError)(qemuMonitorPtr mon, + virDomainObjPtr vm, + const char *diskAlias, + int action); }; @@ -130,6 +134,9 @@ int qemuMonitorEmitPowerdown(qemuMonitorPtr mon); int qemuMonitorEmitStop(qemuMonitorPtr mon); int qemuMonitorEmitRTCChange(qemuMonitorPtr mon, long long offset); int qemuMonitorEmitWatchdog(qemuMonitorPtr mon, int action); +int qemuMonitorEmitIOError(qemuMonitorPtr mon, + const char *diskAlias, + int action); int qemuMonitorStartCPUs(qemuMonitorPtr mon, virConnectPtr conn); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 767a4764c9..30ae80f1be 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -51,6 +51,7 @@ static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr d static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data); static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data); +static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data); struct { const char *type; @@ -62,6 +63,7 @@ struct { { "STOP", qemuMonitorJSONHandleStop, }, { "RTC_CHANGE", qemuMonitorJSONHandleRTCChange, }, { "WATCHDOG", qemuMonitorJSONHandleWatchdog, }, + { "DISK_IO_ERROR", qemuMonitorJSONHandleIOError, }, }; @@ -510,8 +512,8 @@ static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr d } VIR_ENUM_DECL(qemuMonitorWatchdogAction) -VIR_ENUM_IMPL(qemuMonitorWatchdogAction, VIR_DOMAIN_EVENT_WATCHDOG_DEBUG, - "none", "pause", "reset", "poweroff" "shutdown", "debug"); +VIR_ENUM_IMPL(qemuMonitorWatchdogAction, VIR_DOMAIN_EVENT_WATCHDOG_DEBUG + 1, + "none", "pause", "reset", "poweroff", "shutdown", "debug"); static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr data) { @@ -531,6 +533,38 @@ static void qemuMonitorJSONHandleWatchdog(qemuMonitorPtr mon, virJSONValuePtr da qemuMonitorEmitRTCChange(mon, actionID); } +VIR_ENUM_DECL(qemuMonitorIOErrorAction) +VIR_ENUM_IMPL(qemuMonitorIOErrorAction, VIR_DOMAIN_EVENT_IO_ERROR_REPORT + 1, + "ignore", "stop", "report"); + + +static void qemuMonitorJSONHandleIOError(qemuMonitorPtr mon, virJSONValuePtr data) +{ + const char *device; + const char *action; + int actionID; + + /* Throughout here we try our best to carry on upon errors, + since it's imporatant to get as much info as possible out + to the application */ + + if ((action = virJSONValueObjectGetString(data, "action")) == NULL) { + VIR_WARN0("Missing action in disk io error event"); + action = "ignore"; + } + + if ((device = virJSONValueObjectGetString(data, "device")) == NULL) { + VIR_WARN0("missing device in disk io error event"); + } + + 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); +} + int qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon) diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index b3cb36a0e9..91b3a832e8 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -6994,6 +6994,36 @@ remoteDomainReadEventWatchdog(virConnectPtr conn, XDR *xdr) } +static virDomainEventPtr +remoteDomainReadEventIOError(virConnectPtr conn, XDR *xdr) +{ + remote_domain_event_io_error_msg msg; + virDomainPtr dom; + virDomainEventPtr event = NULL; + memset (&msg, 0, sizeof msg); + + /* unmarshall parameters, and process it*/ + if (! xdr_remote_domain_event_io_error_msg(xdr, &msg) ) { + error (conn, VIR_ERR_RPC, + _("unable to demarshall reboot event")); + return NULL; + } + + dom = get_nonnull_domain(conn,msg.dom); + if (!dom) + return NULL; + + event = virDomainEventIOErrorNewFromDom(dom, + msg.srcPath, + msg.devAlias, + msg.action); + xdr_free ((xdrproc_t) &xdr_remote_domain_event_io_error_msg, (char *) &msg); + + virDomainFree(dom); + return event; +} + + static virDrvOpenStatus ATTRIBUTE_NONNULL (1) remoteSecretOpen (virConnectPtr conn, virConnectAuthPtr auth, @@ -8549,6 +8579,10 @@ processCallDispatchMessage(virConnectPtr conn, struct private_data *priv, event = remoteDomainReadEventWatchdog(conn, xdr); break; + case REMOTE_PROC_DOMAIN_EVENT_IO_ERROR: + event = remoteDomainReadEventIOError(conn, xdr); + break; + default: DEBUG("Unexpected event proc %d", hdr->proc); break; diff --git a/src/remote/remote_protocol.c b/src/remote/remote_protocol.c index e022235cab..66fcea7166 100644 --- a/src/remote/remote_protocol.c +++ b/src/remote/remote_protocol.c @@ -3081,6 +3081,21 @@ xdr_remote_domain_event_watchdog_msg (XDR *xdrs, remote_domain_event_watchdog_ms return TRUE; } +bool_t +xdr_remote_domain_event_io_error_msg (XDR *xdrs, remote_domain_event_io_error_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; + return TRUE; +} + bool_t xdr_remote_procedure (XDR *xdrs, remote_procedure *objp) { diff --git a/src/remote/remote_protocol.h b/src/remote/remote_protocol.h index 0d7eec5a8b..d49e8dcbab 100644 --- a/src/remote/remote_protocol.h +++ b/src/remote/remote_protocol.h @@ -1744,6 +1744,14 @@ struct remote_domain_event_watchdog_msg { int action; }; typedef struct remote_domain_event_watchdog_msg remote_domain_event_watchdog_msg; + +struct remote_domain_event_io_error_msg { + remote_nonnull_domain dom; + remote_nonnull_string srcPath; + remote_nonnull_string devAlias; + int action; +}; +typedef struct remote_domain_event_io_error_msg remote_domain_event_io_error_msg; #define REMOTE_PROGRAM 0x20008086 #define REMOTE_PROTOCOL_VERSION 1 @@ -1919,6 +1927,7 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169, REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170, REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171, + REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172, }; typedef enum remote_procedure remote_procedure; @@ -2235,6 +2244,7 @@ extern bool_t xdr_remote_domain_events_deregister_any_args (XDR *, remote_domai extern bool_t xdr_remote_domain_event_reboot_msg (XDR *, remote_domain_event_reboot_msg*); 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_procedure (XDR *, remote_procedure*); extern bool_t xdr_remote_message_type (XDR *, remote_message_type*); extern bool_t xdr_remote_message_status (XDR *, remote_message_status*); @@ -2525,6 +2535,7 @@ extern bool_t xdr_remote_domain_events_deregister_any_args (); 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_procedure (); extern bool_t xdr_remote_message_type (); extern bool_t xdr_remote_message_status (); diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index b3f622e1bd..24be558d99 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1550,6 +1550,13 @@ struct remote_domain_event_watchdog_msg { int action; }; +struct remote_domain_event_io_error_msg { + remote_nonnull_domain dom; + remote_nonnull_string srcPath; + remote_nonnull_string devAlias; + int action; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -1744,7 +1751,8 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169, REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170, - REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171 + REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171, + REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172 /* * Notice how the entries are grouped in sets of 10 ?