diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 593adcbacc..b15f9e20f1 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1008,9 +1008,21 @@
The optional error_policy
attribute controls
- how the hypervisor will behave on an error, possible
- values are "stop", "ignore", and "enospace".
- Since 0.8.0
+ how the hypervisor will behave on a disk read or write
+ error, possible values are "stop", "report", "ignore", and
+ "enospace".Since 0.8.0, "report" since
+ 0.9.7 The default setting of error_policy is "report".
+ There is also an
+ optional rerror_policy
that controls behavior
+ for read errors only. Since
+ 0.9.7. If no rerror_policy is given, error_policy
+ is used for both read and write errors. If rerror_policy
+ is given, it overrides the error_policy
for
+ read errors. Also note that "enospace" is not a valid
+ policy for read errors, so if error_policy
is
+ set to "enospace" and no rerror_policy
is
+ given, the read error policy will be left at its default,
+ which is "report".
The optional io
attribute controls specific
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index cffaac2fe7..492a41dee2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -819,6 +819,9 @@
+
+
+
@@ -856,11 +859,21 @@
stop
+ report
ignore
enospace
+
+
+
+ stop
+ report
+ ignore
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 55e6c3433d..a537251f3d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -176,6 +176,7 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
"default",
"stop",
+ "report",
"ignore",
"enospace")
@@ -2297,6 +2298,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
char *bus = NULL;
char *cachetag = NULL;
char *error_policy = NULL;
+ char *rerror_policy = NULL;
char *iotag = NULL;
char *ioeventfd = NULL;
char *event_idx = NULL;
@@ -2416,6 +2418,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
driverType = virXMLPropString(cur, "type");
cachetag = virXMLPropString(cur, "cache");
error_policy = virXMLPropString(cur, "error_policy");
+ rerror_policy = virXMLPropString(cur, "rerror_policy");
iotag = virXMLPropString(cur, "io");
ioeventfd = virXMLPropString(cur, "ioeventfd");
event_idx = virXMLPropString(cur, "event_idx");
@@ -2560,6 +2563,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
goto error;
}
+ if (rerror_policy &&
+ (((def->rerror_policy
+ = virDomainDiskErrorPolicyTypeFromString(rerror_policy)) <= 0) ||
+ (def->rerror_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE))) {
+ virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+ _("unknown disk read error policy '%s'"),
+ rerror_policy);
+ goto error;
+ }
+
if (iotag) {
if ((def->iomode = virDomainDiskIoTypeFromString(iotag)) < 0 ||
def->iomode == VIR_DOMAIN_DISK_IO_DEFAULT) {
@@ -2667,6 +2680,7 @@ cleanup:
VIR_FREE(driverName);
VIR_FREE(cachetag);
VIR_FREE(error_policy);
+ VIR_FREE(rerror_policy);
VIR_FREE(iotag);
VIR_FREE(ioeventfd);
VIR_FREE(event_idx);
@@ -9127,6 +9141,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
const char *bus = virDomainDiskBusTypeToString(def->bus);
const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy);
+ const char *rerror_policy = virDomainDiskErrorPolicyTypeToString(def->rerror_policy);
const char *iomode = virDomainDiskIoTypeToString(def->iomode);
const char *ioeventfd = virDomainIoEventFdTypeToString(def->ioeventfd);
const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
@@ -9177,6 +9192,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
virBufferAsprintf(buf, " cache='%s'", cachemode);
if (def->error_policy)
virBufferAsprintf(buf, " error_policy='%s'", error_policy);
+ if (def->rerror_policy)
+ virBufferAsprintf(buf, " rerror_policy='%s'", rerror_policy);
if (def->iomode)
virBufferAsprintf(buf, " io='%s'", iomode);
if (def->ioeventfd)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bc41d34d62..e07fd2f718 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -209,6 +209,7 @@ enum virDomainDiskCache {
enum virDomainDiskErrorPolicy {
VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT,
VIR_DOMAIN_DISK_ERROR_POLICY_STOP,
+ VIR_DOMAIN_DISK_ERROR_POLICY_REPORT,
VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE,
VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE,
@@ -284,7 +285,8 @@ struct _virDomainDiskDef {
char *driverType;
char *serial;
int cachemode;
- int error_policy;
+ int error_policy; /* enum virDomainDiskErrorPolicy */
+ int rerror_policy; /* enum virDomainDiskErrorPolicy */
int bootIndex;
int iomode;
int ioeventfd;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 5f729a4fa1..cf99f89e0c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1696,6 +1696,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
if (disk->error_policy)
wpolicy = virDomainDiskErrorPolicyTypeToString(disk->error_policy);
+ if (disk->rerror_policy)
+ rpolicy = virDomainDiskErrorPolicyTypeToString(disk->rerror_policy);
if (disk->error_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE) {
/* in the case of enospace, the option is spelled
@@ -5631,14 +5633,22 @@ qemuParseCommandLineDisk(virCapsPtr caps,
def->cachemode = VIR_DOMAIN_DISK_CACHE_DIRECTSYNC;
else if (STREQ(values[i], "unsafe"))
def->cachemode = VIR_DOMAIN_DISK_CACHE_UNSAFE;
- } else if (STREQ(keywords[i], "werror") ||
- STREQ(keywords[i], "rerror")) {
+ } else if (STREQ(keywords[i], "werror")) {
if (STREQ(values[i], "stop"))
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP;
+ else if (STREQ(values[i], "report"))
+ def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_REPORT;
else if (STREQ(values[i], "ignore"))
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE;
else if (STREQ(values[i], "enospc"))
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE;
+ } else if (STREQ(keywords[i], "rerror")) {
+ if (STREQ(values[i], "stop"))
+ def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_STOP;
+ else if (STREQ(values[i], "report"))
+ def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_REPORT;
+ else if (STREQ(values[i], "ignore"))
+ def->rerror_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE;
} else if (STREQ(keywords[i], "index")) {
if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) {
virDomainDiskDefFree(def);
@@ -5674,6 +5684,9 @@ qemuParseCommandLineDisk(virCapsPtr caps,
}
}
+ if (def->rerror_policy == def->error_policy)
+ def->rerror_policy = 0;
+
if (!def->src &&
def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
def->type != VIR_DOMAIN_DISK_TYPE_NETWORK) {
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 6a79630865..807a771f23 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -165,6 +165,7 @@ mymain(void)
DO_TEST("disk-drive-cache-v1-none");
DO_TEST("disk-drive-error-policy-stop");
DO_TEST("disk-drive-error-policy-enospace");
+ DO_TEST("disk-drive-error-policy-wreport-rignore");
DO_TEST("disk-drive-cache-v2-wt");
DO_TEST("disk-drive-cache-v2-wb");
DO_TEST("disk-drive-cache-v2-none");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args
new file mode 100644
index 0000000000..48795760f5
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args
@@ -0,0 +1,6 @@
+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=report,rerror=ignore -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-wreport-rignore.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml
new file mode 100644
index 0000000000..70068aa4d6
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 24e831cf0a..3d65d5f64b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -334,6 +334,8 @@ mymain(void)
QEMU_CAPS_DRIVE, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-error-policy-enospace", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_DRIVE_FORMAT);
+ DO_TEST("disk-drive-error-policy-wreport-rignore", false,
+ QEMU_CAPS_DRIVE, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-cache-v2-wt", false,
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);
DO_TEST("disk-drive-cache-v2-wb", false,