]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
Add support for 'dpofua' setting for SCSI disks
authorPeter Krempa <pkrempa@redhat.com>
Fri, 21 Nov 2025 13:46:21 +0000 (14:46 +0100)
committerPeter Krempa <pkrempa@redhat.com>
Mon, 24 Nov 2025 15:40:32 +0000 (16:40 +0100)
Add the 'dpofua' setting in the XML and for the qemu driver.

DPO - Disable Page Out and FUA - Force Unit Access are two features
implemented by SCSI disks (either both together or neither of them)
which influence how caching is handled. QEMU provides a good default
but in certain specific occasions changing the default may have
performance benefits.

Add support for setting them via the XML.

Signed-off-by: Peter Krempa <pkrempa@redhat.com>
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
docs/formatdomain.rst
src/conf/domain_conf.c
src/conf/domain_conf.h
src/conf/domain_validate.c
src/conf/schemas/domaincommon.rng
src/qemu/qemu_command.c
tests/qemuxmlconfdata/disk-scsi.x86_64-latest.args
tests/qemuxmlconfdata/disk-scsi.x86_64-latest.xml
tests/qemuxmlconfdata/disk-scsi.xml

index 160e7ad9c7a0ef5243d5e030f6e938ab8f915189..eb1536df7b0a31ac9f6585e9cd638e3e89a59f8c 100644 (file)
@@ -3378,6 +3378,11 @@ paravirtualized driver is specified via the ``disk`` element.
    :since:`since after 0.4.4`; "sata" attribute value :since:`since 0.9.7`;
    "removable" attribute value :since:`since 1.1.3`;
    "rotation_rate" attribute value :since:`since 7.3.0`
+   The optional attribute ``dpofua`` (:since:`Since 11.10.0, only QEMU driver`)
+   controls the support of DPO(Disable Page Out) and FUA(Force Unit Access)
+   properties of a SCSI disk cache access (both must be present or absent).
+   If the value is omitted hypervisor default is applied (which may depend on
+   the machine type version) and is the suggested setting.
 ``throttlefilters``
    The optional ``throttlefilters`` element provides the ability to provide additional
    per-device throttle chain :since:`Since 11.2.0`
index af1b682499b03b4859c44a8c3ff63e8a2030d696..541dad5bdc92222b550d0cf9da69e214333ff381 100644 (file)
@@ -8597,6 +8597,10 @@ virDomainDiskDefParseXML(virDomainXMLOption *xmlopt,
         if (virXMLPropUInt(targetNode, "rotation_rate", 10, VIR_XML_PROP_NONE,
                            &def->rotation_rate) < 0)
             return NULL;
+
+        if (virXMLPropTristateSwitch(targetNode, "dpofua", VIR_XML_PROP_NONE,
+                                     &def->dpofua) < 0)
+            return NULL;
     }
 
     if ((geometryNode = virXPathNode("./geometry", ctxt))) {
@@ -20904,6 +20908,14 @@ virDomainDiskDefCheckABIStability(virDomainDiskDef *src,
         return false;
     }
 
+    if (src->dpofua != dst->dpofua) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target disk 'dpofua' property %1$s does not match source %2$s"),
+                       virTristateSwitchTypeToString(dst->dpofua),
+                       virTristateSwitchTypeToString(src->dpofua));
+        return false;
+    }
+
     if (src->queues != dst->queues) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target disk queue count %1$u does not match source %2$u"),
@@ -24179,6 +24191,9 @@ virDomainDiskDefFormat(virBuffer *buf,
     }
     if (def->rotation_rate)
         virBufferAsprintf(&childBuf, " rotation_rate='%u'", def->rotation_rate);
+    if (def->dpofua != VIR_TRISTATE_SWITCH_ABSENT)
+        virBufferAsprintf(&childBuf, " dpofua='%s'",
+                          virTristateSwitchTypeToString(def->dpofua));
     virBufferAddLit(&childBuf, "/>\n");
 
     virDomainDiskDefFormatIotune(&childBuf, def);
index 4fd8342950ea2753138d970c638c91bc977e22f2..cb35ff06bd19a3178f1e1f11de9619fb1e9c708c 100644 (file)
@@ -601,6 +601,7 @@ struct _virDomainDiskDef {
     unsigned int queue_size;
     virDomainDiskModel model;
     virDomainVirtioOptions *virtio;
+    virTristateSwitch dpofua; /* only SCSI disks; control of the DPO/FUA cache setting */
 
     bool diskElementAuth;
     bool diskElementEnc;
index 8bbea5f000a61108dbbaf4053dc3c2f36422181a..4558e7b210b552971240c78868791f82e49090d7 100644 (file)
@@ -1024,6 +1024,13 @@ virDomainDiskDefValidate(const virDomainDef *def,
         }
     }
 
