]> Git Repo - qemu.git/blobdiff - savevm.c
scsi: hotplug windup
[qemu.git] / savevm.c
index 0dcab79398d045d22dda30b034dc9b7d0c8f56d7..7a363b64d583ebddaeda236c39aa7d2585022e90 100644 (file)
--- a/savevm.c
+++ b/savevm.c
@@ -90,6 +90,7 @@
 #include "audio/audio.h"
 #include "migration.h"
 #include "qemu_socket.h"
+#include "qemu-queue.h"
 
 /* point to the block driver where the snapshots are managed */
 static BlockDriverState *bs_snapshots;
@@ -648,9 +649,9 @@ static int get_int8(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_int8(QEMUFile *f, const void *pv, size_t size)
+static void put_int8(QEMUFile *f, void *pv, size_t size)
 {
-    const int8_t *v = pv;
+    int8_t *v = pv;
     qemu_put_s8s(f, v);
 }
 
@@ -669,9 +670,9 @@ static int get_int16(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_int16(QEMUFile *f, const void *pv, size_t size)
+static void put_int16(QEMUFile *f, void *pv, size_t size)
 {
-    const int16_t *v = pv;
+    int16_t *v = pv;
     qemu_put_sbe16s(f, v);
 }
 
@@ -690,9 +691,9 @@ static int get_int32(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_int32(QEMUFile *f, const void *pv, size_t size)
+static void put_int32(QEMUFile *f, void *pv, size_t size)
 {
-    const int32_t *v = pv;
+    int32_t *v = pv;
     qemu_put_sbe32s(f, v);
 }
 
@@ -751,9 +752,9 @@ static int get_int64(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_int64(QEMUFile *f, const void *pv, size_t size)
+static void put_int64(QEMUFile *f, void *pv, size_t size)
 {
-    const int64_t *v = pv;
+    int64_t *v = pv;
     qemu_put_sbe64s(f, v);
 }
 
@@ -772,9 +773,9 @@ static int get_uint8(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_uint8(QEMUFile *f, const void *pv, size_t size)
+static void put_uint8(QEMUFile *f, void *pv, size_t size)
 {
-    const uint8_t *v = pv;
+    uint8_t *v = pv;
     qemu_put_8s(f, v);
 }
 
@@ -793,9 +794,9 @@ static int get_uint16(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_uint16(QEMUFile *f, const void *pv, size_t size)
+static void put_uint16(QEMUFile *f, void *pv, size_t size)
 {
-    const uint16_t *v = pv;
+    uint16_t *v = pv;
     qemu_put_be16s(f, v);
 }
 
@@ -814,9 +815,9 @@ static int get_uint32(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_uint32(QEMUFile *f, const void *pv, size_t size)
+static void put_uint32(QEMUFile *f, void *pv, size_t size)
 {
-    const uint32_t *v = pv;
+    uint32_t *v = pv;
     qemu_put_be32s(f, v);
 }
 
@@ -835,9 +836,9 @@ static int get_uint64(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_uint64(QEMUFile *f, const void *pv, size_t size)
+static void put_uint64(QEMUFile *f, void *pv, size_t size)
 {
-    const uint64_t *v = pv;
+    uint64_t *v = pv;
     qemu_put_be64s(f, v);
 }
 
@@ -847,6 +848,26 @@ const VMStateInfo vmstate_info_uint64 = {
     .put  = put_uint64,
 };
 
+/* 8 bit int. See that the received value is the same than the one
+   in the field */
+
+static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
+{
+    uint8_t *v = pv;
+    uint8_t v2;
+    qemu_get_8s(f, &v2);
+
+    if (*v == v2)
+        return 0;
+    return -EINVAL;
+}
+
+const VMStateInfo vmstate_info_uint8_equal = {
+    .name = "int32 equal",
+    .get  = get_uint8_equal,
+    .put  = put_uint8,
+};
+
 /* timers  */
 
 static int get_timer(QEMUFile *f, void *pv, size_t size)
@@ -856,9 +877,9 @@ static int get_timer(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_timer(QEMUFile *f, const void *pv, size_t size)
+static void put_timer(QEMUFile *f, void *pv, size_t size)
 {
-    QEMUTimer *v = (void *)pv;
+    QEMUTimer *v = pv;
     qemu_put_timer(f, v);
 }
 
@@ -877,9 +898,9 @@ static int get_buffer(QEMUFile *f, void *pv, size_t size)
     return 0;
 }
 
-static void put_buffer(QEMUFile *f, const void *pv, size_t size)
+static void put_buffer(QEMUFile *f, void *pv, size_t size)
 {
-    uint8_t *v = (void *)pv;
+    uint8_t *v = pv;
     qemu_put_buffer(f, v, size);
 }
 
@@ -890,7 +911,7 @@ const VMStateInfo vmstate_info_buffer = {
 };
 
 typedef struct SaveStateEntry {
-    TAILQ_ENTRY(SaveStateEntry) entry;
+    QTAILQ_ENTRY(SaveStateEntry) entry;
     char idstr[256];
     int instance_id;
     int version_id;
@@ -902,8 +923,8 @@ typedef struct SaveStateEntry {
     void *opaque;
 } SaveStateEntry;
 
-static TAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers =
-    TAILQ_HEAD_INITIALIZER(savevm_handlers);
+static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers =
+    QTAILQ_HEAD_INITIALIZER(savevm_handlers);
 static int global_section_id;
 
 static int calculate_new_instance_id(const char *idstr)
@@ -911,7 +932,7 @@ static int calculate_new_instance_id(const char *idstr)
     SaveStateEntry *se;
     int instance_id = 0;
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (strcmp(idstr, se->idstr) == 0
             && instance_id <= se->instance_id) {
             instance_id = se->instance_id + 1;
@@ -950,7 +971,7 @@ int register_savevm_live(const char *idstr,
         se->instance_id = instance_id;
     }
     /* add at the end of list */
-    TAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
+    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
 }
 
@@ -969,9 +990,9 @@ void unregister_savevm(const char *idstr, void *opaque)
 {
     SaveStateEntry *se, *new_se;
 
-    TAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
+    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
         if (strcmp(se->idstr, idstr) == 0 && se->opaque == opaque) {
-            TAILQ_REMOVE(&savevm_handlers, se, entry);
+            QTAILQ_REMOVE(&savevm_handlers, se, entry);
             qemu_free(se);
         }
     }
@@ -998,13 +1019,20 @@ int vmstate_register(int instance_id, const VMStateDescription *vmsd,
         se->instance_id = instance_id;
     }
     /* add at the end of list */
-    TAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
+    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
     return 0;
 }
 
-void vmstate_unregister(const char *idstr,  void *opaque)
+void vmstate_unregister(const VMStateDescription *vmsd, void *opaque)
 {
-    unregister_savevm(idstr, opaque);
+    SaveStateEntry *se, *new_se;
+
+    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
+        if (se->vmsd == vmsd && se->opaque == opaque) {
+            QTAILQ_REMOVE(&savevm_handlers, se, entry);
+            qemu_free(se);
+        }
+    }
 }
 
 int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
@@ -1021,8 +1049,16 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
     if  (version_id < vmsd->minimum_version_id) {
         return vmsd->load_state_old(f, opaque, version_id);
     }
+    if (vmsd->pre_load) {
+        int ret = vmsd->pre_load(opaque);
+        if (ret)
+            return ret;
+    }
     while(field->name) {
-        if (field->version_id <= version_id) {
+        if ((field->field_exists &&
+             field->field_exists(opaque, version_id)) ||
+            (!field->field_exists &&
+             field->version_id <= version_id)) {
             void *base_addr = opaque + field->offset;
             int ret, i, n_elems = 1;
 
@@ -1037,6 +1073,9 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
             for (i = 0; i < n_elems; i++) {
                 void *addr = base_addr + field->size * i;
 
+                if (field->flags & VMS_ARRAY_OF_POINTER) {
+                    addr = *(void **)addr;
+                }
                 if (field->flags & VMS_STRUCT) {
                     ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id);
                 } else {
@@ -1050,39 +1089,49 @@ int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
         }
         field++;
     }
-    if (vmsd->run_after_load)
-        return vmsd->run_after_load(opaque);
+    if (vmsd->post_load) {
+        return vmsd->post_load(opaque, version_id);
+    }
     return 0;
 }
 
 void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
-                        const void *opaque)
+                        void *opaque)
 {
     VMStateField *field = vmsd->fields;
 
+    if (vmsd->pre_save) {
+        vmsd->pre_save(opaque);
+    }
     while(field->name) {
-        const void *base_addr = opaque + field->offset;
-        int i, n_elems = 1;
+        if (!field->field_exists ||
+            field->field_exists(opaque, vmsd->version_id)) {
+            void *base_addr = opaque + field->offset;
+            int i, n_elems = 1;
 
-        if (field->flags & VMS_ARRAY) {
-            n_elems = field->num;
-        } else if (field->flags & VMS_VARRAY) {
-            n_elems = *(size_t *)(opaque+field->num_offset);
-        }
-        if (field->flags & VMS_POINTER) {
-            base_addr = *(void **)base_addr;
-        }
-        for (i = 0; i < n_elems; i++) {
-            const void *addr = base_addr + field->size * i;
+            if (field->flags & VMS_ARRAY) {
+                n_elems = field->num;
+            } else if (field->flags & VMS_VARRAY) {
+                n_elems = *(size_t *)(opaque+field->num_offset);
+            }
+            if (field->flags & VMS_POINTER) {
+                base_addr = *(void **)base_addr;
+            }
+            for (i = 0; i < n_elems; i++) {
+                void *addr = base_addr + field->size * i;
 
-            if (field->flags & VMS_STRUCT) {
-                vmstate_save_state(f, field->vmsd, addr);
-            } else {
-                field->info->put(f, addr, field->size);
+                if (field->flags & VMS_STRUCT) {
+                    vmstate_save_state(f, field->vmsd, addr);
+                } else {
+                    field->info->put(f, addr, field->size);
+                }
             }
         }
         field++;
     }
+    if (vmsd->post_save) {
+        vmsd->post_save(opaque);
+    }
 }
 
 static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
@@ -1119,7 +1168,7 @@ int qemu_savevm_state_begin(QEMUFile *f)
     qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
     qemu_put_be32(f, QEMU_VM_FILE_VERSION);
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         int len;
 
         if (se->save_live_state == NULL)
@@ -1151,7 +1200,7 @@ int qemu_savevm_state_iterate(QEMUFile *f)
     SaveStateEntry *se;
     int ret = 1;
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->save_live_state == NULL)
             continue;
 
@@ -1175,7 +1224,7 @@ int qemu_savevm_state_complete(QEMUFile *f)
 {
     SaveStateEntry *se;
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (se->save_live_state == NULL)
             continue;
 
@@ -1186,7 +1235,7 @@ int qemu_savevm_state_complete(QEMUFile *f)
         se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
     }
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         int len;
 
        if (se->save_state == NULL && se->vmsd == NULL)
@@ -1251,7 +1300,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
 {
     SaveStateEntry *se;
 
-    TAILQ_FOREACH(se, &savevm_handlers, entry) {
+    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
         if (!strcmp(se->idstr, idstr) &&
             instance_id == se->instance_id)
             return se;
@@ -1260,7 +1309,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id)
 }
 
 typedef struct LoadStateEntry {
-    LIST_ENTRY(LoadStateEntry) entry;
+    QLIST_ENTRY(LoadStateEntry) entry;
     SaveStateEntry *se;
     int section_id;
     int version_id;
@@ -1268,8 +1317,8 @@ typedef struct LoadStateEntry {
 
 int qemu_loadvm_state(QEMUFile *f)
 {
-    LIST_HEAD(, LoadStateEntry) loadvm_handlers =
-        LIST_HEAD_INITIALIZER(loadvm_handlers);
+    QLIST_HEAD(, LoadStateEntry) loadvm_handlers =
+        QLIST_HEAD_INITIALIZER(loadvm_handlers);
     LoadStateEntry *le, *new_le;
     uint8_t section_type;
     unsigned int v;
@@ -1326,7 +1375,7 @@ int qemu_loadvm_state(QEMUFile *f)
             le->se = se;
             le->section_id = section_id;
             le->version_id = version_id;
-            LIST_INSERT_HEAD(&loadvm_handlers, le, entry);
+            QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);
 
             ret = vmstate_load(f, le->se, le->version_id);
             if (ret < 0) {
@@ -1339,7 +1388,7 @@ int qemu_loadvm_state(QEMUFile *f)
         case QEMU_VM_SECTION_END:
             section_id = qemu_get_be32(f);
 
-            LIST_FOREACH(le, &loadvm_handlers, entry) {
+            QLIST_FOREACH(le, &loadvm_handlers, entry) {
                 if (le->section_id == section_id) {
                     break;
                 }
@@ -1367,8 +1416,8 @@ int qemu_loadvm_state(QEMUFile *f)
     ret = 0;
 
 out:
-    LIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
-        LIST_REMOVE(le, entry);
+    QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
+        QLIST_REMOVE(le, entry);
         qemu_free(le);
     }
 
@@ -1401,7 +1450,7 @@ static BlockDriverState *get_bs_snapshots(void)
 
     if (bs_snapshots)
         return bs_snapshots;
-    TAILQ_FOREACH(dinfo, &drives, next) {
+    QTAILQ_FOREACH(dinfo, &drives, next) {
         bs = dinfo->bdrv;
         if (bdrv_can_snapshot(bs))
             goto ok;
@@ -1506,7 +1555,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
 
     /* create the snapshots */
 
-    TAILQ_FOREACH(dinfo, &drives, next) {
+    QTAILQ_FOREACH(dinfo, &drives, next) {
         bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             if (must_delete) {
@@ -1549,7 +1598,7 @@ int load_vmstate(Monitor *mon, const char *name)
     /* Flush all IO requests so they don't interfere with the new state.  */
     qemu_aio_flush();
 
-    TAILQ_FOREACH(dinfo, &drives, next) {
+    QTAILQ_FOREACH(dinfo, &drives, next) {
         bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             ret = bdrv_snapshot_goto(bs1, name);
@@ -1612,7 +1661,7 @@ void do_delvm(Monitor *mon, const QDict *qdict)
         return;
     }
 
-    TAILQ_FOREACH(dinfo, &drives, next) {
+    QTAILQ_FOREACH(dinfo, &drives, next) {
         bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             ret = bdrv_snapshot_delete(bs1, name);
@@ -1643,7 +1692,7 @@ void do_info_snapshots(Monitor *mon)
         return;
     }
     monitor_printf(mon, "Snapshot devices:");
-    TAILQ_FOREACH(dinfo, &drives, next) {
+    QTAILQ_FOREACH(dinfo, &drives, next) {
         bs1 = dinfo->bdrv;
         if (bdrv_has_snapshot(bs1)) {
             if (bs == bs1)
This page took 0.040765 seconds and 4 git commands to generate.