Patchwork [RFC,3/5] savevm: Make use of the new DeviceState param

login
register
mail settings
Submitter Alex Williamson
Date June 14, 2010, 5:51 a.m.
Message ID <20100614055134.879.72781.stgit@localhost.localdomain>
Download mbox | patch
Permalink /patch/55476/
State New
Headers show

Comments

Alex Williamson - June 14, 2010, 5:51 a.m.
Use the now passed in DeviceState along with qdev_get_dev_path() to
create meaningful id strings for the SaveStateEntry.  We append the
driver provided string so we can differentiate multiple savevm
handlers per device:

"/main-system-bus/pci.0,addr=03.0/i82551,mac=52:54:00:12:34:56/eeprom"
"/main-system-bus/pci.0,addr=03.0/i82551,mac=52:54:00:12:34:56/i82551"

We also introduce compatibility fields so that we can attempt to
import savevm data from an older VM.  These should be deprecated and
removed at some point.

Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
---

 savevm.c |   83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 76 insertions(+), 7 deletions(-)

Patch

diff --git a/savevm.c b/savevm.c
index 81d544f..4cc542b 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1002,6 +1002,8 @@  typedef struct SaveStateEntry {
     LoadStateHandler *load_state;
     const VMStateDescription *vmsd;
     void *opaque;
+    char compat_idstr[256];
+    int compat_instance_id;
 } SaveStateEntry;
 
 
@@ -1023,6 +1025,20 @@  static int calculate_new_instance_id(const char *idstr)
     return instance_id;
 }
 
+static int calculate_new_compat_instance_id(const char *idstr)
+{
+    SaveStateEntry *se;
+    int instance_id = 0;
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (strcmp(idstr, se->compat_idstr) == 0
+            && instance_id <= se->compat_instance_id) {
+            instance_id = se->compat_instance_id + 1;
+        }
+    }
+    return instance_id;
+}
+
 /* TODO: Individual devices generally have very little idea about the rest
    of the system, so instance_id should be removed/replaced.
    Meanwhile pass -1 as instance_id if you do not already have a clearly
@@ -1040,7 +1056,16 @@  int register_savevm_live(DeviceState *dev,
     SaveStateEntry *se;
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), idstr);
+
+    if (dev) {
+        char *path = qdev_get_dev_path(dev);
+        pstrcpy(se->idstr, sizeof(se->idstr), path);
+        pstrcat(se->idstr, sizeof(se->idstr), "/");
+        pstrcat(se->idstr, sizeof(se->idstr), idstr);
+        qemu_free(path);
+    } else {
+        pstrcpy(se->idstr, sizeof(se->idstr), idstr);
+    }
     se->version_id = version_id;
     se->section_id = global_section_id++;
     se->set_params = set_params;
@@ -1050,11 +1075,19 @@  int register_savevm_live(DeviceState *dev,
     se->opaque = opaque;
     se->vmsd = NULL;
 
+    pstrcpy(se->compat_idstr, sizeof(se->idstr), idstr);
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(idstr);
+        se->instance_id = calculate_new_instance_id(se->idstr);
+        se->compat_instance_id = calculate_new_compat_instance_id(idstr);
     } else {
-        se->instance_id = instance_id;
+        se->instance_id = se->compat_instance_id = instance_id;
+    }
+
+    if (dev && instance_id == -1 && se->instance_id != 0) {
+        fprintf(stderr, "%s: Failed to create unqiue path \"%s\"\n",
+                __FUNCTION__, se->idstr);
     }
+
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1075,13 +1108,25 @@  int register_savevm(DeviceState *dev,
 void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
+    char *path;
+
+    if (dev) {
+        int len;
+        path = qdev_get_dev_path(dev);
+        len = strlen(path);
+        path = qemu_realloc(path, len + strlen(idstr) + 2);
+        sprintf(path + len, "/%s", idstr);
+    } else {
+        path = qemu_strdup(idstr);
+    }
 
     QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
-        if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
+        if (strcmp(se->idstr, path) == 0 && se->opaque == opaque) {
             QTAILQ_REMOVE(&savevm_handlers, se, entry);
             qemu_free(se);
         }
     }
+    qemu_free(path);
 }
 
 int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
@@ -1095,7 +1140,16 @@  int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
 
     se = qemu_mallocz(sizeof(SaveStateEntry));
-    pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
+
+    if (dev) {
+        char *path = qdev_get_dev_path(dev);
+        pstrcpy(se->idstr, sizeof(se->idstr), path);
+        pstrcat(se->idstr, sizeof(se->idstr), "/");
+        pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
+        qemu_free(path);
+    } else {
+        pstrcpy(se->idstr, sizeof(se->idstr), vmsd->name);
+    }
     se->version_id = vmsd->version_id;
     se->section_id = global_section_id++;
     se->save_live_state = NULL;
@@ -1105,11 +1159,19 @@  int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
     se->vmsd = vmsd;
     se->alias_id = alias_id;
 
+    pstrcpy(se->compat_idstr, sizeof(se->idstr), vmsd->name);
     if (instance_id == -1) {
-        se->instance_id = calculate_new_instance_id(vmsd->name);
+        se->instance_id = calculate_new_instance_id(se->idstr);
+        se->compat_instance_id = calculate_new_compat_instance_id(vmsd->name);
     } else {
-        se->instance_id = instance_id;
+        se->instance_id = se->compat_instance_id = instance_id;
     }
+
+    if (dev && instance_id == -1 && se->instance_id != 0) {
+        fprintf(stderr, "%s: Failed to create unqiue path \"%s\"\n",
+                __FUNCTION__, se->idstr);
+    }
+
     /* add at the end of list */
     QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
@@ -1456,6 +1518,13 @@  static SaveStateEntry *find_se(const char *idstr, int instance_id)
              instance_id == se->alias_id))
             return se;
     }
+
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
+        if (!strcmp(se->compat_idstr, idstr) &&
+            (instance_id == se->compat_instance_id ||
+             instance_id == se->alias_id))
+            return se;
+    }
     return NULL;
 }