diff mbox

[v5] MC146818 RTC: coordinate guest clock base to destination host after migration

Message ID 20160926124101.2364-1-zhongjun@sangfor.com.cn
State New
Headers show

Commit Message

zhongjun@sangfor.com.cn Sept. 26, 2016, 12:41 p.m. UTC
qemu tracks guest time based on vector [base_rtc, last_update], in which
last_update stands for a monotonic tick which is actually uptime of the
host.
according to rtc implementation codes of recent releases and upstream,
after
migration, the time base vector [base_rtc, last_update] isn't updated to
coordinate with the destionation host, ie. qemu doesnt update last_update
to
uptime of the destination host.
what problem have we got because of this bug? after migration, guest time
may
jump back to several days ago, that will make some critical business
applications,
such as lotus notes, malfunction.
this patch is trying to fix the problem. first, when vmsave in progress,
we
rtc_update_time to refresh time stamp in cmos array, then during
vmrestore,
we rtc_set_time to update qemu base_rtc and last_update variable according
to time
stamp in cmos array.

Signed-off-by: Junlian Bell <zhongjun@sangfor.com.cn>
---
 hw/timer/mc146818rtc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

Comments

Michael S. Tsirkin Oct. 7, 2016, 4:24 a.m. UTC | #1
On Mon, Sep 26, 2016 at 08:41:01PM +0800, Junlian Bell wrote:
> qemu tracks guest time based on vector [base_rtc, last_update], in which
> last_update stands for a monotonic tick which is actually uptime of the
> host.
> according to rtc implementation codes of recent releases and upstream,
> after
> migration, the time base vector [base_rtc, last_update] isn't updated to
> coordinate with the destionation host, ie. qemu doesnt update last_update
> to
> uptime of the destination host.
> what problem have we got because of this bug? after migration, guest time
> may
> jump back to several days ago, that will make some critical business
> applications,
> such as lotus notes, malfunction.
> this patch is trying to fix the problem. first, when vmsave in progress,
> we
> rtc_update_time to refresh time stamp in cmos array, then during
> vmrestore,
> we rtc_set_time to update qemu base_rtc and last_update variable according
> to time
> stamp in cmos array.
> 
> Signed-off-by: Junlian Bell <zhongjun@sangfor.com.cn>

Seems to make sense superficially but I'm not a good judge
of the timer code.

Paolo, any comment on this?

Acked-by: Michael S. Tsirkin <mst@redhat.com>

