From 465d4c17f222ddb051f41f5dde70dbe20d14483f Mon Sep 17 00:00:00 2001
From: Eduardo Habkost <ehabkost@redhat.com>
Date: Mon, 14 Oct 2013 19:42:53 +0200
Subject: [PATCH 2/4] savevm: Introduce max_version_id field to SaveStateEntry

RH-Author: Eduardo Habkost <ehabkost@redhat.com>
Message-id: <1381779774-3554-3-git-send-email-ehabkost@redhat.com>
Patchwork-id: 54902
O-Subject: [qemu-kvm RHEL-6 PATCH v2 2/3] savevm: Introduce max_version_id field to SaveStateEntry
Bugzilla: 1016736
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Juan Quintela <quintela@redhat.com>
RH-Acked-by: Orit Wasserman <owasserm@redhat.com>

Bugzilla: 1016736
Scratch build: https://brewweb.devel.redhat.com/taskinfo?taskID=6415966
Upstream status: not submitted
    (Waiting until the vmstate part gets some feedback)

This introduces max_version_id on the savevm code as well, so we can
make QEMU accept v12 of the "cpu" section even after it gets version_id
set to v11.

Even if this is rejected upstream, we have no choice if we want to fix
the bug on RHEL-6.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
 hw/hw.h  |  9 +++++++++
 savevm.c | 52 ++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 51 insertions(+), 10 deletions(-)

Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
---
 hw/hw.h  |    9 +++++++++
 savevm.c |   52 ++++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 51 insertions(+), 10 deletions(-)

diff --git a/hw/hw.h b/hw/hw.h
index d896da2..8e0f9b1 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -265,6 +265,15 @@ int register_savevm_live(DeviceState *dev,
                          LoadStateHandler *load_state,
                          void *opaque);
 
+int register_savevm_max_version(DeviceState *dev,
+                                const char *idstr,
+                                int instance_id,
+                                int version_id,
+                                int max_version_id,
+                                SaveStateHandler *save_state,
+                                LoadStateHandler *load_state,
+                                void *opaque);
+
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque);
 void register_device_unmigratable(DeviceState *dev, const char *idstr,
                                                                 void *opaque);
diff --git a/savevm.c b/savevm.c
index fda52dd..138761d 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1092,6 +1092,7 @@ typedef struct SaveStateEntry {
     char idstr[256];
     int instance_id;
     int version_id;
+    int max_version_id;
     int section_id;
     SaveSetParamsHandler *set_params;
     SaveLiveStateHandler *save_live_state;
@@ -1143,20 +1144,22 @@ static int calculate_compat_instance_id(const char *idstr)
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
    distinguishing id for all instances of your device class. */
-int register_savevm_live(DeviceState *dev,
-                         const char *idstr,
-                         int instance_id,
-                         int version_id,
-                         SaveSetParamsHandler *set_params,
-                         SaveLiveStateHandler *save_live_state,
-                         SaveStateHandler *save_state,
-                         LoadStateHandler *load_state,
-                         void *opaque)
+static int register_savevm_full(DeviceState *dev,
+                                const char *idstr,
+                                int instance_id,
+                                int version_id,
+                                int max_version_id,
+                                SaveSetParamsHandler *set_params,
+                                SaveLiveStateHandler *save_live_state,
+                                SaveStateHandler *save_state,
+                                LoadStateHandler *load_state,
+                                void *opaque)
 {
     SaveStateEntry *se;
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
     se->version_id = version_id;
+    se->max_version_id = max_version_id;
     se->section_id = global_section_id++;
     se->set_params = set_params;
     se->save_live_state = save_live_state;
@@ -1193,6 +1196,21 @@ int register_savevm_live(DeviceState *dev,
     return 0;
 }
 
+int register_savevm_live(DeviceState *dev,
+                         const char *idstr,
+                         int instance_id,
+                         int version_id,
+                         SaveSetParamsHandler *set_params,
+                         SaveLiveStateHandler *save_live_state,
+                         SaveStateHandler *save_state,
+                         LoadStateHandler *load_state,
+                         void *opaque)
+{
+    return register_savevm_full(dev, idstr, instance_id, version_id, version_id,
+                                set_params, save_live_state, save_state,
+                                load_state, opaque);
+}
+
 int register_savevm(DeviceState *dev,
                     const char *idstr,
                     int instance_id,
@@ -1205,6 +1223,20 @@ int register_savevm(DeviceState *dev,
                                 NULL, NULL, save_state, load_state, opaque);
 }
 
+int register_savevm_max_version(DeviceState *dev,
+                                const char *idstr,
+                                int instance_id,
+                                int version_id,
+                                int max_version_id,
+                                SaveStateHandler *save_state,
+                                LoadStateHandler *load_state,
+                                void *opaque)
+{
+    return register_savevm_full(dev, idstr, instance_id,
+                                version_id, max_version_id, NULL, NULL,
+                                save_state, load_state, opaque);
+}
+
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
@@ -1817,7 +1849,7 @@ int qemu_loadvm_state(QEMUFile *f)
             }
 
             /* Validate version */
-            if (version_id > se->version_id) {
+            if (version_id > MAX(se->version_id, se->max_version_id)) {
                 fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
                         version_id, idstr, se->version_id);
                 ret = -EINVAL;
-- 
1.7.1

