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

[libvirt] [PATCH] qemu: Report the offset from host UTC for RTC_CHANGE event



https://bugzilla.redhat.com/show_bug.cgi?id=964177

Though both libvirt and QEMU's document say RTC_CHANGE returns
the offset from the host UTC, qemu actually returns the offset
from the specified date instead when specific date is privided
(-rtc base=$date).

It's not safe for qemu to fix it in code, it worked like that
for 3 years, changing it now may break other QEMU use cases.
What qemu tries to do is to fix the document:

http://lists.gnu.org/archive/html/qemu-devel/2013-05/msg04782.html

And in libvirt side, instead of reply on the qemu, this covert
the offset returned from qemu to the offset from host UTC, by:

  /*
   * a: the offset from qemu RTC_CHANGE event
   * b: The specified date (-rtc base=$date)
   * c: the host date when libvirt gets the RTC_CHANGE event
   * offset: What libvirt will report
   */

  offset = a + (b - c);

The specified date (-rtc base=$date) is recorded in clock's def as
an internal only member (may be useful to exposed outside?).
---
 src/conf/domain_conf.h  |  3 +++
 src/qemu/qemu_command.c |  3 +++
 src/qemu/qemu_process.c | 12 ++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3a71d6c..3947a56 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1767,6 +1767,9 @@ struct _virDomainClockDef {
         struct {
             long long adjustment;
             int basis;
+
+            /* Store the start time of guest process, internaly only */
+            time_t starttime;
         } variable;
 
         /* Timezone name, when
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c4a162a..9254525 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5518,6 +5518,9 @@ qemuBuildClockArgStr(virDomainClockDefPtr def)
         now += def->data.variable.adjustment;
         gmtime_r(&now, &nowbits);
 
+        /* Store the starttime of qemu process */
+        def->data.variable.starttime = now;
+
         virBufferAsprintf(&buf, "base=%d-%02d-%02dT%02d:%02d:%02d",
                           nowbits.tm_year + 1900,
                           nowbits.tm_mon + 1,
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d4fd4fb..e6f0b6d 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -796,6 +796,18 @@ qemuProcessHandleRTCChange(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
 
     virObjectLock(vm);
+
+    /* QEMU's RTC_CHANGE event returns the offset from the specified
+     * date instead of the host UTC if a specific date is provided
+     * (-rtc base=$date). We need to convert it to be offset from
+     * host UTC.
+     */
+    if (vm->def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE) {
+        time_t now = time(NULL);
+
+        offset += vm->def->clock.data.variable.starttime - now;
+    }
+
     event = virDomainEventRTCChangeNewFromObj(vm, offset);
 
     if (vm->def->clock.offset == VIR_DOMAIN_CLOCK_OFFSET_VARIABLE)
-- 
1.8.1.4


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