> ---
>  hw/timer/mc146818rtc.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
> index ea625f2..4e4af43 100644
> --- a/hw/timer/mc146818rtc.c
> +++ b/hw/timer/mc146818rtc.c
> @@ -717,11 +717,19 @@ static void rtc_set_date_from_host(ISADevice *dev)
>      rtc_set_cmos(s, &tm);
>  }
>  
> +static void rtc_pre_save(void *opaque)
> +{
> +    RTCState *s = opaque;
> +
> +    rtc_update_time(s);
> +}
> +
>  static int rtc_post_load(void *opaque, int version_id)
>  {
>      RTCState *s = opaque;
>  
> -    if (version_id <= 2) {
> +    if (version_id <= 2 ||
> +            rtc_clock == QEMU_CLOCK_REALTIME){
>          rtc_set_time(s);
>          s->offset = 0;
>          check_update_timer(s);
> @@ -764,6 +772,7 @@ static const VMStateDescription vmstate_rtc = {
>      .name = "mc146818rtc",
>      .version_id = 3,
>      .minimum_version_id = 1,
> +    .pre_save = rtc_pre_save,
>      .post_load = rtc_post_load,
>      .fields = (VMStateField[]) {
>          VMSTATE_BUFFER(cmos_data, RTCState),
> -- 
> 2.9.0.windows.1
Paolo Bonzini Oct. 7, 2016, 7:51 a.m. UTC | #2
On 07/10/2016 06:24, Michael S. Tsirkin wrote:
> On Mon, Sep 26, 2016 at 08:41:01PM +0800, Junlian Bell wrote:
>> qemu tracks guest time based on vector [base_rtc, last_update], in which
>> last_update stands for a monotonic tick which is actually uptime of the
>> host.
>> according to rtc implementation codes of recent releases and upstream,
>> after
>> migration, the time base vector [base_rtc, last_update] isn't updated to
>> coordinate with the destionation host, ie. qemu doesnt update last_update
>> to
>> uptime of the destination host.
>> what problem have we got because of this bug? after migration, guest time
>> may
>> jump back to several days ago, that will make some critical business
>> applications,
>> such as lotus notes, malfunction.
>> this patch is trying to fix the problem. first, when vmsave in progress,
>> we
>> rtc_update_time to refresh time stamp in cmos array, then during
>> vmrestore,
>> we rtc_set_time to update qemu base_rtc and last_update variable according
>> to time
>> stamp in cmos array.
>>
>> Signed-off-by: Junlian Bell <zhongjun@sangfor.com.cn>
> 
> Seems to make sense superficially but I'm not a good judge
> of the timer code.
> 
> Paolo, any comment on this?
> 
> Acked-by: Michael S. Tsirkin <mst@redhat.com>

Yes, I have it queued already.

Paolo

> 
>> ---
>>  hw/timer/mc146818rtc.c | 11 ++++++++++-
>>  1 file changed, 10 insertions(+), 1 deletion(-)
>>
>> diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
>> index ea625f2..4e4af43 100644
>> --- a/hw/timer/mc146818rtc.c
>> +++ b/hw/timer/mc146818rtc.c
>> @@ -717,11 +717,19 @@ static void rtc_set_date_from_host(ISADevice *dev)
>>      rtc_set_cmos(s, &tm);
>>  }
>>  
>> +static void rtc_pre_save(void *opaque)
>> +{
>> +    RTCState *s = opaque;
>> +
>> +    rtc_update_time(s);
>> +}
>> +
>>  static int rtc_post_load(void *opaque, int version_id)
>>  {
>>      RTCState *s = opaque;
>>  
>> -    if (version_id <= 2) {
>> +    if (version_id <= 2 ||
>> +            rtc_clock == QEMU_CLOCK_REALTIME){
>>          rtc_set_time(s);
>>          s->offset = 0;
>>          check_update_timer(s);
>> @@ -764,6 +772,7 @@ static const VMStateDescription vmstate_rtc = {
>>      .name = "mc146818rtc",
>>      .version_id = 3,
>>      .minimum_version_id = 1,
>> +    .pre_save = rtc_pre_save,
>>      .post_load = rtc_post_load,
>>      .fields = (VMStateField[]) {
>>          VMSTATE_BUFFER(cmos_data, RTCState),
>> -- 
>> 2.9.0.windows.1
> 
>
diff mbox

Patch

diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index ea625f2..4e4af43 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -717,11 +717,19 @@  static void rtc_set_date_from_host(ISADevice *dev)
     rtc_set_cmos(s, &tm);
 }
 
+static void rtc_pre_save(void *opaque)
+{
+    RTCState *s = opaque;
+
+    rtc_update_time(s);
+}
+
 static int rtc_post_load(void *opaque, int version_id)
 {
     RTCState *s = opaque;
 
-    if (version_id <= 2) {
+    if (version_id <= 2 ||
+            rtc_clock == QEMU_CLOCK_REALTIME){
         rtc_set_time(s);
         s->offset = 0;
         check_update_timer(s);
@@ -764,6 +772,7 @@  static const VMStateDescription vmstate_rtc = {
     .name = "mc146818rtc",
     .version_id = 3,
     .minimum_version_id = 1,
+    .pre_save = rtc_pre_save,
     .post_load = rtc_post_load,
     .fields = (VMStateField[]) {
         VMSTATE_BUFFER(cmos_data, RTCState),