]> git.proxmox.com Git - pve-qemu-kvm.git/blob - new/savevm-async.c
remove rate limit
[pve-qemu-kvm.git] / new / savevm-async.c
1 #include "qemu-common.h"
2 #include "qerror.h"
3 #include "sysemu.h"
4 #include "qmp-commands.h"
5 #include "blockdev.h"
6 #include "qemu/qom-qobject.h"
7 #include "buffered_file.h"
8 #include "migration.h"
9
10 //#define DEBUG_SAVEVM_STATE
11
12 #ifdef DEBUG_SAVEVM_STATE
13 #define DPRINTF(fmt, ...) \
14 do { printf("savevm-async: " fmt, ## __VA_ARGS__); } while (0)
15 #else
16 #define DPRINTF(fmt, ...) \
17 do { } while (0)
18 #endif
19
20 enum {
21 SAVE_STATE_DONE,
22 SAVE_STATE_ERROR,
23 SAVE_STATE_ACTIVE,
24 SAVE_STATE_COMPLETED,
25 };
26
27 static struct SnapshotState {
28 BlockDriverState *bs;
29 size_t bs_pos;
30 int state;
31 Error *error;
32 int saved_vm_running;
33 QEMUFile *file;
34 int64_t total_time;
35 } snap_state;
36
37 SaveVMInfo *qmp_query_savevm(Error **errp)
38 {
39 SaveVMInfo *info = g_malloc0(sizeof(*info));
40 struct SnapshotState *s = &snap_state;
41
42 if (s->state != SAVE_STATE_DONE) {
43 info->has_bytes = true;
44 info->bytes = s->bs_pos;
45 switch (s->state) {
46 case SAVE_STATE_ERROR:
47 info->has_status = true;
48 info->status = g_strdup("failed");
49 info->has_total_time = true;
50 info->total_time = s->total_time;
51 if (s->error) {
52 info->has_error = true;
53 info->error = g_strdup(error_get_pretty(s->error));
54 }
55 break;
56 case SAVE_STATE_ACTIVE:
57 info->has_status = true;
58 info->status = g_strdup("active");
59 info->has_total_time = true;
60 info->total_time = qemu_get_clock_ms(rt_clock)
61 - s->total_time;
62 break;
63 case SAVE_STATE_COMPLETED:
64 info->has_status = true;
65 info->status = g_strdup("completed");
66 info->has_total_time = true;
67 info->total_time = s->total_time;
68 break;
69 }
70 }
71
72 return info;
73 }
74
75 static int save_snapshot_cleanup(void)
76 {
77 int ret = 0;
78
79 DPRINTF("save_snapshot_cleanup\n");
80
81 snap_state.total_time = qemu_get_clock_ms(rt_clock) -
82 snap_state.total_time;
83
84 if (snap_state.file) {
85 ret = qemu_fclose(snap_state.file);
86 }
87
88 if (snap_state.bs) {
89 // try to truncate, but ignore errors (will fail on block devices).
90 // note: bdrv_read() need whole blocks, so we round up
91 size_t size = (snap_state.bs_pos + BDRV_SECTOR_SIZE) & BDRV_SECTOR_MASK;
92 bdrv_truncate(snap_state.bs, size);
93
94 bdrv_delete(snap_state.bs);
95 snap_state.bs = NULL;
96 }
97
98 return ret;
99 }
100
101 static void save_snapshot_error(const char *fmt, ...)
102 {
103 va_list ap;
104 char *msg;
105
106 va_start(ap, fmt);
107 msg = g_strdup_vprintf(fmt, ap);
108 va_end(ap);
109
110 DPRINTF("save_snapshot_error: %s\n", msg);
111
112 if (!snap_state.error) {
113 error_set(&snap_state.error, ERROR_CLASS_GENERIC_ERROR, "%s", msg);
114 }
115
116 g_free (msg);
117
118 snap_state.state = SAVE_STATE_ERROR;
119
120 save_snapshot_cleanup();
121 }
122
123 static void save_snapshot_completed(void)
124 {
125 DPRINTF("save_snapshot_completed\n");
126
127 if (save_snapshot_cleanup() < 0) {
128 snap_state.state = SAVE_STATE_ERROR;
129 } else {
130 snap_state.state = SAVE_STATE_COMPLETED;
131 }
132 }
133
134 static int block_state_close(void *opaque)
135 {
136 snap_state.file = NULL;
137 return bdrv_flush(snap_state.bs);
138 }
139
140 static ssize_t block_state_put_buffer(void *opaque, const void *buf,
141 size_t size)
142 {
143 int ret;
144
145 if ((ret = bdrv_pwrite(snap_state.bs, snap_state.bs_pos, buf, size)) > 0) {
146 snap_state.bs_pos += ret;
147 }
148
149 return ret;
150 }
151
152 static void block_state_put_ready(void *opaque)
153 {
154 int ret;
155
156 if (snap_state.state != SAVE_STATE_ACTIVE) {
157 save_snapshot_error("put_ready returning because of non-active state");
158 return;
159 }
160
161 if (!runstate_check(RUN_STATE_SAVE_VM)) {
162 save_snapshot_error("put_ready returning because of wrong run state");
163 return;
164 }
165
166 ret = qemu_savevm_state_iterate(snap_state.file);
167 if (ret < 0) {
168 save_snapshot_error("qemu_savevm_state_iterate error %d", ret);
169 return;
170 } else if (ret == 1) {
171 DPRINTF("savevm inerate finished\n");
172 if ((ret = qemu_savevm_state_complete(snap_state.file)) < 0) {
173 save_snapshot_error("qemu_savevm_state_complete error %d", ret);
174 return;
175 } else {
176 DPRINTF("save complete\n");
177 save_snapshot_completed();
178 return;
179 }
180 }
181 }
182
183 static void block_state_wait_for_unfreeze(void *opaque)
184 {
185 /* do nothing here - should not be called */
186 }
187
188 void qmp_savevm_start(bool has_statefile, const char *statefile, Error **errp)
189 {
190 BlockDriver *drv = NULL;
191 int bdrv_oflags = BDRV_O_CACHE_WB | BDRV_O_RDWR;
192 MigrationParams params = {
193 .blk = 0,
194 .shared = 0
195 };
196 int ret;
197
198 if (snap_state.state != SAVE_STATE_DONE) {
199 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
200 "VM snapshot already started\n");
201 return;
202 }
203
204 /* initialize snapshot info */
205 snap_state.saved_vm_running = runstate_is_running();
206 snap_state.bs_pos = 0;
207 snap_state.total_time = qemu_get_clock_ms(rt_clock);
208
209 if (snap_state.error) {
210 error_free(snap_state.error);
211 snap_state.error = NULL;
212 }
213
214 /* stop the VM */
215 vm_stop(RUN_STATE_SAVE_VM);
216
217 if (!has_statefile) {
218 snap_state.state = SAVE_STATE_COMPLETED;
219 return;
220 }
221
222 if (qemu_savevm_state_blocked(errp)) {
223 return;
224 }
225
226 /* Open the image */
227 snap_state.bs = bdrv_new("vmstate");
228 ret = bdrv_open(snap_state.bs, statefile, bdrv_oflags, drv);
229 if (ret < 0) {
230 error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
231 goto restart;
232 }
233
234 snap_state.file = qemu_fopen_ops_buffered(&snap_state, 1000000000,
235 block_state_put_buffer,
236 block_state_put_ready,
237 block_state_wait_for_unfreeze,
238 block_state_close);
239
240 if (!snap_state.file) {
241 error_set(errp, QERR_OPEN_FILE_FAILED, statefile);
242 goto restart;
243 }
244
245 snap_state.state = SAVE_STATE_ACTIVE;
246
247 ret = qemu_savevm_state_begin(snap_state.file, &params);
248 if (ret < 0) {
249 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
250 "qemu_savevm_state_begin failed\n");
251 goto restart;
252 }
253
254 block_state_put_ready(&snap_state);
255
256 return;
257
258 restart:
259
260 save_snapshot_error("setup failed");
261
262 if (snap_state.saved_vm_running) {
263 vm_start();
264 }
265 }
266
267 void qmp_savevm_end(Error **errp)
268 {
269 if (snap_state.state == SAVE_STATE_DONE) {
270 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
271 "VM snapshot not started\n");
272 return;
273 }
274
275 if (snap_state.saved_vm_running) {
276 vm_start();
277 }
278
279 snap_state.state = SAVE_STATE_DONE;
280 }
281
282 void qmp_snapshot_drive(const char *device, const char *name, Error **errp)
283 {
284 BlockDriverState *bs;
285 QEMUSnapshotInfo sn1, *sn = &sn1;
286 int ret;
287 #ifdef _WIN32
288 struct _timeb tb;
289 #else
290 struct timeval tv;
291 #endif
292
293 if (snap_state.state != SAVE_STATE_COMPLETED) {
294 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
295 "VM snapshot not ready/started\n");
296 return;
297 }
298
299 bs = bdrv_find(device);
300 if (!bs) {
301 error_set(errp, QERR_DEVICE_NOT_FOUND, device);
302 return;
303 }
304
305 if (!bdrv_is_inserted(bs)) {
306 error_set(errp, QERR_DEVICE_HAS_NO_MEDIUM, device);
307 return;
308 }
309
310 if (bdrv_is_read_only(bs)) {
311 error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
312 return;
313 }
314
315 if (!bdrv_can_snapshot(bs)) {
316 error_set(errp, QERR_NOT_SUPPORTED);
317 return;
318 }
319
320 if (bdrv_snapshot_find(bs, sn, name) >= 0) {
321 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
322 "snapshot '%s' already exists", name);
323 return;
324 }
325
326 sn = &sn1;
327 memset(sn, 0, sizeof(*sn));
328
329 #ifdef _WIN32
330 _ftime(&tb);
331 sn->date_sec = tb.time;
332 sn->date_nsec = tb.millitm * 1000000;
333 #else
334 gettimeofday(&tv, NULL);
335 sn->date_sec = tv.tv_sec;
336 sn->date_nsec = tv.tv_usec * 1000;
337 #endif
338 sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
339
340 pstrcpy(sn->name, sizeof(sn->name), name);
341
342 sn->vm_state_size = 0; /* do not save state */
343
344 ret = bdrv_snapshot_create(bs, sn);
345 if (ret < 0) {
346 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
347 "Error while creating snapshot on '%s'\n", device);
348 return;
349 }
350 }
351
352 void qmp_delete_drive_snapshot(const char *device, const char *name,
353 Error **errp)
354 {
355 BlockDriverState *bs;
356 QEMUSnapshotInfo sn1, *sn = &sn1;
357 int ret;
358
359 bs = bdrv_find(device);
360 if (!bs) {
361 error_set(errp, QERR_DEVICE_NOT_FOUND, device);
362 return;
363 }
364 if (bdrv_is_read_only(bs)) {
365 error_set(errp, QERR_DEVICE_IS_READ_ONLY, device);
366 return;
367 }
368
369 if (!bdrv_can_snapshot(bs)) {
370 error_set(errp, QERR_NOT_SUPPORTED);
371 return;
372 }
373
374 if (bdrv_snapshot_find(bs, sn, name) < 0) {
375 /* return success if snapshot does not exists */
376 return;
377 }
378
379 ret = bdrv_snapshot_delete(bs, name);
380 if (ret < 0) {
381 error_set(errp, ERROR_CLASS_GENERIC_ERROR,
382 "Error while deleting snapshot on '%s'\n", device);
383 return;
384 }
385 }
386
387 static int loadstate_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
388 {
389 BlockDriverState *bs = (BlockDriverState *)opaque;
390 int64_t maxlen = bdrv_getlength(bs);
391 if (pos > maxlen) {
392 return -EIO;
393 }
394 if ((pos + size) > maxlen) {
395 size = maxlen - pos - 1;
396 }
397 if (size == 0) {
398 return 0;
399 }
400 return bdrv_pread(bs, pos, buf, size);
401 }
402
403 int load_state_from_blockdev(const char *filename)
404 {
405 BlockDriverState *bs = NULL;
406 BlockDriver *drv = NULL;
407 QEMUFile *f;
408 int ret = -1;
409
410 bs = bdrv_new("vmstate");
411 ret = bdrv_open(bs, filename, BDRV_O_CACHE_WB, drv);
412 if (ret < 0) {
413 error_report("Could not open VM state file");
414 goto the_end;
415 }
416
417 /* restore the VM state */
418 f = qemu_fopen_ops(bs, NULL, loadstate_get_buffer, NULL, NULL, NULL, NULL);
419 if (!f) {
420 error_report("Could not open VM state file");
421 ret = -EINVAL;
422 goto the_end;
423 }
424
425 qemu_system_reset(VMRESET_SILENT);
426 ret = qemu_loadvm_state(f);
427
428 qemu_fclose(f);
429 if (ret < 0) {
430 error_report("Error %d while loading VM state", ret);
431 goto the_end;
432 }
433
434 ret = 0;
435
436 the_end:
437 if (bs) {
438 bdrv_delete(bs);
439 }
440 return ret;
441 }