diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng index 5a8c82be23..e59e103f46 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -521,6 +521,9 @@ + + + @@ -543,6 +546,14 @@ + + + + stop + ignore + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 8fcd7f358e..c802a1c558 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -124,6 +124,11 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST, "writethrough", "writeback") +VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST, + "default", + "stop", + "ignore") + VIR_ENUM_IMPL(virDomainController, VIR_DOMAIN_CONTROLLER_TYPE_LAST, "ide", "fdc", @@ -1303,6 +1308,7 @@ virDomainDiskDefParseXML(xmlNodePtr node, char *target = NULL; char *bus = NULL; char *cachetag = NULL; + char *error_policy = NULL; char *devaddr = NULL; virStorageEncryptionPtr encryption = NULL; char *serial = NULL; @@ -1368,6 +1374,7 @@ virDomainDiskDefParseXML(xmlNodePtr node, driverName = virXMLPropString(cur, "name"); driverType = virXMLPropString(cur, "type"); cachetag = virXMLPropString(cur, "cache"); + error_policy = virXMLPropString(cur, "error_policy"); } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) { def->readonly = 1; } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) { @@ -1484,6 +1491,13 @@ virDomainDiskDefParseXML(xmlNodePtr node, goto error; } + if (error_policy && + (def->error_policy = virDomainDiskErrorPolicyTypeFromString(error_policy)) < 0) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown disk error policy '%s'"), error_policy); + goto error; + } + if (devaddr) { if (sscanf(devaddr, "%x:%x:%x", &def->info.addr.pci.domain, @@ -1526,6 +1540,7 @@ cleanup: VIR_FREE(driverType); VIR_FREE(driverName); VIR_FREE(cachetag); + VIR_FREE(error_policy); VIR_FREE(devaddr); VIR_FREE(serial); virStorageEncryptionFree(encryption); @@ -4651,6 +4666,7 @@ virDomainDiskDefFormat(virBufferPtr buf, const char *device = virDomainDiskDeviceTypeToString(def->device); const char *bus = virDomainDiskBusTypeToString(def->bus); const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode); + const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy); if (!type) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, @@ -4685,6 +4701,8 @@ virDomainDiskDefFormat(virBufferPtr buf, virBufferVSprintf(buf, " type='%s'", def->driverType); if (def->cachemode) virBufferVSprintf(buf, " cache='%s'", cachemode); + if (def->error_policy) + virBufferVSprintf(buf, " error_policy='%s'", error_policy); virBufferVSprintf(buf, "/>\n"); } diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index d97aa45ec2..67a68c975a 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -152,6 +152,14 @@ enum virDomainDiskCache { VIR_DOMAIN_DISK_CACHE_LAST }; +enum virDomainDiskErrorPolicy { + VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT, + VIR_DOMAIN_DISK_ERROR_POLICY_STOP, + VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE, + + VIR_DOMAIN_DISK_ERROR_POLICY_LAST +}; + /* Stores the virtual disk configuration */ typedef struct _virDomainDiskDef virDomainDiskDef; typedef virDomainDiskDef *virDomainDiskDefPtr; @@ -165,6 +173,7 @@ struct _virDomainDiskDef { char *driverType; char *serial; int cachemode; + int error_policy; unsigned int readonly : 1; unsigned int shared : 1; virDomainDeviceInfo info; @@ -941,6 +950,7 @@ VIR_ENUM_DECL(virDomainDisk) VIR_ENUM_DECL(virDomainDiskDevice) VIR_ENUM_DECL(virDomainDiskBus) VIR_ENUM_DECL(virDomainDiskCache) +VIR_ENUM_DECL(virDomainDiskErrorPolicy) VIR_ENUM_DECL(virDomainController) VIR_ENUM_DECL(virDomainFS) VIR_ENUM_DECL(virDomainNet) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index b7334cc4b3..3485b947a3 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -194,7 +194,7 @@ virDomainDefClearDeviceAliases; virDomainDeviceInfoIterate; virDomainClockOffsetTypeToString; virDomainClockOffsetTypeFromString; - +virDomainDiskErrorPolicyTypeToString; # domain_event.h virDomainEventCallbackListAdd; diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 4636194b6e..616af6e817 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -2470,6 +2470,14 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, virBufferAddLit(&opt, ",cache=off"); } + if (qemuCmdFlags & QEMUD_CMD_FLAG_MONITOR_JSON) { + if (disk->error_policy) { + virBufferVSprintf(&opt, ",werror=%s,rerror=%s", + virDomainDiskErrorPolicyTypeToString(disk->error_policy), + virDomainDiskErrorPolicyTypeToString(disk->error_policy)); + } + } + if (virBufferError(&opt)) { virReportOOMError(); goto error; @@ -4759,6 +4767,12 @@ qemuParseCommandLineDisk(const char *val, def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITEBACK; else if (STREQ(values[i], "writethrough")) def->cachemode = VIR_DOMAIN_DISK_CACHE_WRITETHRU; + } else if (STREQ(keywords[i], "werror") || + STREQ(keywords[i], "rerror")) { + if (STREQ(values[i], "stop")) + def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP; + else if (STREQ(values[i], "ignore")) + def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE; } else if (STREQ(keywords[i], "index")) { if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) { virDomainDiskDefFree(def); diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c index 2197438d30..b3302388d0 100644 --- a/tests/qemuargv2xmltest.c +++ b/tests/qemuargv2xmltest.c @@ -162,6 +162,9 @@ mymain(int argc, char **argv) /*DO_TEST("disk-drive-cache-v1-wt", QEMUD_CMD_FLAG_DRIVE);*/ DO_TEST("disk-drive-cache-v1-wb", QEMUD_CMD_FLAG_DRIVE); DO_TEST("disk-drive-cache-v1-none", QEMUD_CMD_FLAG_DRIVE); + DO_TEST("disk-drive-error-policy-stop", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_MONITOR_JSON | + QEMUD_CMD_FLAG_DRIVE_FORMAT); DO_TEST("disk-drive-cache-v2-wt", QEMUD_CMD_FLAG_DRIVE | QEMUD_CMD_FLAG_DRIVE_CACHE_V2); DO_TEST("disk-drive-cache-v2-wb", QEMUD_CMD_FLAG_DRIVE | diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.args new file mode 100644 index 0000000000..765f6a4344 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.args @@ -0,0 +1 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M pc -m 214 -smp 1 -nographic -monitor unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -drive file=/dev/HostVG/QEMUGuest1,if=ide,bus=0,unit=0,format=qcow2,cache=off,werror=stop,rerror=stop -drive file=/dev/HostVG/QEMUGuest2,if=ide,media=cdrom,bus=1,unit=0,format=raw -net none -serial none -parallel none -usb diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.xml new file mode 100644 index 0000000000..67e23ccfe4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-stop.xml @@ -0,0 +1,32 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219200 + 219200 + 1 + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + + +
+ + + + + + +
+ + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index e3762c957a..c98de192cd 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -261,6 +261,9 @@ mymain(int argc, char **argv) QEMUD_CMD_FLAG_DRIVE_FORMAT); DO_TEST("disk-drive-cache-v1-none", QEMUD_CMD_FLAG_DRIVE | QEMUD_CMD_FLAG_DRIVE_FORMAT); + DO_TEST("disk-drive-error-policy-stop", QEMUD_CMD_FLAG_DRIVE | + QEMUD_CMD_FLAG_MONITOR_JSON | + QEMUD_CMD_FLAG_DRIVE_FORMAT); DO_TEST("disk-drive-cache-v2-wt", QEMUD_CMD_FLAG_DRIVE | QEMUD_CMD_FLAG_DRIVE_CACHE_V2 | QEMUD_CMD_FLAG_DRIVE_FORMAT); DO_TEST("disk-drive-cache-v2-wb", QEMUD_CMD_FLAG_DRIVE |