[libvirt] [PATCH] Changes to clock timer XML to match final design.

Laine Stump laine at laine.org
Wed Mar 31 17:14:47 UTC 2010


The clock timer XML is being updated in the following ways (based on
further off-list discussion that was missed during the initial
implementation):

1) 'wallclock' is changed to 'track', and the possible values are 'boot'
 (corresponds to old 'host'), 'guest', and 'wall'.

2) 'mode' has an additional value 'smpsafe'

3) when tickpolicy='catchup', there can be an optional sub-element of
   timer called 'catchup':

   <catchup threshold=123 slew=120 limit=10000/>

Those three values are all longs, always optional, and if they are present,
they are positive. Internally, 0 indicates "unspecified".

* docs/schemas/domain.rng: updated RNG definition to account for changes

* src/conf/domain_conf.h: change the C struct and enums to match changes.

* src/conf/domain_conf.c: timer parse and format functions changed to
                          handle the new selections and new element.

* src/libvirt_private.syms: *TimerWallclock* changes to *TimerTrack*

* src/qemu/qemu_conf.c: again, account for Wallclock --> Track change.
---
 docs/schemas/domain.rng  |   24 +++++++++++-
 src/conf/domain_conf.c   |   89 +++++++++++++++++++++++++++++++++++----------
 src/conf/domain_conf.h   |   26 ++++++++++----
 src/libvirt_private.syms |    4 +-
 src/qemu/qemu_conf.c     |   17 +++++++--
 5 files changed, 126 insertions(+), 34 deletions(-)

diff --git a/docs/schemas/domain.rng b/docs/schemas/domain.rng
index d804301..228665c 100644
--- a/docs/schemas/domain.rng
+++ b/docs/schemas/domain.rng
@@ -344,10 +344,11 @@
         </choice>
       </attribute>
       <optional>
-        <attribute name="wallclock">
+        <attribute name="track">
           <choice>
-            <value>host</value>
+            <value>boot</value>
             <value>guest</value>
+            <value>wall</value>
           </choice>
         </attribute>
       </optional>
@@ -362,6 +363,9 @@
         </attribute>
       </optional>
       <optional>
+        <ref name="catchup"/>
+      </optional>
+      <optional>
         <attribute name="frequency">
           <ref name="unsignedInt"/>
         </attribute>
@@ -373,6 +377,7 @@
             <value>native</value>
             <value>emulate</value>
             <value>paravirt</value>
+            <value>smpsafe</value>
           </choice>
         </attribute>
       </optional>
@@ -387,6 +392,21 @@
       <empty/>
     </element>
   </define>
+  <define name="catchup">
+    <element name="catchup">
+      <optional>
+        <attribute name="threshold">
+          <ref name="unsignedInt"/>
+        </attribute>
+        <attribute name="slew">
+          <ref name="unsignedInt"/>
+        </attribute>
+        <attribute name="limit">
+          <ref name="unsignedInt"/>
+        </attribute>
+      </optional>
+    </element>
+  </define>
 <!--
       A bootloader may be used to extract the OS information instead of
       defining the OS parameter in the instance. It points just to the
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 66aa53e..b8acab9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -252,9 +252,10 @@ VIR_ENUM_IMPL(virDomainTimerName, VIR_DOMAIN_TIMER_NAME_LAST,
               "hpet",
               "tsc");
 
-VIR_ENUM_IMPL(virDomainTimerWallclock, VIR_DOMAIN_TIMER_WALLCLOCK_LAST,
-              "host",
-              "guest");
+VIR_ENUM_IMPL(virDomainTimerTrack, VIR_DOMAIN_TIMER_TRACK_LAST,
+              "boot",
+              "guest",
+              "wall");
 
 VIR_ENUM_IMPL(virDomainTimerTickpolicy, VIR_DOMAIN_TIMER_TICKPOLICY_LAST,
               "delay",
@@ -266,7 +267,8 @@ VIR_ENUM_IMPL(virDomainTimerMode, VIR_DOMAIN_TIMER_MODE_LAST,
               "auto",
               "native",
               "emulate",
-              "paravirt");
+              "paravirt",
+              "smpsafe");
 
 #define virDomainReportError(code, ...)                              \
     virReportErrorHelper(NULL, VIR_FROM_DOMAIN, code, __FILE__,      \
@@ -2555,7 +2557,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node,
     char *name = NULL;
     char *present = NULL;
     char *tickpolicy = NULL;
-    char *wallclock = NULL;
+    char *track = NULL;
     char *mode = NULL;
 
     virDomainTimerDefPtr def;
@@ -2603,12 +2605,12 @@ virDomainTimerDefParseXML(const xmlNodePtr node,
         }
     }
 
