aboutsummaryrefslogtreecommitdiffstats
path: root/savevm.c
diff options
context:
space:
mode:
authorOt ten Thije <ottenthije@google.com>2010-07-29 10:26:01 +0100
committerOt ten Thije <ottenthije@google.com>2010-07-29 16:16:29 +0100
commit7fd67eba0b961d94a5d6baa8e3c3de37b729f738 (patch)
tree7c73ed8c8452f90b816689b14f691297241659ba /savevm.c
parent8acd2219729896fea80a363076f31e64c0b54e12 (diff)
downloadexternal_qemu-7fd67eba0b961d94a5d6baa8e3c3de37b729f738.zip
external_qemu-7fd67eba0b961d94a5d6baa8e3c3de37b729f738.tar.gz
external_qemu-7fd67eba0b961d94a5d6baa8e3c3de37b729f738.tar.bz2
Fixed rudimentary suspend/resume.
This patch replaces the failing asynchronous I/O code in the qcow2 driver with a working synchronous implementation and fixes another minor bug in iteration over QField structs. As a result, the VM can now be suspended and resumed with the savevm and loadvm commands, albeit with the following (major) caveats: 1. The ADBd and other network services do not resume correctly. 2. Normal SD card usage is blocked, since snapshots are written to a qcow2 image that must (for now) be mounted on hda. 3. Resume only works after the emulator is fully booted. It is not (yet) possible to load an image immediately after the machine started. The synchronous I/O code is ported from commit ef845c3b in mainline QEMU, which addresses a similar issue. Further upstream mainline also introduces a fix for the async I/O, but that patch is quite involved, and for now this relatively simple fix works. Change-Id: I660c19c22316aecdd7dcae357e66da20e0ab6d80
Diffstat (limited to 'savevm.c')
-rw-r--r--savevm.c22
1 files changed, 10 insertions, 12 deletions
diff --git a/savevm.c b/savevm.c
index 33ec239..1219ad6 100644
--- a/savevm.c
+++ b/savevm.c
@@ -631,12 +631,11 @@ void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
{
const QField* qf = fields;
- for (;;) {
+ /* Iterate over struct fields */
+ while (qf->type != Q_FIELD_END) {
uint8_t* p = (uint8_t*)s + qf->offset;
switch (qf->type) {
- case Q_FIELD_END:
- break;
case Q_FIELD_BYTE:
qemu_put_byte(f, p[0]);
break;
@@ -650,8 +649,8 @@ void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
qemu_put_be64(f, ((uint64_t*)p)[0]);
break;
case Q_FIELD_BUFFER:
- if (fields[1].type != Q_FIELD_BUFFER_SIZE ||
- fields[2].type != Q_FIELD_BUFFER_SIZE)
+ if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
+ qf[2].type != Q_FIELD_BUFFER_SIZE)
{
fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
__FUNCTION__ );
@@ -659,7 +658,7 @@ void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
}
else
{
- uint32_t size = ((uint32_t)fields[1].offset << 16) | (uint32_t)fields[2].offset;
+ uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
qemu_put_buffer(f, p, size);
qf += 2;
@@ -677,12 +676,11 @@ int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
{
const QField* qf = fields;
- for (;;) {
+ /* Iterate over struct fields */
+ while (qf->type != Q_FIELD_END) {
uint8_t* p = (uint8_t*)s + qf->offset;
switch (qf->type) {
- case Q_FIELD_END:
- break;
case Q_FIELD_BYTE:
p[0] = qemu_get_byte(f);
break;
@@ -696,8 +694,8 @@ int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
((uint64_t*)p)[0] = qemu_get_be64(f);
break;
case Q_FIELD_BUFFER:
- if (fields[1].type != Q_FIELD_BUFFER_SIZE ||
- fields[2].type != Q_FIELD_BUFFER_SIZE)
+ if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
+ qf[2].type != Q_FIELD_BUFFER_SIZE)
{
fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
__FUNCTION__ );
@@ -705,7 +703,7 @@ int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
}
else
{
- uint32_t size = ((uint32_t)fields[1].offset << 16) | (uint32_t)fields[2].offset;
+ uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
int ret = qemu_get_buffer(f, p, size);
if (ret != size) {