On Tue, Feb 16, 2010 at 05:04:04PM +0000, Daniel P. Berrange wrote: > With the QMP mode monitor, it is possible to get a notification > that a disk I/O error occurs ina guest. This patch enables such > reporting and when receiving an error updates libvirt's view > of the guest to indicate that it is now paused. It also emits > an event > > VIR_DOMAIN_EVENT_SUSPENDED > > with a detail of: > > VIR_DOMAIN_EVENT_SUSPENDED_IOERROR > > * include/libvirt/libvirt.h.in: Add VIR_DOMAIN_EVENT_SUSPENDED_IOERROR > * src/qemu/qemu_driver.c: Update VM state to paused when IO error > occurrs > * src/qemu/qemu_monitor.c, src/qemu/qemu_monitor.h, > src/qemu/qemu_monitor_json.c: Wire up handlers for disk IO errors > --- > include/libvirt/libvirt.h.in | 1 + > src/qemu/qemu_conf.c | 7 +++++-- > src/qemu/qemu_conf.h | 2 +- > src/qemu/qemu_driver.c | 38 +++++++++++++++++++++++++++++++++++--- > src/qemu/qemu_monitor.c | 16 ++++++++++++++++ > src/qemu/qemu_monitor.h | 5 +++++ > src/qemu/qemu_monitor_json.c | 6 ++++++ > 7 files changed, 69 insertions(+), 6 deletions(-) > > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index 260505e..b7a6922 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -1361,6 +1361,7 @@ typedef enum { > typedef enum { > VIR_DOMAIN_EVENT_SUSPENDED_PAUSED = 0, /* Normal suspend due to admin pause */ > VIR_DOMAIN_EVENT_SUSPENDED_MIGRATED = 1, /* Suspended for offline migration */ > + VIR_DOMAIN_EVENT_SUSPENDED_IOERROR = 2, /* Suspended due to a disk I/O error */ > } virDomainEventSuspendedDetailType; > > /** > diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c > index c9fe55b..20076bc 100644 > --- a/src/qemu/qemu_conf.c > +++ b/src/qemu/qemu_conf.c > @@ -2385,6 +2385,9 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, > } else if (disk->shared && !disk->readonly) { > virBufferAddLit(&opt, ",cache=off"); > } > + if (qemuCmdFlags & QEMUD_CMD_FLAG_MONITOR_JSON) { > + virBufferVSprintf(&opt, ",werror=stop,rerror=stop"); > + } > > if (virBufferError(&opt)) { > virReportOOMError(); > @@ -2400,7 +2403,7 @@ error: > > > char * > -qemuBuildDriveDevStr(virDomainDiskDefPtr disk) > +qemuBuildDriveDevStr(virDomainDiskDefPtr disk, int qemuCmdFlags ATTRIBUTE_UNUSED) > { > virBuffer opt = VIR_BUFFER_INITIALIZER; > const char *bus = virDomainDiskQEMUBusTypeToString(disk->bus); > @@ -3578,7 +3581,7 @@ int qemudBuildCommandLine(virConnectPtr conn, > } else { > ADD_ARG_LIT("-device"); > > - if (!(optstr = qemuBuildDriveDevStr(disk))) > + if (!(optstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) > goto error; > ADD_ARG(optstr); > } > diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h > index 7041489..ec8033a 100644 > --- a/src/qemu/qemu_conf.h > +++ b/src/qemu/qemu_conf.h > @@ -214,7 +214,7 @@ char *qemuBuildDriveStr(virDomainDiskDefPtr disk, > unsigned long long qemuCmdFlags); > > /* Current, best practice */ > -char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk); > +char * qemuBuildDriveDevStr(virDomainDiskDefPtr disk, int qemuCmdFlags); > /* Current, best practice */ > char * qemuBuildControllerDevStr(virDomainControllerDefPtr def); > > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index 77306f3..23073bc 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -824,9 +824,41 @@ cleanup: > return ret; > } > > + > +static int > +qemuHandleDiskIOError(qemuMonitorPtr mon ATTRIBUTE_UNUSED, > + virDomainObjPtr vm, > + const char *diskalias ATTRIBUTE_UNUSED) > +{ > + struct qemud_driver *driver = qemu_driver; > + virDomainEventPtr event = NULL; > + > + VIR_DEBUG("Received IO error on %p '%s': %s", vm, vm->def->name, diskalias); > + virDomainObjLock(vm); > + > + vm->state = VIR_DOMAIN_PAUSED; > + event = virDomainEventNewFromObj(vm, > + VIR_DOMAIN_EVENT_SUSPENDED, > + VIR_DOMAIN_EVENT_SUSPENDED_IOERROR); > + > + if (virDomainSaveStatus(driver->caps, driver->stateDir, vm) < 0) > + VIR_WARN("Unable to save status on vm %s after IO error", vm->def->name); > + > + virDomainObjUnlock(vm); > + > + if (event) { > + qemuDriverLock(driver); > + qemuDomainEventQueue(driver, event); > + qemuDriverUnlock(driver); > + } > + return 0; > +} > + > + > static qemuMonitorCallbacks monitorCallbacks = { > .eofNotify = qemuHandleMonitorEOF, > .diskSecretLookup = findVolumeQcowPassphrase, > + .diskIOError = qemuHandleDiskIOError, > }; > > static int > @@ -5353,7 +5385,7 @@ static int qemudDomainAttachPciDiskDevice(struct qemud_driver *driver, > if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags))) > goto error; > > - if (!(devstr = qemuBuildDriveDevStr(disk))) > + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) > goto error; > } > > @@ -5548,7 +5580,7 @@ static int qemudDomainAttachSCSIDisk(struct qemud_driver *driver, > if (qemuCmdFlags & QEMUD_CMD_FLAG_DEVICE) { > if (qemuAssignDeviceDiskAlias(disk, qemuCmdFlags) < 0) > goto error; > - if (!(devstr = qemuBuildDriveDevStr(disk))) > + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) > goto error; > } > > @@ -5652,7 +5684,7 @@ static int qemudDomainAttachUsbMassstorageDevice(struct qemud_driver *driver, > goto error; > if (!(drivestr = qemuBuildDriveStr(disk, 0, qemuCmdFlags))) > goto error; > - if (!(devstr = qemuBuildDriveDevStr(disk))) > + if (!(devstr = qemuBuildDriveDevStr(disk, qemuCmdFlags))) > goto error; > } > > diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c > index b88532c..3f8772a 100644 > --- a/src/qemu/qemu_monitor.c > +++ b/src/qemu/qemu_monitor.c > @@ -791,6 +791,22 @@ int qemuMonitorEmitStop(qemuMonitorPtr mon) > } > > > +int qemuMonitorEmitDiskIOError(qemuMonitorPtr mon, const char *deviceAlias) > +{ > + int ret = -1; > + VIR_DEBUG("mon=%p deviceAlias=%s", mon, deviceAlias); > + > + qemuMonitorRef(mon); > + qemuMonitorUnlock(mon); > + if (mon->cb && mon->cb->diskIOError) > + ret = mon->cb->diskIOError(mon, mon->vm, deviceAlias); > + 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 0ac3957..6b9fd50 100644 > --- a/src/qemu/qemu_monitor.h > +++ b/src/qemu/qemu_monitor.h > @@ -86,6 +86,10 @@ struct _qemuMonitorCallbacks { > virDomainObjPtr vm); > int (*domainStop)(qemuMonitorPtr mon, > virDomainObjPtr vm); > + > + int (*diskIOError)(qemuMonitorPtr mon, > + virDomainObjPtr vm, > + const char *diskAlias); > }; > > > @@ -122,6 +126,7 @@ int qemuMonitorEmitShutdown(qemuMonitorPtr mon); > int qemuMonitorEmitReset(qemuMonitorPtr mon); > int qemuMonitorEmitPowerdown(qemuMonitorPtr mon); > int qemuMonitorEmitStop(qemuMonitorPtr mon); > +int qemuMonitorEmitDiskIOError(qemuMonitorPtr mon, const char *deviceAlias); > > int qemuMonitorStartCPUs(qemuMonitorPtr mon, > virConnectPtr conn); > diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c > index 49e0370..c20d063 100644 > --- a/src/qemu/qemu_monitor_json.c > +++ b/src/qemu/qemu_monitor_json.c > @@ -49,6 +49,7 @@ static void qemuMonitorJSONHandleShutdown(qemuMonitorPtr mon, virJSONValuePtr da > static void qemuMonitorJSONHandleReset(qemuMonitorPtr mon, virJSONValuePtr data); > static void qemuMonitorJSONHandlePowerdown(qemuMonitorPtr mon, virJSONValuePtr data); > static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data); > +static void qemuMonitorJSONHandleDiskIOError(qemuMonitorPtr mon, virJSONValuePtr data); > > struct { > const char *type; > @@ -58,6 +59,7 @@ struct { > { "RESET", qemuMonitorJSONHandleReset, }, > { "POWERDOWN", qemuMonitorJSONHandlePowerdown, }, > { "STOP", qemuMonitorJSONHandleStop, }, > + { "BLOCK_IO_ERROR", qemuMonitorJSONHandleDiskIOError, }, > }; > > > @@ -495,6 +497,10 @@ static void qemuMonitorJSONHandleStop(qemuMonitorPtr mon, virJSONValuePtr data A > qemuMonitorEmitStop(mon); > } > > +static void qemuMonitorJSONHandleDiskIOError(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED) > +{ > + qemuMonitorEmitDiskIOError(mon, NULL); > +} > > int > qemuMonitorJSONSetCapabilities(qemuMonitorPtr mon) > -- > 1.6.2.5 > ACK, I think that adding this unconditionally if supported is the right thing to do. Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@xxxxxxxxxxxx | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/ -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list