mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-13 00:01:55 +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>
|
||||||
<li>
|
<li>
|
||||||
The optional <code>error_policy</code> attribute controls
|
The optional <code>error_policy</code> attribute controls
|
||||||
how the hypervisor will behave on an error, possible
|
how the hypervisor will behave on a disk read or write
|
||||||
values are "stop", "ignore", and "enospace".
|
error, possible values are "stop", "report", "ignore", and
|
||||||
<span class="since">Since 0.8.0</span>
|
"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>
|
||||||
<li>
|
<li>
|
||||||
The optional <code>io</code> attribute controls specific
|
The optional <code>io</code> attribute controls specific
|
||||||
|
@ -819,6 +819,9 @@
|
|||||||
<optional>
|
<optional>
|
||||||
<ref name="driverErrorPolicy"/>
|
<ref name="driverErrorPolicy"/>
|
||||||
</optional>
|
</optional>
|
||||||
|
<optional>
|
||||||
|
<ref name="driverRerrorPolicy"/>
|
||||||
|
</optional>
|
||||||
<optional>
|
<optional>
|
||||||
<ref name="driverIO"/>
|
<ref name="driverIO"/>
|
||||||
</optional>
|
</optional>
|
||||||
@ -856,11 +859,21 @@
|
|||||||
<attribute name="error_policy">
|
<attribute name="error_policy">
|
||||||
<choice>
|
<choice>
|
||||||
<value>stop</value>
|
<value>stop</value>
|
||||||
|
<value>report</value>
|
||||||
<value>ignore</value>
|
<value>ignore</value>
|
||||||
<value>enospace</value>
|
<value>enospace</value>
|
||||||
</choice>
|
</choice>
|
||||||
</attribute>
|
</attribute>
|
||||||
</define>
|
</define>
|
||||||
|
<define name="driverRerrorPolicy">
|
||||||
|
<attribute name="rerror_policy">
|
||||||
|
<choice>
|
||||||
|
<value>stop</value>
|
||||||
|
<value>report</value>
|
||||||
|
<value>ignore</value>
|
||||||
|
</choice>
|
||||||
|
</attribute>
|
||||||
|
</define>
|
||||||
<define name="driverIO">
|
<define name="driverIO">
|
||||||
<attribute name="io">
|
<attribute name="io">
|
||||||
<choice>
|
<choice>
|
||||||
|
@ -176,6 +176,7 @@ VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
|
|||||||
VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
|
VIR_ENUM_IMPL(virDomainDiskErrorPolicy, VIR_DOMAIN_DISK_ERROR_POLICY_LAST,
|
||||||
"default",
|
"default",
|
||||||
"stop",
|
"stop",
|
||||||
|
"report",
|
||||||
"ignore",
|
"ignore",
|
||||||
"enospace")
|
"enospace")
|
||||||
|
|
||||||
@ -2297,6 +2298,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
char *bus = NULL;
|
char *bus = NULL;
|
||||||
char *cachetag = NULL;
|
char *cachetag = NULL;
|
||||||
char *error_policy = NULL;
|
char *error_policy = NULL;
|
||||||
|
char *rerror_policy = NULL;
|
||||||
char *iotag = NULL;
|
char *iotag = NULL;
|
||||||
char *ioeventfd = NULL;
|
char *ioeventfd = NULL;
|
||||||
char *event_idx = NULL;
|
char *event_idx = NULL;
|
||||||
@ -2416,6 +2418,7 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
driverType = virXMLPropString(cur, "type");
|
driverType = virXMLPropString(cur, "type");
|
||||||
cachetag = virXMLPropString(cur, "cache");
|
cachetag = virXMLPropString(cur, "cache");
|
||||||
error_policy = virXMLPropString(cur, "error_policy");
|
error_policy = virXMLPropString(cur, "error_policy");
|
||||||
|
rerror_policy = virXMLPropString(cur, "rerror_policy");
|
||||||
iotag = virXMLPropString(cur, "io");
|
iotag = virXMLPropString(cur, "io");
|
||||||
ioeventfd = virXMLPropString(cur, "ioeventfd");
|
ioeventfd = virXMLPropString(cur, "ioeventfd");
|
||||||
event_idx = virXMLPropString(cur, "event_idx");
|
event_idx = virXMLPropString(cur, "event_idx");
|
||||||
@ -2560,6 +2563,16 @@ virDomainDiskDefParseXML(virCapsPtr caps,
|
|||||||
goto error;
|
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 (iotag) {
|
||||||
if ((def->iomode = virDomainDiskIoTypeFromString(iotag)) < 0 ||
|
if ((def->iomode = virDomainDiskIoTypeFromString(iotag)) < 0 ||
|
||||||
def->iomode == VIR_DOMAIN_DISK_IO_DEFAULT) {
|
def->iomode == VIR_DOMAIN_DISK_IO_DEFAULT) {
|
||||||
@ -2667,6 +2680,7 @@ cleanup:
|
|||||||
VIR_FREE(driverName);
|
VIR_FREE(driverName);
|
||||||
VIR_FREE(cachetag);
|
VIR_FREE(cachetag);
|
||||||
VIR_FREE(error_policy);
|
VIR_FREE(error_policy);
|
||||||
|
VIR_FREE(rerror_policy);
|
||||||
VIR_FREE(iotag);
|
VIR_FREE(iotag);
|
||||||
VIR_FREE(ioeventfd);
|
VIR_FREE(ioeventfd);
|
||||||
VIR_FREE(event_idx);
|
VIR_FREE(event_idx);
|
||||||
@ -9127,6 +9141,7 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
const char *bus = virDomainDiskBusTypeToString(def->bus);
|
const char *bus = virDomainDiskBusTypeToString(def->bus);
|
||||||
const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
|
const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
|
||||||
const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy);
|
const char *error_policy = virDomainDiskErrorPolicyTypeToString(def->error_policy);
|
||||||
|
const char *rerror_policy = virDomainDiskErrorPolicyTypeToString(def->rerror_policy);
|
||||||
const char *iomode = virDomainDiskIoTypeToString(def->iomode);
|
const char *iomode = virDomainDiskIoTypeToString(def->iomode);
|
||||||
const char *ioeventfd = virDomainIoEventFdTypeToString(def->ioeventfd);
|
const char *ioeventfd = virDomainIoEventFdTypeToString(def->ioeventfd);
|
||||||
const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
|
const char *event_idx = virDomainVirtioEventIdxTypeToString(def->event_idx);
|
||||||
@ -9177,6 +9192,8 @@ virDomainDiskDefFormat(virBufferPtr buf,
|
|||||||
virBufferAsprintf(buf, " cache='%s'", cachemode);
|
virBufferAsprintf(buf, " cache='%s'", cachemode);
|
||||||
if (def->error_policy)
|
if (def->error_policy)
|
||||||
virBufferAsprintf(buf, " error_policy='%s'", error_policy);
|
virBufferAsprintf(buf, " error_policy='%s'", error_policy);
|
||||||
|
if (def->rerror_policy)
|
||||||
|
virBufferAsprintf(buf, " rerror_policy='%s'", rerror_policy);
|
||||||
if (def->iomode)
|
if (def->iomode)
|
||||||
virBufferAsprintf(buf, " io='%s'", iomode);
|
virBufferAsprintf(buf, " io='%s'", iomode);
|
||||||
if (def->ioeventfd)
|
if (def->ioeventfd)
|
||||||
|
@ -209,6 +209,7 @@ enum virDomainDiskCache {
|
|||||||
enum virDomainDiskErrorPolicy {
|
enum virDomainDiskErrorPolicy {
|
||||||
VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT,
|
VIR_DOMAIN_DISK_ERROR_POLICY_DEFAULT,
|
||||||
VIR_DOMAIN_DISK_ERROR_POLICY_STOP,
|
VIR_DOMAIN_DISK_ERROR_POLICY_STOP,
|
||||||
|
VIR_DOMAIN_DISK_ERROR_POLICY_REPORT,
|
||||||
VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE,
|
VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE,
|
||||||
VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE,
|
VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE,
|
||||||
|
|
||||||
@ -284,7 +285,8 @@ struct _virDomainDiskDef {
|
|||||||
char *driverType;
|
char *driverType;
|
||||||
char *serial;
|
char *serial;
|
||||||
int cachemode;
|
int cachemode;
|
||||||
int error_policy;
|
int error_policy; /* enum virDomainDiskErrorPolicy */
|
||||||
|
int rerror_policy; /* enum virDomainDiskErrorPolicy */
|
||||||
int bootIndex;
|
int bootIndex;
|
||||||
int iomode;
|
int iomode;
|
||||||
int ioeventfd;
|
int ioeventfd;
|
||||||
|
@ -1696,6 +1696,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk,
|
|||||||
|
|
||||||
if (disk->error_policy)
|
if (disk->error_policy)
|
||||||
wpolicy = virDomainDiskErrorPolicyTypeToString(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) {
|
if (disk->error_policy == VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE) {
|
||||||
/* in the case of enospace, the option is spelled
|
/* in the case of enospace, the option is spelled
|
||||||
@ -5631,14 +5633,22 @@ qemuParseCommandLineDisk(virCapsPtr caps,
|
|||||||
def->cachemode = VIR_DOMAIN_DISK_CACHE_DIRECTSYNC;
|
def->cachemode = VIR_DOMAIN_DISK_CACHE_DIRECTSYNC;
|
||||||
else if (STREQ(values[i], "unsafe"))
|
else if (STREQ(values[i], "unsafe"))
|
||||||
def->cachemode = VIR_DOMAIN_DISK_CACHE_UNSAFE;
|
def->cachemode = VIR_DOMAIN_DISK_CACHE_UNSAFE;
|
||||||
} else if (STREQ(keywords[i], "werror") ||
|
} else if (STREQ(keywords[i], "werror")) {
|
||||||
STREQ(keywords[i], "rerror")) {
|
|
||||||
if (STREQ(values[i], "stop"))
|
if (STREQ(values[i], "stop"))
|
||||||
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_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"))
|
else if (STREQ(values[i], "ignore"))
|
||||||
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE;
|
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_IGNORE;
|
||||||
else if (STREQ(values[i], "enospc"))
|
else if (STREQ(values[i], "enospc"))
|
||||||
def->error_policy = VIR_DOMAIN_DISK_ERROR_POLICY_ENOSPACE;
|
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")) {
|
} else if (STREQ(keywords[i], "index")) {
|
||||||
if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) {
|
if (virStrToLong_i(values[i], NULL, 10, &idx) < 0) {
|
||||||
virDomainDiskDefFree(def);
|
virDomainDiskDefFree(def);
|
||||||
@ -5674,6 +5684,9 @@ qemuParseCommandLineDisk(virCapsPtr caps,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (def->rerror_policy == def->error_policy)
|
||||||
|
def->rerror_policy = 0;
|
||||||
|
|
||||||
if (!def->src &&
|
if (!def->src &&
|
||||||
def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
|
def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
|
||||||
def->type != VIR_DOMAIN_DISK_TYPE_NETWORK) {
|
def->type != VIR_DOMAIN_DISK_TYPE_NETWORK) {
|
||||||
|
@ -165,6 +165,7 @@ mymain(void)
|
|||||||
DO_TEST("disk-drive-cache-v1-none");
|
DO_TEST("disk-drive-cache-v1-none");
|
||||||
DO_TEST("disk-drive-error-policy-stop");
|
DO_TEST("disk-drive-error-policy-stop");
|
||||||
DO_TEST("disk-drive-error-policy-enospace");
|
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-wt");
|
||||||
DO_TEST("disk-drive-cache-v2-wb");
|
DO_TEST("disk-drive-cache-v2-wb");
|
||||||
DO_TEST("disk-drive-cache-v2-none");
|
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);
|
QEMU_CAPS_DRIVE, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_DRIVE_FORMAT);
|
||||||
DO_TEST("disk-drive-error-policy-enospace", false,
|
DO_TEST("disk-drive-error-policy-enospace", false,
|
||||||
QEMU_CAPS_DRIVE, QEMU_CAPS_MONITOR_JSON, QEMU_CAPS_DRIVE_FORMAT);
|
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,
|
DO_TEST("disk-drive-cache-v2-wt", false,
|
||||||
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);
|
QEMU_CAPS_DRIVE, QEMU_CAPS_DRIVE_CACHE_V2, QEMU_CAPS_DRIVE_FORMAT);
|
||||||
DO_TEST("disk-drive-cache-v2-wb", false,
|
DO_TEST("disk-drive-cache-v2-wb", false,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user