1 Index: new/savevm-async.c
2 ===================================================================
3 --- new.orig/savevm-async.c 2012-11-22 10:44:32.000000000 +0100
4 +++ new/savevm-async.c 2012-11-22 12:15:20.000000000 +0100
6 #include "buffered_file.h"
9 -//#define DEBUG_SAVEVM_STATE
10 +/* #define DEBUG_SAVEVM_STATE */
12 #ifdef DEBUG_SAVEVM_STATE
13 #define DPRINTF(fmt, ...) \
18 - // try to truncate, but ignore errors (will fail on block devices).
19 - // note: bdrv_read() need whole blocks, so we round up
20 + /* try to truncate, but ignore errors (will fail on block devices).
21 + * note: bdrv_read() need whole blocks, so we round up
23 size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
24 bdrv_truncate(snap_state.bs, size);
26 bdrv_delete(snap_state.bs);
30 return bdrv_flush(snap_state.bs);
33 -static ssize_t block_state_put_buffer(void *opaque, const void *buf,
35 +static int block_state_put_buffer(void *opaque, const uint8_t *buf,
36 + int64_t pos, int size)
40 + assert(pos == snap_state.bs_pos);
42 if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
43 snap_state.bs_pos += ret;
49 -static void block_state_put_ready(void *opaque)
50 +static void process_savevm_co(void *opaque)
55 + MigrationParams params = {
60 - if (snap_state.state != SAVE_STATE_ACTIVE) {
61 - save_snapshot_error("put_ready returning because of non-active state");
64 + snap_state.state = SAVE_STATE_ACTIVE;
66 - if (!runstate_check(RUN_STATE_SAVE_VM)) {
67 - save_snapshot_error("put_ready returning because of wrong run state");
68 + ret = qemu_savevm_state_begin(snap_state.file, ¶ms);
70 + save_snapshot_error("qemu_savevm_state_begin failed");
74 - ret = qemu_savevm_state_iterate(snap_state.file);
76 - save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
78 - } else if (ret == 1) {
79 - DPRINTF("savevm inerate finished\n");
80 - if ((ret = qemu_savevm_state_complete(snap_state.file)) < 0) {
81 - save_snapshot_error("qemu_savevm_state_complete error %d", ret);
84 - DPRINTF("save complete\n");
85 - save_snapshot_completed();
86 + while (snap_state.state == SAVE_STATE_ACTIVE) {
88 + ret = qemu_savevm_state_iterate(snap_state.file);
89 + remaining = ram_bytes_remaining();
91 + DPRINTF("savevm inerate %zd %d\n", remaining, ret);
94 + save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
98 + /* stop the VM if we get to the end of available space,
99 + * or if remaining is just a few MB
101 + maxlen = bdrv_getlength(snap_state.bs) - 30*1024*1024;
102 + if ((remaining < 100000) ||
103 + ((snap_state.bs_pos + remaining) >= maxlen)) {
104 + if (runstate_is_running()) {
105 + vm_stop(RUN_STATE_SAVE_VM);
109 + if (ret == 1) { /* finished */
110 + if (runstate_is_running()) {
111 + vm_stop(RUN_STATE_SAVE_VM);
113 + DPRINTF("savevm inerate finished\n");
114 + if ((ret = qemu_savevm_state_complete(snap_state.file)) < 0) {
115 + save_snapshot_error("qemu_savevm_state_complete error %d", ret);
118 + DPRINTF("save complete\n");
119 + save_snapshot_completed();
126 -static void block_state_wait_for_unfreeze(void *opaque)
128 - /* do nothing here - should not be called */
130 +static const QEMUFileOps block_file_ops = {
131 + .put_buffer = block_state_put_buffer,
132 + .close = block_state_close,
136 void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
138 BlockDriver *drv = NULL;
139 int bdrv_oflags = BDRV_O_CACHE_WB | BDRV_O_RDWR;
140 - MigrationParams params = {
146 if (snap_state.state != SAVE_STATE_DONE) {
148 snap_state.error = NULL;
152 - vm_stop(RUN_STATE_SAVE_VM);
154 if (!has_statefile) {
155 + vm_stop(RUN_STATE_SAVE_VM);
156 snap_state.state = SAVE_STATE_COMPLETED;
159 @@ -231,27 +255,15 @@
163 - snap_state.file = qemu_fopen_ops_buffered(&snap_state, 1000000000,
164 - block_state_put_buffer,
165 - block_state_put_ready,
166 - block_state_wait_for_unfreeze,
167 - block_state_close);
168 + snap_state.file = qemu_fopen_ops(&snap_state, &block_file_ops);
170 if (!snap_state.file) {
171 error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
175 - snap_state.state = SAVE_STATE_ACTIVE;
177 - ret = qemu_savevm_state_begin(snap_state.file, ¶ms);
179 - error_set(errp, ERROR_CLASS_GENERIC_ERROR,
180 - "qemu_savevm_state_begin failed\n");
184 - block_state_put_ready(&snap_state);
185 + Coroutine *co = qemu_coroutine_create(process_savevm_co);
186 + qemu_coroutine_enter(co, NULL);
194 -static int loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
195 +static int loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos,
198 BlockDriverState *bs = (BlockDriverState *)opaque;
199 int64_t maxlen = bdrv_getlength(bs);
201 return bdrv_pread(bs, pos, buf, size);
204 +static const QEMUFileOps loadstate_file_ops = {
205 + .get_buffer = loadstate_get_buffer,
208 int load_state_from_blockdev(const char *filename)
210 BlockDriverState *bs = NULL;
214 /* restore the VM state */
215 - f = qemu_fopen_ops(bs, NULL, loadstate_get_buffer, NULL, NULL, NULL, NULL);
216 + f = qemu_fopen_ops(bs, &loadstate_file_ops);
218 error_report("Could not open VM state file");