libvirt's XML only had a single attribute, error_policy to control both read and write error policy, but qemu has separate settings for these. 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. --- docs/formatdomain.html.in | 16 +++++++++++++--- src/conf/domain_conf.c | 16 ++++++++++++++++ src/conf/domain_conf.h | 3 ++- src/qemu/qemu_command.c | 5 ++++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 593adcb..5265b21 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1008,9 +1008,19 @@ </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", "ignore", and + "enospace".<span class="since">Since 0.8.0</span> 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 automatically set to + "ignore". </li> <li> The optional <code>io</code> attribute controls specific diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index f9007ce..95e1a9a 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -2297,6 +2297,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 +2417,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 +2562,16 @@ virDomainDiskDefParseXML(virCapsPtr caps, goto error; } + if (rerror_policy && + (((def->rerror_policy + = virDomainDiskErrorPolicyTypeFromString(error_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 +2679,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 +9140,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 +9191,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 bc41d34..35eacc7 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -284,7 +284,8 @@ struct _virDomainDiskDef { char *driverType; char *serial; int cachemode; - int error_policy; + int error_policy; /* virDomainDiskErrorPolicy */ + int rerror_policy; /* virDomainDiskErrorPolicy */ int bootIndex; int iomode; int ioeventfd; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 123bcab..4f1bb25 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 (!rpolicy) rpolicy = wpolicy; @@ -1704,7 +1706,8 @@ qemuBuildDriveStr(virDomainDiskDefPtr disk, * and it's only valid for werror, not for rerror. */ wpolicy="enospc"; - rpolicy="ignore"; + if (!disk->rerror_policy) + rpolicy="ignore"; } if (wpolicy) -- 1.7.3.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list