]> git.proxmox.com Git - pve-qemu-kvm.git/blob - debian/patches/savevm-live.patch
update to qemu 1.3 rc1
[pve-qemu-kvm.git] / debian / patches / savevm-live.patch
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
5 @@ -7,7 +7,7 @@
6 #include "buffered_file.h"
7 #include "migration.h"
8
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)
37 {
38 int ret;
39
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;
44 }
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;
65
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, &params);
69 + if (ret < 0) {
70 + save_snapshot_error("qemu_savevm_state_begin failed");
71 return;
72 }
73
74 - ret = qemu_savevm_state_iterate(snap_state.file);
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 + }
107 + }
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 @@
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 }
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;