</li>
<li>
The optional <code>error_policy</code> attribute controls
- how the hypervisor will behave on an error, possible
- values are "stop", "ignore", and "enospace".
- <span class="since">Since 0.8.0</span>
+ how the hypervisor will behave on a disk read or write
+ error, possible values are "stop", "report", "ignore", and
+ "enospace".<span class="since">Since 0.8.0, "report" since
+ 0.9.7</span> The default setting of error_policy is "report".
+ There is also an
+ optional <code>rerror_policy</code> that controls behavior
+ for read errors only. <span class="since">Since
+ 0.9.7</space>. If no rerror_policy is given, error_policy
+ is used for both read and write errors. If rerror_policy
+ is given, it overrides the <code>error_policy</code> for
+ read errors. Also note that "enospace" is not a valid
+ policy for read errors, so if <code>error_policy</code> is
+ set to "enospace" and no <code>rerror_policy</code> is
+ given, the read error policy will be left at its default,
+ which is "report".
</li>
<li>
The optional <code>io</code> attribute controls specific
<optional>
<ref name="driverErrorPolicy"/>
</optional>
+ <optional>
+ <ref name="driverRerrorPolicy"/>
+ </optional>
<optional>
<ref name="driverIO"/>
</optional>
<attribute name="error_policy">
<choice>
<value>stop</value>
+ <value>report</value>
<value>ignore</value>
<value>enospace</value>
</choice>
</attribute>
</define>
+ <define name="driverRerrorPolicy">
+ <attribute name="rerror_policy">
+ <choice>
+ <value>stop</value>
+ <value>report</value>
+ <value>ignore</value>
+ </choice>
+ </attribute>
+ </define>
<define name="driverIO">
<attribute name="io">
<choice>
VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
"default",
"stop",
+ "report",
"ignore",
"enospace")
char *bus = NULL;
char *cachetag = NULL;
char *error_policy = NULL;
+ char *rerror_policy = NULL;
char *iotag = NULL;
char *ioeventfd = NULL;
char *event_idx = NULL;
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");
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) {
VIR_FREE(driverName);
VIR_FREE(cachetag);
VIR_FREE(error_policy);
+ VIR_FREE(rerror_policy);
VIR_FREE(iotag);
VIR_FREE(ioeventfd);
VIR_FREE(event_idx);
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);
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)
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,
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;
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
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);
}
}
+ 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) {
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");
--- /dev/null
+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
--- /dev/null
+<domain type='qemu'>
+ <name>QEMUGuest1</name>
+ <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
+ <memory>219136</memory>
+ <currentMemory>219136</currentMemory>
+ <vcpu>1</vcpu>
+ <os>
+ <type arch='i686' machine='pc'>hvm</type>
+ <boot dev='hd'/>
+ </os>
+ <clock offset='utc'/>
+ <on_poweroff>destroy</on_poweroff>
+ <on_reboot>restart</on_reboot>
+ <on_crash>destroy</on_crash>
+ <devices>
+ <emulator>/usr/bin/qemu</emulator>
+ <disk type='block' device='disk'>
+ <driver name='qemu' type='qcow2' cache='none' error_policy='report' rerror_policy='ignore'/>
+ <source dev='/dev/HostVG/QEMUGuest1'/>
+ <target dev='hda' bus='ide'/>
+ <address type='drive' controller='0' bus='0' unit='0'/>
+ </disk>
+ <disk type='block' device='cdrom'>
+ <driver name='qemu' type='raw'/>
+ <source dev='/dev/HostVG/QEMUGuest2'/>
+ <target dev='hdc' bus='ide'/>
+ <readonly/>
+ <address type='drive' controller='0' bus='1' unit='0'/>
+ </disk>
+ <controller type='ide' index='0'/>
+ <memballoon model='virtio'/>
+ </devices>
+</domain>
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,