]> git.proxmox.com Git - pve-qemu-kvm.git/blame - debian/patches/savevm-live.patch
update to qemu 1.3 rc1
[pve-qemu-kvm.git] / debian / patches / savevm-live.patch
CommitLineData
d592fd72
DM
1Index: new/savevm-async.c
2===================================================================
e96de165
DM
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
5@@ -7,7 +7,7 @@
6 #include "buffered_file.h"
7 #include "migration.h"
d592fd72 8
e96de165
DM
9-//#define DEBUG_SAVEVM_STATE
10+/* #define DEBUG_SAVEVM_STATE */
11
12 #ifdef DEBUG_SAVEVM_STATE
13 #define DPRINTF(fmt, ...) \
14@@ -86,11 +86,11 @@
15 }
16
17 if (snap_state.bs) {
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
22+ */
23 size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
24 bdrv_truncate(snap_state.bs, size);
25-
26 bdrv_delete(snap_state.bs);
27 snap_state.bs = NULL;
28 }
29@@ -137,11 +137,13 @@
30 return bdrv_flush(snap_state.bs);
31 }
32
33-static ssize_t block_state_put_buffer(void *opaque, const void *buf,
34- size_t size)
35+static int block_state_put_buffer(void *opaque, const uint8_t *buf,
36+ int64_t pos, int size)
d592fd72 37 {
d592fd72
DM
38 int ret;
39
e96de165
DM
40+ assert(pos == snap_state.bs_pos);
41+
42 if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
43 snap_state.bs_pos += ret;
d592fd72 44 }
e96de165
DM
45@@ -149,50 +151,74 @@
46 return ret;
47 }
48
49-static void block_state_put_ready(void *opaque)
50+static void process_savevm_co(void *opaque)
51 {
52 int ret;
53+ uint64_t remaining;
54+ int64_t maxlen;
55+ MigrationParams params = {
56+ .blk = 0,
57+ .shared = 0
58+ };
59
60- if (snap_state.state != SAVE_STATE_ACTIVE) {
61- save_snapshot_error("put_ready returning because of non-active state");
62- return;
63- }
64+ snap_state.state = SAVE_STATE_ACTIVE;
d592fd72
DM
65
66- if (!runstate_check(RUN_STATE_SAVE_VM)) {
67- save_snapshot_error("put_ready returning because of wrong run state");
e96de165
DM
68+ ret = qemu_savevm_state_begin(snap_state.file, &params);
69+ if (ret < 0) {
70+ save_snapshot_error("qemu_savevm_state_begin failed");
71 return;
d592fd72
DM
72 }
73
74- ret = qemu_savevm_state_iterate(snap_state.file);
e96de165
DM
75- if (ret < 0) {
76- save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
77- return;
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);
82- return;
83- } else {
84- DPRINTF("save complete\n");
85- save_snapshot_completed();
86+ while (snap_state.state == SAVE_STATE_ACTIVE) {
87+
88+ ret = qemu_savevm_state_iterate(snap_state.file);
89+ remaining = ram_bytes_remaining();
90+
91+ DPRINTF("savevm inerate %zd %d\n", remaining, ret);
92+
93+ if (ret < 0) {
94+ save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
95 return;
96 }
97+
98+ /* stop the VM if we get to the end of available space,
99+ * or if remaining is just a few MB
100+ */
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);
106+ }
d592fd72 107+ }
e96de165
DM
108+
109+ if (ret == 1) { /* finished */
110+ if (runstate_is_running()) {
111+ vm_stop(RUN_STATE_SAVE_VM);
112+ }
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);
116+ return;
117+ } else {
118+ DPRINTF("save complete\n");
119+ save_snapshot_completed();
120+ return;
121+ }
122+ }
123 }
124 }
125
126-static void block_state_wait_for_unfreeze(void *opaque)
127-{
128- /* do nothing here - should not be called */
129-}
130+static const QEMUFileOps block_file_ops = {
131+ .put_buffer = block_state_put_buffer,
132+ .close = block_state_close,
133+};
134+
135
136 void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
137 {
138 BlockDriver *drv = NULL;
139 int bdrv_oflags = BDRV_O_CACHE_WB | BDRV_O_RDWR;
140- MigrationParams params = {
141- .blk = 0,
142- .shared = 0
143- };
144 int ret;
145
146 if (snap_state.state != SAVE_STATE_DONE) {
147@@ -211,10 +237,8 @@
d592fd72
DM
148 snap_state.error = NULL;
149 }
150
151- /* stop the VM */
152- vm_stop(RUN_STATE_SAVE_VM);
153-
154 if (!has_statefile) {
155+ vm_stop(RUN_STATE_SAVE_VM);
156 snap_state.state = SAVE_STATE_COMPLETED;
157 return;
158 }
e96de165
DM
159@@ -231,27 +255,15 @@
160 goto restart;
161 }
162
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);
169
170 if (!snap_state.file) {
171 error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
172 goto restart;
173 }
174
175- snap_state.state = SAVE_STATE_ACTIVE;
176-
177- ret = qemu_savevm_state_begin(snap_state.file, &params);
178- if (ret < 0) {
179- error_set(errp, ERROR_CLASS_GENERIC_ERROR,
180- "qemu_savevm_state_begin failed\n");
181- goto restart;
182- }
183-
184- block_state_put_ready(&snap_state);
185+ Coroutine *co = qemu_coroutine_create(process_savevm_co);
186+ qemu_coroutine_enter(co, NULL);
187
188 return;
189
190@@ -384,7 +396,8 @@
191 }
192 }
193
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,
196+ int size)
197 {
198 BlockDriverState *bs = (BlockDriverState *)opaque;
199 int64_t maxlen = bdrv_getlength(bs);
200@@ -400,6 +413,10 @@
201 return bdrv_pread(bs, pos, buf, size);
202 }
203
204+static const QEMUFileOps loadstate_file_ops = {
205+ .get_buffer = loadstate_get_buffer,
206+};
207+
208 int load_state_from_blockdev(const char *filename)
209 {
210 BlockDriverState *bs = NULL;
211@@ -415,7 +432,7 @@
212 }
213
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);
217 if (!f) {
218 error_report("Could not open VM state file");
219 ret = -EINVAL;