mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 21:55:25 +00:00
qemu: add separate rerror_policy for disk errors
Previously libvirt's disk device XML only had a single attribute, error_policy, to control both read and write error policy, but qemu has separate options for controlling read and write. In one case (enospc) a policy is allowed for write errors but not read errors. This patch adds a separate attribute that sets only the read error policy. If just error_policy is set, it will apply to both read and write error policy (previous behavior), but if the new rerror_policy attribute is set, it will override error_policy for read errors only. Possible values for rerror_policy are "stop", "report", and "ignore" ("report" is the qemu-controlled default for rerror_policy when error_policy isn't specified). For consistency, the value "report" has been added to the possible values for error_policy as well.
This commit is contained in:
parent
91195b4321
commit
4bb4109f7b
@ -1008,9 +1008,21 @@
|
||||
</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
|
||||
|
@ -819,6 +819,9 @@
|
||||
<optional>
|
||||
<ref name="driverErrorPolicy"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="driverRerrorPolicy"/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name="driverIO"/>
|
||||
</optional>
|
||||
@ -856,11 +859,21 @@
|
||||
<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>
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
|
@ -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
|
@ -0,0 +1,33 @@
|
||||
<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>
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user