From: Arun Menon <[email protected]>

SWTPM will support backup and fsync of the state file. [1] and [2]
Libvirt needs to support these options while launching a VM.
This commit adds these optional attributes to the RNG schema, and
updates the logic for both creation and parsing them from the XML.

[1] 
https://github.com/stefanberger/swtpm/commit/186f72a3a995fc68957ffc0b1438bb6e30d51ef0
[2] 
https://github.com/stefanberger/swtpm/commit/795c1973c913da59925fa6c2d688c5ef51cb5b73

Signed-off-by: Arun Menon <[email protected]>
---
 docs/formatdomain.rst                         | 15 +++++++++++++
 src/conf/domain_conf.c                        | 22 +++++++++++++++++++
 src/conf/domain_conf.h                        |  2 ++
 src/conf/schemas/domaincommon.rng             | 10 +++++++++
 .../qemuxmlconfdata/tpm-emulator-tpm2-enc.xml |  2 +-
 5 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index e4eb2d9ba3..402c3ab221 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8932,6 +8932,21 @@ Example: usage of external TPM emulator :since:`Since 
9.0.0`
    This attribute only works with the ``emulator`` backend. The accepted values
    are ``yes`` and ``no``. :since:`Since 7.0.0`
 
+``backup``
+  The optional ``backup`` attribute controls whether swtpm creates a
+  backup of its TPM state file before updating it. Enabling backup
+  protects against TPM state file corruption if swtpm process crashes
+  unexpectedly. Disabling backups avoids file-copying overhead. The
+  accepted values are ``yes`` and ``no``. :since:`Since 12.8.0`
+
+``fsync``
+  The optional ``fsync`` attribute controls whether swtpm explicitly
+  flushes its state changes to the physical storage using fsync().
+  Enabling fsync ensures data remains consistent across host power loss,
+  but might introduces I/O latency. Disabling fsync removes this latency
+  at the expense of host-level crash resilience. Acceptable
+  values are ``yes`` and ``no``. :since:`Since 12.8.0`
+
 ``active_pcr_banks``
    The ``active_pcr_banks`` node is used to define which of the PCR banks
    of a TPM 2.0 to activate. Valid names are for example sha1, sha256, sha384,
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 1327793b0a..283658849a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -11449,6 +11449,11 @@ virDomainSmartcardDefParseXML(virDomainXMLOption 
*xmlopt,
  *   </backend>
  * </tpm>
  *
+ * Emulator state backup and fsync is supported with the following:
+ * <tpm model='tpm-crb'>
+ *   <backend type='emulator' version='2.0' backup='yes' fsync='yes'>
+ * </tpm>
+ *
  */
 static virDomainTPMDef *
 virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
@@ -11562,6 +11567,16 @@ virDomainTPMDefParseXML(virDomainXMLOption *xmlopt,
             }
         }
 
+        if (virXMLPropTristateBool(backends[0], "backup",
+                                   VIR_XML_PROP_NONE,
+                                   &def->data.emulator.backup) < 0)
+            goto error;
+
+        if (virXMLPropTristateBool(backends[0], "fsync",
+                                   VIR_XML_PROP_NONE,
+                                   &def->data.emulator.fsync) < 0)
+            goto error;
+
         if ((nnodes = virXPathNodeSet("./backend/active_pcr_banks/*", ctxt, 
&nodes)) < 0)
             break;
         if (nnodes > 0)
@@ -26743,6 +26758,13 @@ virDomainTPMDefFormat(virBuffer *buf,
         }
         if (def->data.emulator.persistent_state)
             virBufferAddLit(&backendAttrBuf, " persistent_state='yes'");
+
+        if (def->data.emulator.backup)
+            virBufferAddLit(&backendAttrBuf, " backup='yes'");
+
+        if (def->data.emulator.fsync)
+            virBufferAddLit(&backendAttrBuf, " fsync='yes'");
+
         if (def->data.emulator.debug != 0)
             virBufferAsprintf(&backendAttrBuf, " debug='%u'",
                               def->data.emulator.debug);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f7cbe7bf1d..fd022ea66f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1546,6 +1546,8 @@ struct _virDomainTPMEmulatorDef {
         char *name;   /* name read from active profile */
         virDomainTPMProfileRemoveDisabled removeDisabled;
     } profile;
+    virTristateBool backup;
+    virTristateBool fsync;
 };
 
 struct _virDomainTPMDef {
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 0c0a3597a9..13de7ce528 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6208,6 +6208,16 @@
               <ref name="uint8"/>
             </attribute>
           </optional>
+          <optional>
+            <attribute name="backup">
+              <ref name="virYesNo"/>
+            </attribute>
+          </optional>
+          <optional>
+            <attribute name="fsync">
+              <ref name="virYesNo"/>
+            </attribute>
+          </optional>
         </group>
         <group>
           <attribute name="type">
diff --git a/tests/qemuxmlconfdata/tpm-emulator-tpm2-enc.xml 
b/tests/qemuxmlconfdata/tpm-emulator-tpm2-enc.xml
index e6746d5739..515831ab8c 100644
--- a/tests/qemuxmlconfdata/tpm-emulator-tpm2-enc.xml
+++ b/tests/qemuxmlconfdata/tpm-emulator-tpm2-enc.xml
@@ -28,7 +28,7 @@
     <input type='mouse' bus='ps2'/>
     <input type='keyboard' bus='ps2'/>
     <tpm model='tpm-tis'>
-      <backend type='emulator' version='2.0'>
+      <backend type='emulator' version='2.0' backup='yes' fsync='yes'>
         <encryption secret='32ee7e76-2178-47a1-ab7b-269e6e348015'/>
         <source type='dir' path='/some/dir'/>
       </backend>
-- 
2.54.0

Reply via email to