#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;
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
.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)
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);
}
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);
}
};
typedef struct SaveStateEntry {
- TAILQ_ENTRY(SaveStateEntry) entry;
+ QTAILQ_ENTRY(SaveStateEntry) entry;
char idstr[256];
int instance_id;
int version_id;
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)
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;
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;
}
{
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);
}
}
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,
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;
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 {
}
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)
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)
SaveStateEntry *se;
int ret = 1;
- TAILQ_FOREACH(se, &savevm_handlers, entry) {
+ QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->save_live_state == NULL)
continue;
{
SaveStateEntry *se;
- TAILQ_FOREACH(se, &savevm_handlers, entry) {
+ QTAILQ_FOREACH(se, &savevm_handlers, entry) {
if (se->save_live_state == NULL)
continue;
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)
{
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;
}
typedef struct LoadStateEntry {
- LIST_ENTRY(LoadStateEntry) entry;
+ QLIST_ENTRY(LoadStateEntry) entry;
SaveStateEntry *se;
int section_id;
int version_id;
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;
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) {
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;
}
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);
}
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;
/* create the snapshots */
- TAILQ_FOREACH(dinfo, &drives, next) {
+ QTAILQ_FOREACH(dinfo, &drives, next) {
bs1 = dinfo->bdrv;
if (bdrv_has_snapshot(bs1)) {
if (must_delete) {
/* 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);
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);
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)