+    if (disk->dpofua != VIR_TRISTATE_SWITCH_ABSENT &&
+        disk->bus != VIR_DOMAIN_DISK_BUS_SCSI) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                       _("'dpofua' option is available only for SCSI disks"));
+            return -1;
+    }
+
     return 0;
 }
 
index d3255e2dd8527960b99c8d5417bfd243806e07a2..1f9ac102a071a7604933668d0689a1580707ddef 100644 (file)
           <ref name="positiveInteger"/>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="dpofua">
+          <ref name="virOnOff"/>
+        </attribute>
+      </optional>
     </element>
   </define>
   <define name="geometry">
index 0c1d39bdd260d61ee630f06df12b3d84428b4366..b69fe23236772edcc19daff58c188f8fe44beaf7 100644 (file)
@@ -1936,6 +1936,7 @@ qemuBuildDiskDeviceProps(const virDomainDef *def,
                               "S:werror", wpolicy,
                               "S:rerror", rpolicy,
                               "A:stats-intervals", &statistics,
+                              "T:dpofua", disk->dpofua, /* SCSI-only, ensured by validation */
                               NULL) < 0)
         return NULL;
 
index cd07cd2d22ad7b4a9df773907a96146618073073..ae0a1ffe0cd93ffaa5c3169abb6e89f7b6c308f8 100644 (file)
@@ -41,9 +41,9 @@ XDG_CONFIG_HOME=/var/lib/libvirt/qemu/domain--1-QEMUGuest1/.config \
 -blockdev '{"driver":"file","filename":"/tmp/scsidisk3.img","node-name":"libvirt-3-storage","read-only":false}' \
 -device '{"driver":"scsi-hd","bus":"scsi2.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi2-0-0-0","drive":"libvirt-3-storage","id":"scsi2-0-0-0","wwn":5764824127192592812}' \
 -blockdev '{"driver":"file","filename":"/tmp/scsidisk4.img","node-name":"libvirt-2-storage","read-only":false}' \
--device '{"driver":"scsi-hd","bus":"scsi3.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi3-0-0-0","drive":"libvirt-2-storage","id":"scsi3-0-0-0"}' \
+-device '{"driver":"scsi-hd","bus":"scsi3.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi3-0-0-0","drive":"libvirt-2-storage","id":"scsi3-0-0-0","dpofua":true}' \
 -blockdev '{"driver":"file","filename":"/tmp/scsidisk5.img","node-name":"libvirt-1-storage","read-only":false}' \
--device '{"driver":"scsi-hd","bus":"scsi4.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi4-0-0-0","drive":"libvirt-1-storage","id":"scsi4-0-0-0","removable":true}' \
+-device '{"driver":"scsi-hd","bus":"scsi4.0","channel":0,"scsi-id":0,"lun":0,"device_id":"drive-scsi4-0-0-0","drive":"libvirt-1-storage","id":"scsi4-0-0-0","removable":true,"dpofua":false}' \
 -audiodev '{"id":"audio1","driver":"none"}' \
 -device '{"driver":"virtio-balloon-pci","id":"balloon0","bus":"pci.0","addr":"0x6"}' \
 -sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,resourcecontrol=deny \
index 3e645ea343eb91f98f64b3f61767578b889ffdf5..33de2a6595c94139b0a53cea5c31dd7f50bb08c7 100644 (file)
     <disk type='file' device='disk'>
       <driver name='qemu' type='raw'/>
       <source file='/tmp/scsidisk4.img'/>
-      <target dev='sdd' bus='scsi'/>
+      <target dev='sdd' bus='scsi' dpofua='on'/>
       <address type='drive' controller='3' bus='0' target='0' unit='0'/>
     </disk>
     <disk type='file' device='disk'>
       <driver name='qemu' type='raw'/>
       <source file='/tmp/scsidisk5.img'/>
-      <target dev='sde' bus='scsi'/>
+      <target dev='sde' bus='scsi' dpofua='off'/>
       <address type='drive' controller='4' bus='0' target='0' unit='0'/>
     </disk>
     <controller type='usb' index='0' model='piix3-uhci'>
index 755c856b982e1f4525ead2415e67f258b2782b18..7e20c70dfedb1d5e82d2881f575d2d1c09af3a08 100644 (file)
     </disk>
     <disk type='file' device='disk'>
       <source file='/tmp/scsidisk4.img'/>
-      <target dev='sdd' bus='scsi'/>
+      <target dev='sdd' bus='scsi' dpofua='on'/>
       <address type='drive' controller='3' bus='0' target='0' unit='0'/>
     </disk>
     <disk type='file' device='disk'>
       <source file='/tmp/scsidisk5.img'/>
-      <target dev='sde' bus='scsi' removable='on'/>
+      <target dev='sde' bus='scsi' removable='on' dpofua='off'/>
       <address type='drive' controller='4' bus='0' target='0' unit='0'/>
     </disk>
     <controller type='usb' index='0'/>