-    def->wallclock = -1;
-    wallclock = virXMLPropString(node, "wallclock");
-    if (wallclock != NULL) {
-        if ((def->wallclock = virDomainTimerWallclockTypeFromString(wallclock)) < 0) {
+    def->track = -1;
+    track = virXMLPropString(node, "track");
+    if (track != NULL) {
+        if ((def->track = virDomainTimerTrackTypeFromString(track)) < 0) {
             virDomainReportError(VIR_ERR_INTERNAL_ERROR,
-                                 _("unknown timer wallclock '%s'"), wallclock);
+                                 _("unknown timer track '%s'"), track);
             goto error;
         }
     }
@@ -2616,7 +2618,7 @@ virDomainTimerDefParseXML(const xmlNodePtr node,
     int ret = virXPathULong("string(./frequency)", ctxt, &def->frequency);
     if (ret == -1) {
         def->frequency = 0;
-    } else if (ret <= 0) {
+    } else if (ret < 0) {
         virDomainReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("invalid timer frequency"));
         goto error;
@@ -2632,11 +2634,42 @@ virDomainTimerDefParseXML(const xmlNodePtr node,
         }
     }
 
+    xmlNodePtr catchup = virXPathNode("./catchup", ctxt);
+    if (catchup != NULL) {
+        ret = virXPathULong("string(./catchup/@threshold)", ctxt,
+                            &def->catchup.threshold);
+        if (ret == -1) {
+            def->catchup.threshold = 0;
+        } else if (ret < 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("invalid catchup threshold"));
+            goto error;
+        }
+
+        ret = virXPathULong("string(./catchup/@slew)", ctxt, &def->catchup.slew);
+        if (ret == -1) {
+            def->catchup.slew = 0;
+        } else if (ret < 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("invalid catchup slew"));
+            goto error;
+        }
+
+        ret = virXPathULong("string(./catchup/@limit)", ctxt, &def->catchup.limit);
+        if (ret == -1) {
+            def->catchup.limit = 0;
+        } else if (ret < 0) {
+            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                 "%s", _("invalid catchup limit"));
+            goto error;
+        }
+    }
+
 cleanup:
     VIR_FREE(name);
     VIR_FREE(present);
     VIR_FREE(tickpolicy);
-    VIR_FREE(wallclock);
+    VIR_FREE(track);
     VIR_FREE(mode);
     ctxt->node = oldnode;
 
@@ -5456,16 +5489,16 @@ virDomainTimerDefFormat(virBufferPtr buf,
 
     if ((def->name == VIR_DOMAIN_TIMER_NAME_PLATFORM)
         || (def->name == VIR_DOMAIN_TIMER_NAME_RTC)) {
-        if (def->wallclock != -1) {
-            const char *wallclock
-                = virDomainTimerWallclockTypeToString(def->wallclock);
-            if (!wallclock) {
+        if (def->track != -1) {
+            const char *track
+                = virDomainTimerTrackTypeToString(def->track);
+            if (!track) {
                 virDomainReportError(VIR_ERR_INTERNAL_ERROR,
-                                     _("unexpected timer wallclock %d"),
-                                     def->wallclock);
+                                     _("unexpected timer track %d"),
+                                     def->track);
                 return -1;
             }
-            virBufferVSprintf(buf, " wallclock='%s'", wallclock);
+            virBufferVSprintf(buf, " track='%s'", track);
         }
     }
 
@@ -5487,7 +5520,23 @@ virDomainTimerDefFormat(virBufferPtr buf,
         }
     }
 
-    virBufferAddLit(buf, "/>\n");
+    if ((def->catchup.threshold == 0)
+        && (def->catchup.slew == 0)
+        && (def->catchup.limit == 0)) {
+        virBufferAddLit(buf, "/>\n");
+    } else {
+        virBufferAddLit(buf, ">\n      <catchup ");
+        if (def->catchup.threshold > 0) {
+            virBufferVSprintf(buf, " threshold='%lu'", def->catchup.threshold);
+        }
+        if (def->catchup.slew > 0) {
+            virBufferVSprintf(buf, " slew='%lu'", def->catchup.slew);
+        }
+        if (def->catchup.limit > 0) {
+            virBufferVSprintf(buf, " limit='%lu'", def->catchup.limit);
+        }
+        virBufferAddLit(buf, "/>\n    </timer>\n");
+    }
 
     return 0;
 }
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ed1a4ad..435d546 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -656,11 +656,12 @@ enum virDomainTimerNameType {
     VIR_DOMAIN_TIMER_NAME_LAST,
 };
 
