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