blob: 090596316f2463fc69889a91504ac93923a7cf85 [file] [log] [blame]
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001/*
2 * QEMU System Emulator
3 *
4 * Copyright (c) 2003-2008 Fabrice Bellard
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
24#include <unistd.h>
25#include <fcntl.h>
26#include <signal.h>
27#include <time.h>
28#include <errno.h>
29#include <sys/time.h>
30#include <zlib.h>
31
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070032/* Needed early for CONFIG_BSD etc. */
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070033#include "config-host.h"
34
35#ifndef _WIN32
36#include <sys/times.h>
37#include <sys/wait.h>
38#include <termios.h>
39#include <sys/mman.h>
40#include <sys/ioctl.h>
41#include <sys/resource.h>
42#include <sys/socket.h>
43#include <netinet/in.h>
44#include <net/if.h>
45#if defined(__NetBSD__)
46#include <net/if_tap.h>
47#endif
48#ifdef __linux__
49#include <linux/if_tun.h>
50#endif
51#include <arpa/inet.h>
52#include <dirent.h>
53#include <netdb.h>
54#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070055#ifdef CONFIG_BSD
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070056#include <sys/stat.h>
57#if defined(__FreeBSD__) || defined(__DragonFly__)
58#include <libutil.h>
59#else
60#include <util.h>
61#endif
62#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
63#include <freebsd/stdlib.h>
64#else
65#ifdef __linux__
66#include <pty.h>
67#include <malloc.h>
68#include <linux/rtc.h>
69#endif
70#endif
71#endif
72
73#ifdef _WIN32
74#include <windows.h>
75#include <malloc.h>
76#include <sys/timeb.h>
77#include <mmsystem.h>
78#define getopt_long_only getopt_long
79#define memalign(align, size) malloc(size)
80#endif
81
82#include "qemu-common.h"
83#include "hw/hw.h"
84#include "net.h"
85#include "monitor.h"
86#include "sysemu.h"
87#include "qemu-timer.h"
88#include "qemu-char.h"
Ot ten Thije2ff39a32010-10-06 17:48:15 +010089#include "outputchannel.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090#include "block.h"
91#include "audio/audio.h"
92#include "migration.h"
93#include "qemu_socket.h"
94#include "qemu_file.h"
Tim Baverstock622b8f42010-12-07 11:36:59 +000095#include "android/snapshot.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070096
97/* point to the block driver where the snapshots are managed */
98static BlockDriverState *bs_snapshots;
99
100#define SELF_ANNOUNCE_ROUNDS 5
101#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number */
102//#define ETH_P_EXPERIMENTAL 0x0012 /* make it the size of the packet */
103#define EXPERIMENTAL_MAGIC 0xf1f23f4f
104
105static int announce_self_create(uint8_t *buf,
106 uint8_t *mac_addr)
107{
108 uint32_t magic = EXPERIMENTAL_MAGIC;
109 uint16_t proto = htons(ETH_P_EXPERIMENTAL);
110
111 /* FIXME: should we send a different packet (arp/rarp/ping)? */
112
113 memset(buf, 0, 64);
114 memset(buf, 0xff, 6); /* h_dst */
115 memcpy(buf + 6, mac_addr, 6); /* h_src */
116 memcpy(buf + 12, &proto, 2); /* h_proto */
117 memcpy(buf + 14, &magic, 4); /* magic */
118
119 return 64; /* len */
120}
121
122static void qemu_announce_self_once(void *opaque)
123{
124 int i, len;
125 VLANState *vlan;
126 VLANClientState *vc;
127 uint8_t buf[256];
128 static int count = SELF_ANNOUNCE_ROUNDS;
129 QEMUTimer *timer = *(QEMUTimer **)opaque;
130
131 for (i = 0; i < MAX_NICS; i++) {
132 if (!nd_table[i].used)
133 continue;
134 len = announce_self_create(buf, nd_table[i].macaddr);
135 vlan = nd_table[i].vlan;
136 for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
137 vc->receive(vc, buf, len);
138 }
139 }
140 if (count--) {
141 qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100);
142 } else {
143 qemu_del_timer(timer);
144 qemu_free_timer(timer);
145 }
146}
147
148void qemu_announce_self(void)
149{
150 static QEMUTimer *timer;
151 timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
152 qemu_announce_self_once(&timer);
153}
154
155/***********************************************************/
156/* savevm/loadvm support */
157
158#define IO_BUF_SIZE 32768
159
160struct QEMUFile {
161 QEMUFilePutBufferFunc *put_buffer;
162 QEMUFileGetBufferFunc *get_buffer;
163 QEMUFileCloseFunc *close;
164 QEMUFileRateLimit *rate_limit;
165 QEMUFileSetRateLimit *set_rate_limit;
David Turnera12820e2010-09-09 21:16:39 +0200166 QEMUFileGetRateLimit *get_rate_limit;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700167 void *opaque;
168 int is_write;
169
170 int64_t buf_offset; /* start of buffer when writing, end of buffer
171 when reading */
172 int buf_index;
173 int buf_size; /* 0 when writing */
174 uint8_t buf[IO_BUF_SIZE];
175
176 int has_error;
177};
178
179typedef struct QEMUFilePopen
180{
181 FILE *popen_file;
182 QEMUFile *file;
183} QEMUFilePopen;
184
185typedef struct QEMUFileSocket
186{
187 int fd;
188 QEMUFile *file;
189} QEMUFileSocket;
190
191static int file_socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
192{
193 QEMUFileSocket *s = opaque;
194 ssize_t len;
195
196 do {
197 len = recv(s->fd, (void *)buf, size, 0);
198 } while (len == -1 && socket_error() == EINTR);
199
200 if (len == -1)
201 len = -socket_error();
202
203 return len;
204}
205
206static int file_socket_close(void *opaque)
207{
208 QEMUFileSocket *s = opaque;
209 qemu_free(s);
210 return 0;
211}
212
213static int popen_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
214{
215 QEMUFilePopen *s = opaque;
216 return fwrite(buf, 1, size, s->popen_file);
217}
218
219static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
220{
221 QEMUFilePopen *s = opaque;
222 FILE *fp = s->popen_file;
223 int bytes;
224
225 do {
226 clearerr(fp);
227 bytes = fread(buf, 1, size, fp);
228 } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
229 return bytes;
230}
231
232static int popen_close(void *opaque)
233{
234 QEMUFilePopen *s = opaque;
235 pclose(s->popen_file);
236 qemu_free(s);
237 return 0;
238}
239
240QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
241{
242 QEMUFilePopen *s;
243
244 if (popen_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
245 fprintf(stderr, "qemu_popen: Argument validity check failed\n");
246 return NULL;
247 }
248
249 s = qemu_mallocz(sizeof(QEMUFilePopen));
250
251 s->popen_file = popen_file;
252
253 if(mode[0] == 'r') {
David Turnera12820e2010-09-09 21:16:39 +0200254 s->file = qemu_fopen_ops(s, NULL, popen_get_buffer, popen_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700255 } else {
David Turnera12820e2010-09-09 21:16:39 +0200256 s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700257 }
258 return s->file;
259}
260
261QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
262{
263 FILE *popen_file;
264
265 popen_file = popen(command, mode);
266 if(popen_file == NULL) {
267 return NULL;
268 }
269
270 return qemu_popen(popen_file, mode);
271}
272
273int qemu_popen_fd(QEMUFile *f)
274{
275 QEMUFilePopen *p;
276 int fd;
277
278 p = (QEMUFilePopen *)f->opaque;
279 fd = fileno(p->popen_file);
280
281 return fd;
282}
283
284QEMUFile *qemu_fopen_socket(int fd)
285{
286 QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
287
288 s->fd = fd;
David Turnera12820e2010-09-09 21:16:39 +0200289 s->file = qemu_fopen_ops(s, NULL, file_socket_get_buffer, file_socket_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700290 return s->file;
291}
292
293typedef struct QEMUFileStdio
294{
295 FILE *outfile;
296} QEMUFileStdio;
297
298static int file_put_buffer(void *opaque, const uint8_t *buf,
299 int64_t pos, int size)
300{
301 QEMUFileStdio *s = opaque;
302 fseek(s->outfile, pos, SEEK_SET);
303 fwrite(buf, 1, size, s->outfile);
304 return size;
305}
306
307static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
308{
309 QEMUFileStdio *s = opaque;
310 fseek(s->outfile, pos, SEEK_SET);
311 return fread(buf, 1, size, s->outfile);
312}
313
314static int file_close(void *opaque)
315{
316 QEMUFileStdio *s = opaque;
317 fclose(s->outfile);
318 qemu_free(s);
319 return 0;
320}
321
322QEMUFile *qemu_fopen(const char *filename, const char *mode)
323{
324 QEMUFileStdio *s;
325
326 s = qemu_mallocz(sizeof(QEMUFileStdio));
327
328 s->outfile = fopen(filename, mode);
329 if (!s->outfile)
330 goto fail;
331
332 if (!strcmp(mode, "wb"))
David Turnera12820e2010-09-09 21:16:39 +0200333 return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700334 else if (!strcmp(mode, "rb"))
David Turnera12820e2010-09-09 21:16:39 +0200335 return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700336
337fail:
338 if (s->outfile)
339 fclose(s->outfile);
340 qemu_free(s);
341 return NULL;
342}
343
344typedef struct QEMUFileBdrv
345{
346 BlockDriverState *bs;
347 int64_t base_offset;
348} QEMUFileBdrv;
349
350static int block_put_buffer(void *opaque, const uint8_t *buf,
351 int64_t pos, int size)
352{
353 QEMUFileBdrv *s = opaque;
354 bdrv_put_buffer(s->bs, buf, s->base_offset + pos, size);
355 return size;
356}
357
358static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
359{
360 QEMUFileBdrv *s = opaque;
361 return bdrv_get_buffer(s->bs, buf, s->base_offset + pos, size);
362}
363
364static int bdrv_fclose(void *opaque)
365{
366 QEMUFileBdrv *s = opaque;
367 qemu_free(s);
368 return 0;
369}
370
371static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
372{
373 QEMUFileBdrv *s;
374
375 s = qemu_mallocz(sizeof(QEMUFileBdrv));
376
377 s->bs = bs;
378 s->base_offset = offset;
379
380 if (is_writable)
David Turnera12820e2010-09-09 21:16:39 +0200381 return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700382
David Turnera12820e2010-09-09 21:16:39 +0200383 return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700384}
385
386QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
387 QEMUFileGetBufferFunc *get_buffer,
388 QEMUFileCloseFunc *close,
389 QEMUFileRateLimit *rate_limit,
David Turnera12820e2010-09-09 21:16:39 +0200390 QEMUFileSetRateLimit *set_rate_limit,
391 QEMUFileGetRateLimit *get_rate_limit)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700392{
393 QEMUFile *f;
394
395 f = qemu_mallocz(sizeof(QEMUFile));
396
397 f->opaque = opaque;
398 f->put_buffer = put_buffer;
399 f->get_buffer = get_buffer;
400 f->close = close;
401 f->rate_limit = rate_limit;
402 f->set_rate_limit = set_rate_limit;
403 f->is_write = 0;
404
405 return f;
406}
407
408int qemu_file_has_error(QEMUFile *f)
409{
410 return f->has_error;
411}
412
413void qemu_file_set_error(QEMUFile *f)
414{
415 f->has_error = 1;
416}
417
418void qemu_fflush(QEMUFile *f)
419{
420 if (!f->put_buffer)
421 return;
422
423 if (f->is_write && f->buf_index > 0) {
424 int len;
425
426 len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
427 if (len > 0)
428 f->buf_offset += f->buf_index;
429 else
430 f->has_error = 1;
431 f->buf_index = 0;
432 }
433}
434
435static void qemu_fill_buffer(QEMUFile *f)
436{
437 int len;
438
439 if (!f->get_buffer)
440 return;
441
442 if (f->is_write)
443 abort();
444
445 len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
446 if (len > 0) {
447 f->buf_index = 0;
448 f->buf_size = len;
449 f->buf_offset += len;
450 } else if (len != -EAGAIN)
451 f->has_error = 1;
452}
453
454int qemu_fclose(QEMUFile *f)
455{
456 int ret = 0;
457 qemu_fflush(f);
458 if (f->close)
459 ret = f->close(f->opaque);
460 qemu_free(f);
461 return ret;
462}
463
464void qemu_file_put_notify(QEMUFile *f)
465{
466 f->put_buffer(f->opaque, NULL, 0, 0);
467}
468
469void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
470{
471 int l;
472
473 if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
474 fprintf(stderr,
475 "Attempted to write to buffer while read buffer is not empty\n");
476 abort();
477 }
478
479 while (!f->has_error && size > 0) {
480 l = IO_BUF_SIZE - f->buf_index;
481 if (l > size)
482 l = size;
483 memcpy(f->buf + f->buf_index, buf, l);
484 f->is_write = 1;
485 f->buf_index += l;
486 buf += l;
487 size -= l;
488 if (f->buf_index >= IO_BUF_SIZE)
489 qemu_fflush(f);
490 }
491}
492
493void qemu_put_byte(QEMUFile *f, int v)
494{
495 if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
496 fprintf(stderr,
497 "Attempted to write to buffer while read buffer is not empty\n");
498 abort();
499 }
500
501 f->buf[f->buf_index++] = v;
502 f->is_write = 1;
503 if (f->buf_index >= IO_BUF_SIZE)
504 qemu_fflush(f);
505}
506
507int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
508{
509 int size, l;
510
511 if (f->is_write)
512 abort();
513
514 size = size1;
515 while (size > 0) {
516 l = f->buf_size - f->buf_index;
517 if (l == 0) {
518 qemu_fill_buffer(f);
519 l = f->buf_size - f->buf_index;
520 if (l == 0)
521 break;
522 }
523 if (l > size)
524 l = size;
525 memcpy(buf, f->buf + f->buf_index, l);
526 f->buf_index += l;
527 buf += l;
528 size -= l;
529 }
530 return size1 - size;
531}
532
533int qemu_get_byte(QEMUFile *f)
534{
535 if (f->is_write)
536 abort();
537
538 if (f->buf_index >= f->buf_size) {
539 qemu_fill_buffer(f);
540 if (f->buf_index >= f->buf_size)
541 return 0;
542 }
543 return f->buf[f->buf_index++];
544}
545
546int64_t qemu_ftell(QEMUFile *f)
547{
548 return f->buf_offset - f->buf_size + f->buf_index;
549}
550
551int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
552{
553 if (whence == SEEK_SET) {
554 /* nothing to do */
555 } else if (whence == SEEK_CUR) {
556 pos += qemu_ftell(f);
557 } else {
558 /* SEEK_END not supported */
559 return -1;
560 }
561 if (f->put_buffer) {
562 qemu_fflush(f);
563 f->buf_offset = pos;
564 } else {
565 f->buf_offset = pos;
566 f->buf_index = 0;
567 f->buf_size = 0;
568 }
569 return pos;
570}
571
572int qemu_file_rate_limit(QEMUFile *f)
573{
574 if (f->rate_limit)
575 return f->rate_limit(f->opaque);
576
577 return 0;
578}
579
580size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate)
581{
582 if (f->set_rate_limit)
583 return f->set_rate_limit(f->opaque, new_rate);
584
585 return 0;
586}
587
588void qemu_put_be16(QEMUFile *f, unsigned int v)
589{
590 qemu_put_byte(f, v >> 8);
591 qemu_put_byte(f, v);
592}
593
594void qemu_put_be32(QEMUFile *f, unsigned int v)
595{
596 qemu_put_byte(f, v >> 24);
597 qemu_put_byte(f, v >> 16);
598 qemu_put_byte(f, v >> 8);
599 qemu_put_byte(f, v);
600}
601
602void qemu_put_be64(QEMUFile *f, uint64_t v)
603{
604 qemu_put_be32(f, v >> 32);
605 qemu_put_be32(f, v);
606}
607
608unsigned int qemu_get_be16(QEMUFile *f)
609{
610 unsigned int v;
611 v = qemu_get_byte(f) << 8;
612 v |= qemu_get_byte(f);
613 return v;
614}
615
616unsigned int qemu_get_be32(QEMUFile *f)
617{
618 unsigned int v;
619 v = qemu_get_byte(f) << 24;
620 v |= qemu_get_byte(f) << 16;
621 v |= qemu_get_byte(f) << 8;
622 v |= qemu_get_byte(f);
623 return v;
624}
625
626uint64_t qemu_get_be64(QEMUFile *f)
627{
628 uint64_t v;
629 v = (uint64_t)qemu_get_be32(f) << 32;
630 v |= qemu_get_be32(f);
631 return v;
632}
633
634void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
635{
636 const QField* qf = fields;
637
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100638 /* Iterate over struct fields */
639 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700640 uint8_t* p = (uint8_t*)s + qf->offset;
641
642 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700643 case Q_FIELD_BYTE:
644 qemu_put_byte(f, p[0]);
645 break;
646 case Q_FIELD_INT16:
647 qemu_put_be16(f, ((uint16_t*)p)[0]);
648 break;
649 case Q_FIELD_INT32:
650 qemu_put_be32(f, ((uint32_t*)p)[0]);
651 break;
652 case Q_FIELD_INT64:
653 qemu_put_be64(f, ((uint64_t*)p)[0]);
654 break;
655 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100656 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
657 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700658 {
659 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
660 __FUNCTION__ );
661 exit(1);
662 }
663 else
664 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100665 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700666
667 qemu_put_buffer(f, p, size);
668 qf += 2;
669 }
670 break;
671 default:
672 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
673 exit(1);
674 }
675 qf++;
676 }
677}
678
679int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
680{
681 const QField* qf = fields;
682
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100683 /* Iterate over struct fields */
684 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700685 uint8_t* p = (uint8_t*)s + qf->offset;
686
687 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700688 case Q_FIELD_BYTE:
689 p[0] = qemu_get_byte(f);
690 break;
691 case Q_FIELD_INT16:
692 ((uint16_t*)p)[0] = qemu_get_be16(f);
693 break;
694 case Q_FIELD_INT32:
695 ((uint32_t*)p)[0] = qemu_get_be32(f);
696 break;
697 case Q_FIELD_INT64:
698 ((uint64_t*)p)[0] = qemu_get_be64(f);
699 break;
700 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100701 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
702 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700703 {
704 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
705 __FUNCTION__ );
706 return -1;
707 }
708 else
709 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100710 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700711 int ret = qemu_get_buffer(f, p, size);
712
713 if (ret != size) {
714 fprintf(stderr, "%s: not enough bytes to load structure\n", __FUNCTION__);
715 return -1;
716 }
717 qf += 2;
718 }
719 break;
720 default:
721 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
722 exit(1);
723 }
724 qf++;
725 }
726 return 0;
727}
728
Ot ten Thije871da2a2010-09-20 10:29:22 +0100729/* write a float to file */
730void qemu_put_float(QEMUFile *f, float v)
731{
732 uint8_t *bytes = (uint8_t*) &v;
733 qemu_put_buffer(f, bytes, sizeof(float));
734}
735
736/* read a float from file */
737float qemu_get_float(QEMUFile *f)
738{
739 uint8_t bytes[sizeof(float)];
740 qemu_get_buffer(f, bytes, sizeof(float));
741
742 return *((float*) bytes);
743}
744
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700745typedef struct SaveStateEntry {
746 char idstr[256];
747 int instance_id;
748 int version_id;
749 int section_id;
750 SaveLiveStateHandler *save_live_state;
751 SaveStateHandler *save_state;
752 LoadStateHandler *load_state;
753 void *opaque;
754 struct SaveStateEntry *next;
755} SaveStateEntry;
756
757static SaveStateEntry *first_se;
758
759/* TODO: Individual devices generally have very little idea about the rest
760 of the system, so instance_id should be removed/replaced.
761 Meanwhile pass -1 as instance_id if you do not already have a clearly
762 distinguishing id for all instances of your device class. */
763int register_savevm_live(const char *idstr,
764 int instance_id,
765 int version_id,
766 SaveLiveStateHandler *save_live_state,
767 SaveStateHandler *save_state,
768 LoadStateHandler *load_state,
769 void *opaque)
770{
771 SaveStateEntry *se, **pse;
772 static int global_section_id;
773
774 se = qemu_malloc(sizeof(SaveStateEntry));
775 pstrcpy(se->idstr, sizeof(se->idstr), idstr);
776 se->instance_id = (instance_id == -1) ? 0 : instance_id;
777 se->version_id = version_id;
778 se->section_id = global_section_id++;
779 se->save_live_state = save_live_state;
780 se->save_state = save_state;
781 se->load_state = load_state;
782 se->opaque = opaque;
783 se->next = NULL;
784
785 /* add at the end of list */
786 pse = &first_se;
787 while (*pse != NULL) {
788 if (instance_id == -1
789 && strcmp(se->idstr, (*pse)->idstr) == 0
790 && se->instance_id <= (*pse)->instance_id)
791 se->instance_id = (*pse)->instance_id + 1;
792 pse = &(*pse)->next;
793 }
794 *pse = se;
795 return 0;
796}
797
798int register_savevm(const char *idstr,
799 int instance_id,
800 int version_id,
801 SaveStateHandler *save_state,
802 LoadStateHandler *load_state,
803 void *opaque)
804{
805 return register_savevm_live(idstr, instance_id, version_id,
806 NULL, save_state, load_state, opaque);
807}
808
809void unregister_savevm(const char *idstr, void *opaque)
810{
811 SaveStateEntry **pse;
812
813 pse = &first_se;
814 while (*pse != NULL) {
815 if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
816 SaveStateEntry *next = (*pse)->next;
817 qemu_free(*pse);
818 *pse = next;
819 continue;
820 }
821 pse = &(*pse)->next;
822 }
823}
824
825#define QEMU_VM_FILE_MAGIC 0x5145564d
826#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
827#define QEMU_VM_FILE_VERSION 0x00000003
828
829#define QEMU_VM_EOF 0x00
830#define QEMU_VM_SECTION_START 0x01
831#define QEMU_VM_SECTION_PART 0x02
832#define QEMU_VM_SECTION_END 0x03
833#define QEMU_VM_SECTION_FULL 0x04
834
835int qemu_savevm_state_begin(QEMUFile *f)
836{
837 SaveStateEntry *se;
838
839 qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
840 qemu_put_be32(f, QEMU_VM_FILE_VERSION);
841
842 for (se = first_se; se != NULL; se = se->next) {
843 int len;
844
845 if (se->save_live_state == NULL)
846 continue;
847
848 /* Section type */
849 qemu_put_byte(f, QEMU_VM_SECTION_START);
850 qemu_put_be32(f, se->section_id);
851
852 /* ID string */
853 len = strlen(se->idstr);
854 qemu_put_byte(f, len);
855 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
856
857 qemu_put_be32(f, se->instance_id);
858 qemu_put_be32(f, se->version_id);
859
860 se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
861 }
862
863 if (qemu_file_has_error(f))
864 return -EIO;
865
866 return 0;
867}
868
869int qemu_savevm_state_iterate(QEMUFile *f)
870{
871 SaveStateEntry *se;
872 int ret = 1;
873
874 for (se = first_se; se != NULL; se = se->next) {
875 if (se->save_live_state == NULL)
876 continue;
877
878 /* Section type */
879 qemu_put_byte(f, QEMU_VM_SECTION_PART);
880 qemu_put_be32(f, se->section_id);
881
882 ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
883 }
884
885 if (ret)
886 return 1;
887
888 if (qemu_file_has_error(f))
889 return -EIO;
890
891 return 0;
892}
893
894int qemu_savevm_state_complete(QEMUFile *f)
895{
896 SaveStateEntry *se;
897
898 for (se = first_se; se != NULL; se = se->next) {
899 if (se->save_live_state == NULL)
900 continue;
901
902 /* Section type */
903 qemu_put_byte(f, QEMU_VM_SECTION_END);
904 qemu_put_be32(f, se->section_id);
905
906 se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
907 }
908
909 for(se = first_se; se != NULL; se = se->next) {
910 int len;
911
Ot ten Thije8f2de6d2010-09-30 14:17:10 +0100912 if (se->save_state == NULL)
913 continue;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700914
915 /* Section type */
916 qemu_put_byte(f, QEMU_VM_SECTION_FULL);
917 qemu_put_be32(f, se->section_id);
918
919 /* ID string */
920 len = strlen(se->idstr);
921 qemu_put_byte(f, len);
922 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
923
924 qemu_put_be32(f, se->instance_id);
925 qemu_put_be32(f, se->version_id);
926
927 se->save_state(f, se->opaque);
928 }
929
930 qemu_put_byte(f, QEMU_VM_EOF);
931
932 if (qemu_file_has_error(f))
933 return -EIO;
934
935 return 0;
936}
937
938int qemu_savevm_state(QEMUFile *f)
939{
940 int saved_vm_running;
941 int ret;
942
943 saved_vm_running = vm_running;
944 vm_stop(0);
945
946 bdrv_flush_all();
947
948 ret = qemu_savevm_state_begin(f);
949 if (ret < 0)
950 goto out;
951
952 do {
953 ret = qemu_savevm_state_iterate(f);
954 if (ret < 0)
955 goto out;
956 } while (ret == 0);
957
958 ret = qemu_savevm_state_complete(f);
959
960out:
961 if (qemu_file_has_error(f))
962 ret = -EIO;
963
964 if (!ret && saved_vm_running)
965 vm_start();
966
967 return ret;
968}
969
970static SaveStateEntry *find_se(const char *idstr, int instance_id)
971{
972 SaveStateEntry *se;
973
974 for(se = first_se; se != NULL; se = se->next) {
975 if (!strcmp(se->idstr, idstr) &&
976 instance_id == se->instance_id)
977 return se;
978 }
979 return NULL;
980}
981
982typedef struct LoadStateEntry {
983 SaveStateEntry *se;
984 int section_id;
985 int version_id;
986 struct LoadStateEntry *next;
987} LoadStateEntry;
988
989static int qemu_loadvm_state_v2(QEMUFile *f)
990{
991 SaveStateEntry *se;
992 int len, ret, instance_id, record_len, version_id;
993 int64_t total_len, end_pos, cur_pos;
994 char idstr[256];
995
996 total_len = qemu_get_be64(f);
997 end_pos = total_len + qemu_ftell(f);
998 for(;;) {
999 if (qemu_ftell(f) >= end_pos)
1000 break;
1001 len = qemu_get_byte(f);
1002 qemu_get_buffer(f, (uint8_t *)idstr, len);
1003 idstr[len] = '\0';
1004 instance_id = qemu_get_be32(f);
1005 version_id = qemu_get_be32(f);
1006 record_len = qemu_get_be32(f);
1007 cur_pos = qemu_ftell(f);
1008 se = find_se(idstr, instance_id);
1009 if (!se) {
1010 fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
1011 instance_id, idstr);
1012 } else {
1013 ret = se->load_state(f, se->opaque, version_id);
1014 if (ret < 0) {
1015 fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
1016 instance_id, idstr);
1017 return ret;
1018 }
1019 }
1020 /* always seek to exact end of record */
1021 qemu_fseek(f, cur_pos + record_len, SEEK_SET);
1022 }
1023
1024 if (qemu_file_has_error(f))
1025 return -EIO;
1026
1027 return 0;
1028}
1029
1030int qemu_loadvm_state(QEMUFile *f)
1031{
1032 LoadStateEntry *first_le = NULL;
1033 uint8_t section_type;
1034 unsigned int v;
1035 int ret;
1036
1037 v = qemu_get_be32(f);
1038 if (v != QEMU_VM_FILE_MAGIC)
1039 return -EINVAL;
1040
1041 v = qemu_get_be32(f);
1042 if (v == QEMU_VM_FILE_VERSION_COMPAT)
1043 return qemu_loadvm_state_v2(f);
1044 if (v != QEMU_VM_FILE_VERSION)
1045 return -ENOTSUP;
1046
1047 while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
1048 uint32_t instance_id, version_id, section_id;
1049 LoadStateEntry *le;
1050 SaveStateEntry *se;
1051 char idstr[257];
1052 int len;
1053
1054 switch (section_type) {
1055 case QEMU_VM_SECTION_START:
1056 case QEMU_VM_SECTION_FULL:
1057 /* Read section start */
1058 section_id = qemu_get_be32(f);
1059 len = qemu_get_byte(f);
1060 qemu_get_buffer(f, (uint8_t *)idstr, len);
1061 idstr[len] = 0;
1062 instance_id = qemu_get_be32(f);
1063 version_id = qemu_get_be32(f);
1064
1065 /* Find savevm section */
1066 se = find_se(idstr, instance_id);
1067 if (se == NULL) {
1068 fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
1069 ret = -EINVAL;
1070 goto out;
1071 }
1072
1073 /* Validate version */
1074 if (version_id > se->version_id) {
1075 fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
1076 version_id, idstr, se->version_id);
1077 ret = -EINVAL;
1078 goto out;
1079 }
1080
1081 /* Add entry */
1082 le = qemu_mallocz(sizeof(*le));
1083
1084 le->se = se;
1085 le->section_id = section_id;
1086 le->version_id = version_id;
1087 le->next = first_le;
1088 first_le = le;
1089
1090 le->se->load_state(f, le->se->opaque, le->version_id);
1091 break;
1092 case QEMU_VM_SECTION_PART:
1093 case QEMU_VM_SECTION_END:
1094 section_id = qemu_get_be32(f);
1095
1096 for (le = first_le; le && le->section_id != section_id; le = le->next);
1097 if (le == NULL) {
1098 fprintf(stderr, "Unknown savevm section %d\n", section_id);
1099 ret = -EINVAL;
1100 goto out;
1101 }
1102
1103 le->se->load_state(f, le->se->opaque, le->version_id);
1104 break;
1105 default:
1106 fprintf(stderr, "Unknown savevm section type %d\n", section_type);
1107 ret = -EINVAL;
1108 goto out;
1109 }
1110 }
1111
1112 ret = 0;
1113
1114out:
1115 while (first_le) {
1116 LoadStateEntry *le = first_le;
1117 first_le = first_le->next;
1118 qemu_free(le);
1119 }
1120
1121 if (qemu_file_has_error(f))
1122 ret = -EIO;
1123
1124 return ret;
1125}
1126
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001127static BlockDriverState *get_bs_snapshots(void)
1128{
1129 BlockDriverState *bs;
1130 int i;
1131
1132 if (bs_snapshots)
1133 return bs_snapshots;
1134 for(i = 0; i <= nb_drives; i++) {
1135 bs = drives_table[i].bdrv;
1136 if (bdrv_can_snapshot(bs))
1137 goto ok;
1138 }
1139 return NULL;
1140 ok:
1141 bs_snapshots = bs;
1142 return bs;
1143}
1144
1145static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
1146 const char *name)
1147{
1148 QEMUSnapshotInfo *sn_tab, *sn;
1149 int nb_sns, i, ret;
1150
1151 ret = -ENOENT;
1152 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1153 if (nb_sns < 0)
1154 return ret;
1155 for(i = 0; i < nb_sns; i++) {
1156 sn = &sn_tab[i];
1157 if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
1158 *sn_info = *sn;
1159 ret = 0;
1160 break;
1161 }
1162 }
1163 qemu_free(sn_tab);
1164 return ret;
1165}
1166
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001167static int
1168monitor_output_channel_cb(void* opaque, const char* fmt, va_list ap)
1169{
1170 return monitor_vprintf((Monitor*) opaque, fmt, ap);
1171}
1172
1173
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001174void do_savevm(Monitor *mon, const char *name)
1175{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001176 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1177 do_savevm_oc(oc, name);
1178 output_channel_free(oc);
1179}
1180
1181void do_savevm_oc(OutputChannel *err, const char *name)
1182{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001183 BlockDriverState *bs, *bs1;
1184 QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
1185 int must_delete, ret, i;
1186 BlockDriverInfo bdi1, *bdi = &bdi1;
1187 QEMUFile *f;
1188 int saved_vm_running;
1189 uint32_t vm_state_size;
1190#ifdef _WIN32
1191 struct _timeb tb;
1192#else
1193 struct timeval tv;
1194#endif
1195
1196 bs = get_bs_snapshots();
1197 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001198 output_channel_printf(err, "No block device can accept snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001199 return;
1200 }
1201
1202 /* ??? Should this occur after vm_stop? */
1203 qemu_aio_flush();
1204
1205 saved_vm_running = vm_running;
1206 vm_stop(0);
1207
1208 must_delete = 0;
1209 if (name) {
1210 ret = bdrv_snapshot_find(bs, old_sn, name);
1211 if (ret >= 0) {
1212 must_delete = 1;
1213 }
1214 }
1215 memset(sn, 0, sizeof(*sn));
1216 if (must_delete) {
1217 pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
1218 pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
1219 } else {
1220 if (name)
1221 pstrcpy(sn->name, sizeof(sn->name), name);
1222 }
1223
1224 /* fill auxiliary fields */
1225#ifdef _WIN32
1226 _ftime(&tb);
1227 sn->date_sec = tb.time;
1228 sn->date_nsec = tb.millitm * 1000000;
1229#else
1230 gettimeofday(&tv, NULL);
1231 sn->date_sec = tv.tv_sec;
1232 sn->date_nsec = tv.tv_usec * 1000;
1233#endif
1234 sn->vm_clock_nsec = qemu_get_clock(vm_clock);
1235
1236 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001237 output_channel_printf(err, "Device %s does not support VM state snapshots\n",
1238 bdrv_get_device_name(bs));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001239 goto the_end;
1240 }
1241
1242 /* save the VM state */
1243 f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
1244 if (!f) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001245 output_channel_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001246 goto the_end;
1247 }
1248 ret = qemu_savevm_state(f);
1249 vm_state_size = qemu_ftell(f);
1250 qemu_fclose(f);
1251 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001252 output_channel_printf(err, "Error %d while writing VM\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001253 goto the_end;
1254 }
1255
1256 /* create the snapshots */
1257
1258 for(i = 0; i < nb_drives; i++) {
1259 bs1 = drives_table[i].bdrv;
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001260 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001261 if (must_delete) {
1262 ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
1263 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001264 output_channel_printf(err,
1265 "Error while deleting snapshot on '%s'\n",
1266 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001267 }
1268 }
1269 /* Write VM state size only to the image that contains the state */
1270 sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
1271 ret = bdrv_snapshot_create(bs1, sn);
1272 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001273 output_channel_printf(err, "Error while creating snapshot on '%s'\n",
1274 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001275 }
1276 }
1277 }
1278
1279 the_end:
1280 if (saved_vm_running)
1281 vm_start();
1282}
1283
1284void do_loadvm(Monitor *mon, const char *name)
1285{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001286 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
Tim Baverstock622b8f42010-12-07 11:36:59 +00001287 android_snapshot_update_time_request = 1;
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001288 do_loadvm_oc(oc, name);
1289 output_channel_free(oc);
1290}
1291
1292void do_loadvm_oc(OutputChannel *err, const char *name)
1293{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001294 BlockDriverState *bs, *bs1;
1295 BlockDriverInfo bdi1, *bdi = &bdi1;
1296 QEMUSnapshotInfo sn;
1297 QEMUFile *f;
1298 int i, ret;
1299 int saved_vm_running;
1300
1301 bs = get_bs_snapshots();
1302 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001303 output_channel_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001304 return;
1305 }
1306
1307 /* Flush all IO requests so they don't interfere with the new state. */
1308 qemu_aio_flush();
1309
1310 saved_vm_running = vm_running;
1311 vm_stop(0);
1312
1313 for(i = 0; i <= nb_drives; i++) {
1314 bs1 = drives_table[i].bdrv;
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001315 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001316 ret = bdrv_snapshot_goto(bs1, name);
1317 if (ret < 0) {
1318 if (bs != bs1)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001319 output_channel_printf(err, "Warning: ");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001320 switch(ret) {
1321 case -ENOTSUP:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001322 output_channel_printf(err,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001323 "Snapshots not supported on device '%s'\n",
1324 bdrv_get_device_name(bs1));
1325 break;
1326 case -ENOENT:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001327 output_channel_printf(err, "Could not find snapshot '%s' on "
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001328 "device '%s'\n",
1329 name, bdrv_get_device_name(bs1));
1330 break;
1331 default:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001332 output_channel_printf(err, "Error %d while activating snapshot on"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001333 " '%s'\n", ret, bdrv_get_device_name(bs1));
1334 break;
1335 }
1336 /* fatal on snapshot block device */
1337 if (bs == bs1)
1338 goto the_end;
1339 }
1340 }
1341 }
1342
1343 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001344 output_channel_printf(err, "Device %s does not support VM state snapshots\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001345 bdrv_get_device_name(bs));
1346 return;
1347 }
1348
1349 /* Don't even try to load empty VM states */
1350 ret = bdrv_snapshot_find(bs, &sn, name);
1351 if ((ret >= 0) && (sn.vm_state_size == 0))
1352 goto the_end;
1353
1354 /* restore the VM state */
1355 f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
1356 if (!f) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001357 output_channel_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001358 goto the_end;
1359 }
1360 ret = qemu_loadvm_state(f);
1361 qemu_fclose(f);
1362 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001363 output_channel_printf(err, "Error %d while loading VM state\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001364 }
1365 the_end:
1366 if (saved_vm_running)
1367 vm_start();
1368}
1369
1370void do_delvm(Monitor *mon, const char *name)
1371{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001372 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1373 do_delvm_oc(oc, name);
1374 output_channel_free(oc);
1375}
1376void do_delvm_oc(OutputChannel *err, const char *name)
1377{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001378 BlockDriverState *bs, *bs1;
1379 int i, ret;
1380
1381 bs = get_bs_snapshots();
1382 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001383 output_channel_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001384 return;
1385 }
1386
1387 for(i = 0; i <= nb_drives; i++) {
1388 bs1 = drives_table[i].bdrv;
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001389 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001390 ret = bdrv_snapshot_delete(bs1, name);
1391 if (ret < 0) {
1392 if (ret == -ENOTSUP)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001393 output_channel_printf(err,
1394 "Snapshots not supported on device '%s'\n",
1395 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001396 else
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001397 output_channel_printf(err, "Error %d while deleting snapshot on "
1398 "'%s'\n", ret, bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001399 }
1400 }
1401 }
1402}
1403
1404void do_info_snapshots(Monitor *mon)
1405{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001406 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1407 do_info_snapshots_oc(oc, oc);
1408 output_channel_free(oc);
1409}
1410
1411void do_info_snapshots_oc(OutputChannel *out, OutputChannel *err)
1412{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001413 BlockDriverState *bs, *bs1;
1414 QEMUSnapshotInfo *sn_tab, *sn;
1415 int nb_sns, i;
1416 char buf[256];
1417
1418 bs = get_bs_snapshots();
1419 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001420 output_channel_printf(err, "No available block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001421 return;
1422 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001423 output_channel_printf(out, "Snapshot devices:");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001424 for(i = 0; i <= nb_drives; i++) {
1425 bs1 = drives_table[i].bdrv;
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001426 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001427 if (bs == bs1)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001428 output_channel_printf(out, " %s", bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001429 }
1430 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001431 output_channel_printf(out, "\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001432
1433 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1434 if (nb_sns < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001435 output_channel_printf(err, "bdrv_snapshot_list: error %d\n", nb_sns);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001436 return;
1437 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001438 output_channel_printf(out, "Snapshot list (from %s):\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001439 bdrv_get_device_name(bs));
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001440 output_channel_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001441 for(i = 0; i < nb_sns; i++) {
1442 sn = &sn_tab[i];
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001443 output_channel_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001444 }
1445 qemu_free(sn_tab);
1446}