[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCHv2 2/2] 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.
---
Changes in V2:

* added rerror_policy to domaincommon.rng
* added "report" to the list of possible policies and to docs
* fix qemuParseCommandLineDisk to set rerror_policy and error_policy
  separately.
* add a new xml2argv & argv2xml test that sets error_policy='report'
  rerror_policy='ignore'.


 docs/formatdomain.html.in                          |   18 +++++++++--
 docs/schemas/domaincommon.rng                      |   13 ++++++++
 src/conf/domain_conf.c                             |   17 ++++++++++
 src/conf/domain_conf.h                             |    4 ++-
 src/qemu/qemu_command.c                            |   17 +++++++++-
 tests/qemuargv2xmltest.c                           |    1 +
 ...gv-disk-drive-error-policy-wreport-rignore.args |    6 +++
 ...rgv-disk-drive-error-policy-wreport-rignore.xml |   33 ++++++++++++++++++++
 tests/qemuxml2argvtest.c                           |    2 +
 9 files changed, 105 insertions(+), 6 deletions(-)
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args
 create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 593adcb..b15f9e2 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -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
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index cffaac2..492a41d 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -820,6 +820,9 @@
         <ref name="driverErrorPolicy"/>
       </optional>
       <optional>
+        <ref name="driverRerrorPolicy"/>
+      </optional>
+      <optional>
         <ref name="driverIO"/>
       </optional>
       <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>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 55e6c34..a537251 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -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)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bc41d34..56c9777 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -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;  /* 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 5f729a4..cf99f89 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 (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) {
diff --git a/tests/qemuargv2xmltest.c b/tests/qemuargv2xmltest.c
index 6a79630..807a771 100644
--- a/tests/qemuargv2xmltest.c
+++ b/tests/qemuargv2xmltest.c
@@ -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");
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args
new file mode 100644
index 0000000..4879576
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.args
@@ -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
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml
new file mode 100644
index 0000000..70068aa
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-disk-drive-error-policy-wreport-rignore.xml
@@ -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>
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 24e831c..3d65d5f 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -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,
-- 
1.7.3.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]