-enum virDomainTimerWallclockType {
-    VIR_DOMAIN_TIMER_WALLCLOCK_HOST = 0,
-    VIR_DOMAIN_TIMER_WALLCLOCK_GUEST,
+enum virDomainTimerTrackType {
+    VIR_DOMAIN_TIMER_TRACK_BOOT = 0,
+    VIR_DOMAIN_TIMER_TRACK_GUEST,
+    VIR_DOMAIN_TIMER_TRACK_WALL,
 
-    VIR_DOMAIN_TIMER_WALLCLOCK_LAST,
+    VIR_DOMAIN_TIMER_TRACK_LAST,
 };
 
 enum virDomainTimerTickpolicyType {
@@ -677,10 +678,19 @@ enum virDomainTimerModeType {
     VIR_DOMAIN_TIMER_MODE_NATIVE,
     VIR_DOMAIN_TIMER_MODE_EMULATE,
     VIR_DOMAIN_TIMER_MODE_PARAVIRT,
+    VIR_DOMAIN_TIMER_MODE_SMPSAFE,
 
     VIR_DOMAIN_TIMER_MODE_LAST,
 };
 
+typedef struct _virDomainTimerCatchupDef virDomainTimerCatchupDef;
+typedef virDomainTimerCatchupDef *virDomainTimerCatchupDefPtr;
+struct _virDomainTimerCatchupDef {
+    unsigned long threshold;
+    unsigned long slew;
+    unsigned long limit;
+};
+
 typedef struct _virDomainTimerDef virDomainTimerDef;
 typedef virDomainTimerDef *virDomainTimerDefPtr;
 struct _virDomainTimerDef {
@@ -688,8 +698,10 @@ struct _virDomainTimerDef {
     int present;    /* unspecified = -1, no = 0, yes = 1 */
     int tickpolicy; /* none|catchup|merge|discard */
 
-    /* wallclock is only valid for name='platform|rtc' */
-    int wallclock;  /* host|guest */
+    virDomainTimerCatchupDef catchup;
+
+    /* track is only valid for name='platform|rtc' */
+    int track;  /* host|guest */
 
     /* frequency & mode are only valid for name='tsc' */
     unsigned long frequency; /* in Hz, unspecified = 0 */
@@ -1029,7 +1041,7 @@ VIR_ENUM_DECL(virDomainClockOffset)
 VIR_ENUM_DECL(virDomainNetdevMacvtap)
 
 VIR_ENUM_DECL(virDomainTimerName)
-VIR_ENUM_DECL(virDomainTimerWallclock)
+VIR_ENUM_DECL(virDomainTimerTrack)
 VIR_ENUM_DECL(virDomainTimerTickpolicy)
 VIR_ENUM_DECL(virDomainTimerMode)
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index cc943f8..08a6b97 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -199,8 +199,8 @@ virDomainClockOffsetTypeFromString;
 virDomainDiskErrorPolicyTypeToString;
 virDomainTimerNameTypeToString;
 virDomainTimerNameTypeFromString;
-virDomainTimerWallclockTypeToString;
-virDomainTimerWallclockTypeFromString;
+virDomainTimerTrackTypeToString;
+virDomainTimerTrackTypeFromString;
 virDomainTimerTickpolicyTypeToString;
 virDomainTimerTickpolicyTypeFromString;
 virDomainTimerModeTypeToString;
diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c
index 8f6f7ec..4f279be 100644
--- a/src/qemu/qemu_conf.c
+++ b/src/qemu/qemu_conf.c
@@ -3183,11 +3183,22 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
     int i;
     for (i = 0; i < def->ntimers; i++) {
         if (def->timers[i]->name == VIR_DOMAIN_TIMER_NAME_RTC) {
-            if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_HOST) {
-                virBufferAddLit(&buf, ",clock=host");
-            } else if (def->timers[i]->wallclock == VIR_DOMAIN_TIMER_WALLCLOCK_GUEST) {
+            switch (def->timers[i]->track) {
+            case -1: /* unspecified - use hypervisor default */
+                break;
+            case VIR_DOMAIN_TIMER_TRACK_BOOT:
+                qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                                _("unsupported rtc timer track '%s'"),
+                                virDomainTimerTrackTypeToString(def->timers[i]->track));
+                goto error;
+            case VIR_DOMAIN_TIMER_TRACK_GUEST:
                 virBufferAddLit(&buf, ",clock=vm");
+                break;
+            case VIR_DOMAIN_TIMER_TRACK_WALL:
+                virBufferAddLit(&buf, ",clock=host");
+                break;
             }
+
             switch (def->timers[i]->tickpolicy) {
             case -1:
             case VIR_DOMAIN_TIMER_TICKPOLICY_DELAY:
-- 
1.6.6.1




More information about the libvir-list mailing list