blob: bbf07c53d324f1b6a06882ebb857fc60c425fe60 [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>
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070045#include <arpa/inet.h>
46#include <dirent.h>
47#include <netdb.h>
48#include <sys/select.h>
David 'Digit' Turner2c538c82010-05-10 16:48:20 -070049#ifdef CONFIG_BSD
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070050#include <sys/stat.h>
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +010051#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070052#include <libutil.h>
53#else
54#include <util.h>
55#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070056#ifdef __linux__
57#include <pty.h>
58#include <malloc.h>
59#include <linux/rtc.h>
60#endif
61#endif
62#endif
63
64#ifdef _WIN32
65#include <windows.h>
66#include <malloc.h>
67#include <sys/timeb.h>
68#include <mmsystem.h>
69#define getopt_long_only getopt_long
70#define memalign(align, size) malloc(size)
71#endif
72
73#include "qemu-common.h"
74#include "hw/hw.h"
75#include "net.h"
76#include "monitor.h"
77#include "sysemu.h"
78#include "qemu-timer.h"
79#include "qemu-char.h"
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +010080#include "blockdev.h"
Ot ten Thije2ff39a32010-10-06 17:48:15 +010081#include "outputchannel.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070082#include "block.h"
83#include "audio/audio.h"
84#include "migration.h"
85#include "qemu_socket.h"
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +010086#include "qemu-queue.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070087#include "qemu_file.h"
Tim Baverstock622b8f42010-12-07 11:36:59 +000088#include "android/snapshot.h"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070089
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -070090
91#define SELF_ANNOUNCE_ROUNDS 5
92#define ETH_P_EXPERIMENTAL 0x01F1 /* just a number */
93//#define ETH_P_EXPERIMENTAL 0x0012 /* make it the size of the packet */
94#define EXPERIMENTAL_MAGIC 0xf1f23f4f
95
96static int announce_self_create(uint8_t *buf,
97 uint8_t *mac_addr)
98{
99 uint32_t magic = EXPERIMENTAL_MAGIC;
100 uint16_t proto = htons(ETH_P_EXPERIMENTAL);
101
102 /* FIXME: should we send a different packet (arp/rarp/ping)? */
103
104 memset(buf, 0, 64);
105 memset(buf, 0xff, 6); /* h_dst */
106 memcpy(buf + 6, mac_addr, 6); /* h_src */
107 memcpy(buf + 12, &proto, 2); /* h_proto */
108 memcpy(buf + 14, &magic, 4); /* magic */
109
110 return 64; /* len */
111}
112
113static void qemu_announce_self_once(void *opaque)
114{
115 int i, len;
116 VLANState *vlan;
117 VLANClientState *vc;
118 uint8_t buf[256];
119 static int count = SELF_ANNOUNCE_ROUNDS;
120 QEMUTimer *timer = *(QEMUTimer **)opaque;
121
122 for (i = 0; i < MAX_NICS; i++) {
123 if (!nd_table[i].used)
124 continue;
125 len = announce_self_create(buf, nd_table[i].macaddr);
126 vlan = nd_table[i].vlan;
127 for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
128 vc->receive(vc, buf, len);
129 }
130 }
131 if (count--) {
132 qemu_mod_timer(timer, qemu_get_clock(rt_clock) + 100);
133 } else {
134 qemu_del_timer(timer);
135 qemu_free_timer(timer);
136 }
137}
138
139void qemu_announce_self(void)
140{
141 static QEMUTimer *timer;
142 timer = qemu_new_timer(rt_clock, qemu_announce_self_once, &timer);
143 qemu_announce_self_once(&timer);
144}
145
146/***********************************************************/
147/* savevm/loadvm support */
148
149#define IO_BUF_SIZE 32768
150
151struct QEMUFile {
152 QEMUFilePutBufferFunc *put_buffer;
153 QEMUFileGetBufferFunc *get_buffer;
154 QEMUFileCloseFunc *close;
155 QEMUFileRateLimit *rate_limit;
156 QEMUFileSetRateLimit *set_rate_limit;
David Turnera12820e2010-09-09 21:16:39 +0200157 QEMUFileGetRateLimit *get_rate_limit;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700158 void *opaque;
159 int is_write;
160
161 int64_t buf_offset; /* start of buffer when writing, end of buffer
162 when reading */
163 int buf_index;
164 int buf_size; /* 0 when writing */
165 uint8_t buf[IO_BUF_SIZE];
166
167 int has_error;
168};
169
170typedef struct QEMUFilePopen
171{
172 FILE *popen_file;
173 QEMUFile *file;
174} QEMUFilePopen;
175
176typedef struct QEMUFileSocket
177{
178 int fd;
179 QEMUFile *file;
180} QEMUFileSocket;
181
182static int file_socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
183{
184 QEMUFileSocket *s = opaque;
185 ssize_t len;
186
187 do {
188 len = recv(s->fd, (void *)buf, size, 0);
189 } while (len == -1 && socket_error() == EINTR);
190
191 if (len == -1)
192 len = -socket_error();
193
194 return len;
195}
196
197static int file_socket_close(void *opaque)
198{
199 QEMUFileSocket *s = opaque;
200 qemu_free(s);
201 return 0;
202}
203
204static int popen_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
205{
206 QEMUFilePopen *s = opaque;
207 return fwrite(buf, 1, size, s->popen_file);
208}
209
210static int popen_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
211{
212 QEMUFilePopen *s = opaque;
213 FILE *fp = s->popen_file;
214 int bytes;
215
216 do {
217 clearerr(fp);
218 bytes = fread(buf, 1, size, fp);
219 } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
220 return bytes;
221}
222
223static int popen_close(void *opaque)
224{
225 QEMUFilePopen *s = opaque;
226 pclose(s->popen_file);
227 qemu_free(s);
228 return 0;
229}
230
231QEMUFile *qemu_popen(FILE *popen_file, const char *mode)
232{
233 QEMUFilePopen *s;
234
235 if (popen_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
236 fprintf(stderr, "qemu_popen: Argument validity check failed\n");
237 return NULL;
238 }
239
240 s = qemu_mallocz(sizeof(QEMUFilePopen));
241
242 s->popen_file = popen_file;
243
244 if(mode[0] == 'r') {
David Turnera12820e2010-09-09 21:16:39 +0200245 s->file = qemu_fopen_ops(s, NULL, popen_get_buffer, popen_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700246 } else {
David Turnera12820e2010-09-09 21:16:39 +0200247 s->file = qemu_fopen_ops(s, popen_put_buffer, NULL, popen_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700248 }
249 return s->file;
250}
251
252QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
253{
254 FILE *popen_file;
255
256 popen_file = popen(command, mode);
257 if(popen_file == NULL) {
258 return NULL;
259 }
260
261 return qemu_popen(popen_file, mode);
262}
263
264int qemu_popen_fd(QEMUFile *f)
265{
266 QEMUFilePopen *p;
267 int fd;
268
269 p = (QEMUFilePopen *)f->opaque;
270 fd = fileno(p->popen_file);
271
272 return fd;
273}
274
275QEMUFile *qemu_fopen_socket(int fd)
276{
277 QEMUFileSocket *s = qemu_mallocz(sizeof(QEMUFileSocket));
278
279 s->fd = fd;
David Turnera12820e2010-09-09 21:16:39 +0200280 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 -0700281 return s->file;
282}
283
284typedef struct QEMUFileStdio
285{
286 FILE *outfile;
287} QEMUFileStdio;
288
289static int file_put_buffer(void *opaque, const uint8_t *buf,
290 int64_t pos, int size)
291{
292 QEMUFileStdio *s = opaque;
293 fseek(s->outfile, pos, SEEK_SET);
294 fwrite(buf, 1, size, s->outfile);
295 return size;
296}
297
298static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
299{
300 QEMUFileStdio *s = opaque;
301 fseek(s->outfile, pos, SEEK_SET);
302 return fread(buf, 1, size, s->outfile);
303}
304
305static int file_close(void *opaque)
306{
307 QEMUFileStdio *s = opaque;
308 fclose(s->outfile);
309 qemu_free(s);
310 return 0;
311}
312
313QEMUFile *qemu_fopen(const char *filename, const char *mode)
314{
315 QEMUFileStdio *s;
316
317 s = qemu_mallocz(sizeof(QEMUFileStdio));
318
319 s->outfile = fopen(filename, mode);
320 if (!s->outfile)
321 goto fail;
322
323 if (!strcmp(mode, "wb"))
David Turnera12820e2010-09-09 21:16:39 +0200324 return qemu_fopen_ops(s, file_put_buffer, NULL, file_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700325 else if (!strcmp(mode, "rb"))
David Turnera12820e2010-09-09 21:16:39 +0200326 return qemu_fopen_ops(s, NULL, file_get_buffer, file_close, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700327
328fail:
329 if (s->outfile)
330 fclose(s->outfile);
331 qemu_free(s);
332 return NULL;
333}
334
335typedef struct QEMUFileBdrv
336{
337 BlockDriverState *bs;
338 int64_t base_offset;
339} QEMUFileBdrv;
340
341static int block_put_buffer(void *opaque, const uint8_t *buf,
342 int64_t pos, int size)
343{
Tim Baverstocka413a352011-01-10 18:45:07 +0000344 bdrv_save_vmstate(((QEMUFileBdrv*)opaque)->bs, buf, pos, size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700345 return size;
346}
347
348static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
349{
Tim Baverstocka413a352011-01-10 18:45:07 +0000350 return bdrv_load_vmstate(((QEMUFileBdrv*)opaque)->bs, buf, pos, size);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700351}
352
353static int bdrv_fclose(void *opaque)
354{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700355 return 0;
356}
357
358static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int64_t offset, int is_writable)
359{
360 QEMUFileBdrv *s;
361
362 s = qemu_mallocz(sizeof(QEMUFileBdrv));
363
364 s->bs = bs;
365 s->base_offset = offset;
366
367 if (is_writable)
David Turnera12820e2010-09-09 21:16:39 +0200368 return qemu_fopen_ops(s, block_put_buffer, NULL, bdrv_fclose, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700369
David Turnera12820e2010-09-09 21:16:39 +0200370 return qemu_fopen_ops(s, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700371}
372
373QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
374 QEMUFileGetBufferFunc *get_buffer,
375 QEMUFileCloseFunc *close,
376 QEMUFileRateLimit *rate_limit,
David Turnera12820e2010-09-09 21:16:39 +0200377 QEMUFileSetRateLimit *set_rate_limit,
378 QEMUFileGetRateLimit *get_rate_limit)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700379{
380 QEMUFile *f;
381
382 f = qemu_mallocz(sizeof(QEMUFile));
383
384 f->opaque = opaque;
385 f->put_buffer = put_buffer;
386 f->get_buffer = get_buffer;
387 f->close = close;
388 f->rate_limit = rate_limit;
389 f->set_rate_limit = set_rate_limit;
390 f->is_write = 0;
391
392 return f;
393}
394
395int qemu_file_has_error(QEMUFile *f)
396{
397 return f->has_error;
398}
399
400void qemu_file_set_error(QEMUFile *f)
401{
402 f->has_error = 1;
403}
404
405void qemu_fflush(QEMUFile *f)
406{
407 if (!f->put_buffer)
408 return;
409
410 if (f->is_write && f->buf_index > 0) {
411 int len;
412
413 len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
414 if (len > 0)
415 f->buf_offset += f->buf_index;
416 else
417 f->has_error = 1;
418 f->buf_index = 0;
419 }
420}
421
422static void qemu_fill_buffer(QEMUFile *f)
423{
424 int len;
425
426 if (!f->get_buffer)
427 return;
428
429 if (f->is_write)
430 abort();
431
432 len = f->get_buffer(f->opaque, f->buf, f->buf_offset, IO_BUF_SIZE);
433 if (len > 0) {
434 f->buf_index = 0;
435 f->buf_size = len;
436 f->buf_offset += len;
437 } else if (len != -EAGAIN)
438 f->has_error = 1;
439}
440
441int qemu_fclose(QEMUFile *f)
442{
443 int ret = 0;
444 qemu_fflush(f);
445 if (f->close)
446 ret = f->close(f->opaque);
447 qemu_free(f);
448 return ret;
449}
450
451void qemu_file_put_notify(QEMUFile *f)
452{
453 f->put_buffer(f->opaque, NULL, 0, 0);
454}
455
456void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
457{
458 int l;
459
460 if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
461 fprintf(stderr,
462 "Attempted to write to buffer while read buffer is not empty\n");
463 abort();
464 }
465
466 while (!f->has_error && size > 0) {
467 l = IO_BUF_SIZE - f->buf_index;
468 if (l > size)
469 l = size;
470 memcpy(f->buf + f->buf_index, buf, l);
471 f->is_write = 1;
472 f->buf_index += l;
473 buf += l;
474 size -= l;
475 if (f->buf_index >= IO_BUF_SIZE)
476 qemu_fflush(f);
477 }
478}
479
480void qemu_put_byte(QEMUFile *f, int v)
481{
482 if (!f->has_error && f->is_write == 0 && f->buf_index > 0) {
483 fprintf(stderr,
484 "Attempted to write to buffer while read buffer is not empty\n");
485 abort();
486 }
487
488 f->buf[f->buf_index++] = v;
489 f->is_write = 1;
490 if (f->buf_index >= IO_BUF_SIZE)
491 qemu_fflush(f);
492}
493
494int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size1)
495{
496 int size, l;
497
498 if (f->is_write)
499 abort();
500
501 size = size1;
502 while (size > 0) {
503 l = f->buf_size - f->buf_index;
504 if (l == 0) {
505 qemu_fill_buffer(f);
506 l = f->buf_size - f->buf_index;
507 if (l == 0)
508 break;
509 }
510 if (l > size)
511 l = size;
512 memcpy(buf, f->buf + f->buf_index, l);
513 f->buf_index += l;
514 buf += l;
515 size -= l;
516 }
517 return size1 - size;
518}
519
520int qemu_get_byte(QEMUFile *f)
521{
522 if (f->is_write)
523 abort();
524
525 if (f->buf_index >= f->buf_size) {
526 qemu_fill_buffer(f);
527 if (f->buf_index >= f->buf_size)
528 return 0;
529 }
530 return f->buf[f->buf_index++];
531}
532
533int64_t qemu_ftell(QEMUFile *f)
534{
535 return f->buf_offset - f->buf_size + f->buf_index;
536}
537
538int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
539{
540 if (whence == SEEK_SET) {
541 /* nothing to do */
542 } else if (whence == SEEK_CUR) {
543 pos += qemu_ftell(f);
544 } else {
545 /* SEEK_END not supported */
546 return -1;
547 }
548 if (f->put_buffer) {
549 qemu_fflush(f);
550 f->buf_offset = pos;
551 } else {
552 f->buf_offset = pos;
553 f->buf_index = 0;
554 f->buf_size = 0;
555 }
556 return pos;
557}
558
559int qemu_file_rate_limit(QEMUFile *f)
560{
561 if (f->rate_limit)
562 return f->rate_limit(f->opaque);
563
564 return 0;
565}
566
567size_t qemu_file_set_rate_limit(QEMUFile *f, size_t new_rate)
568{
569 if (f->set_rate_limit)
570 return f->set_rate_limit(f->opaque, new_rate);
571
572 return 0;
573}
574
575void qemu_put_be16(QEMUFile *f, unsigned int v)
576{
577 qemu_put_byte(f, v >> 8);
578 qemu_put_byte(f, v);
579}
580
581void qemu_put_be32(QEMUFile *f, unsigned int v)
582{
583 qemu_put_byte(f, v >> 24);
584 qemu_put_byte(f, v >> 16);
585 qemu_put_byte(f, v >> 8);
586 qemu_put_byte(f, v);
587}
588
589void qemu_put_be64(QEMUFile *f, uint64_t v)
590{
591 qemu_put_be32(f, v >> 32);
592 qemu_put_be32(f, v);
593}
594
595unsigned int qemu_get_be16(QEMUFile *f)
596{
597 unsigned int v;
598 v = qemu_get_byte(f) << 8;
599 v |= qemu_get_byte(f);
600 return v;
601}
602
603unsigned int qemu_get_be32(QEMUFile *f)
604{
605 unsigned int v;
606 v = qemu_get_byte(f) << 24;
607 v |= qemu_get_byte(f) << 16;
608 v |= qemu_get_byte(f) << 8;
609 v |= qemu_get_byte(f);
610 return v;
611}
612
613uint64_t qemu_get_be64(QEMUFile *f)
614{
615 uint64_t v;
616 v = (uint64_t)qemu_get_be32(f) << 32;
617 v |= qemu_get_be32(f);
618 return v;
619}
620
621void qemu_put_struct(QEMUFile* f, const QField* fields, const void* s)
622{
623 const QField* qf = fields;
624
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100625 /* Iterate over struct fields */
626 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700627 uint8_t* p = (uint8_t*)s + qf->offset;
628
629 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700630 case Q_FIELD_BYTE:
631 qemu_put_byte(f, p[0]);
632 break;
633 case Q_FIELD_INT16:
634 qemu_put_be16(f, ((uint16_t*)p)[0]);
635 break;
636 case Q_FIELD_INT32:
637 qemu_put_be32(f, ((uint32_t*)p)[0]);
638 break;
639 case Q_FIELD_INT64:
640 qemu_put_be64(f, ((uint64_t*)p)[0]);
641 break;
642 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100643 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
644 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700645 {
646 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument. aborting\n",
647 __FUNCTION__ );
648 exit(1);
649 }
650 else
651 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100652 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700653
654 qemu_put_buffer(f, p, size);
655 qf += 2;
656 }
657 break;
658 default:
659 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
660 exit(1);
661 }
662 qf++;
663 }
664}
665
666int qemu_get_struct(QEMUFile* f, const QField* fields, void* s)
667{
668 const QField* qf = fields;
669
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100670 /* Iterate over struct fields */
671 while (qf->type != Q_FIELD_END) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700672 uint8_t* p = (uint8_t*)s + qf->offset;
673
674 switch (qf->type) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700675 case Q_FIELD_BYTE:
676 p[0] = qemu_get_byte(f);
677 break;
678 case Q_FIELD_INT16:
679 ((uint16_t*)p)[0] = qemu_get_be16(f);
680 break;
681 case Q_FIELD_INT32:
682 ((uint32_t*)p)[0] = qemu_get_be32(f);
683 break;
684 case Q_FIELD_INT64:
685 ((uint64_t*)p)[0] = qemu_get_be64(f);
686 break;
687 case Q_FIELD_BUFFER:
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100688 if (qf[1].type != Q_FIELD_BUFFER_SIZE ||
689 qf[2].type != Q_FIELD_BUFFER_SIZE)
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700690 {
691 fprintf(stderr, "%s: invalid QFIELD_BUFFER item passed as argument.\n",
692 __FUNCTION__ );
693 return -1;
694 }
695 else
696 {
Ot ten Thije7fd67eb2010-07-29 10:26:01 +0100697 uint32_t size = ((uint32_t)qf[1].offset << 16) | (uint32_t)qf[2].offset;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700698 int ret = qemu_get_buffer(f, p, size);
699
700 if (ret != size) {
701 fprintf(stderr, "%s: not enough bytes to load structure\n", __FUNCTION__);
702 return -1;
703 }
704 qf += 2;
705 }
706 break;
707 default:
708 fprintf(stderr, "%s: invalid fields list passed as argument. aborting\n", __FUNCTION__);
709 exit(1);
710 }
711 qf++;
712 }
713 return 0;
714}
715
Ot ten Thije871da2a2010-09-20 10:29:22 +0100716/* write a float to file */
717void qemu_put_float(QEMUFile *f, float v)
718{
719 uint8_t *bytes = (uint8_t*) &v;
720 qemu_put_buffer(f, bytes, sizeof(float));
721}
722
723/* read a float from file */
724float qemu_get_float(QEMUFile *f)
725{
726 uint8_t bytes[sizeof(float)];
727 qemu_get_buffer(f, bytes, sizeof(float));
728
729 return *((float*) bytes);
730}
731
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700732typedef struct SaveStateEntry {
733 char idstr[256];
734 int instance_id;
735 int version_id;
736 int section_id;
737 SaveLiveStateHandler *save_live_state;
738 SaveStateHandler *save_state;
739 LoadStateHandler *load_state;
740 void *opaque;
741 struct SaveStateEntry *next;
742} SaveStateEntry;
743
744static SaveStateEntry *first_se;
745
746/* TODO: Individual devices generally have very little idea about the rest
747 of the system, so instance_id should be removed/replaced.
748 Meanwhile pass -1 as instance_id if you do not already have a clearly
749 distinguishing id for all instances of your device class. */
750int register_savevm_live(const char *idstr,
751 int instance_id,
752 int version_id,
753 SaveLiveStateHandler *save_live_state,
754 SaveStateHandler *save_state,
755 LoadStateHandler *load_state,
756 void *opaque)
757{
758 SaveStateEntry *se, **pse;
759 static int global_section_id;
760
761 se = qemu_malloc(sizeof(SaveStateEntry));
762 pstrcpy(se->idstr, sizeof(se->idstr), idstr);
763 se->instance_id = (instance_id == -1) ? 0 : instance_id;
764 se->version_id = version_id;
765 se->section_id = global_section_id++;
766 se->save_live_state = save_live_state;
767 se->save_state = save_state;
768 se->load_state = load_state;
769 se->opaque = opaque;
770 se->next = NULL;
771
772 /* add at the end of list */
773 pse = &first_se;
774 while (*pse != NULL) {
775 if (instance_id == -1
776 && strcmp(se->idstr, (*pse)->idstr) == 0
777 && se->instance_id <= (*pse)->instance_id)
778 se->instance_id = (*pse)->instance_id + 1;
779 pse = &(*pse)->next;
780 }
781 *pse = se;
782 return 0;
783}
784
785int register_savevm(const char *idstr,
786 int instance_id,
787 int version_id,
788 SaveStateHandler *save_state,
789 LoadStateHandler *load_state,
790 void *opaque)
791{
792 return register_savevm_live(idstr, instance_id, version_id,
793 NULL, save_state, load_state, opaque);
794}
795
796void unregister_savevm(const char *idstr, void *opaque)
797{
798 SaveStateEntry **pse;
799
800 pse = &first_se;
801 while (*pse != NULL) {
802 if (strcmp((*pse)->idstr, idstr) == 0 && (*pse)->opaque == opaque) {
803 SaveStateEntry *next = (*pse)->next;
804 qemu_free(*pse);
805 *pse = next;
806 continue;
807 }
808 pse = &(*pse)->next;
809 }
810}
811
812#define QEMU_VM_FILE_MAGIC 0x5145564d
813#define QEMU_VM_FILE_VERSION_COMPAT 0x00000002
814#define QEMU_VM_FILE_VERSION 0x00000003
815
816#define QEMU_VM_EOF 0x00
817#define QEMU_VM_SECTION_START 0x01
818#define QEMU_VM_SECTION_PART 0x02
819#define QEMU_VM_SECTION_END 0x03
820#define QEMU_VM_SECTION_FULL 0x04
821
822int qemu_savevm_state_begin(QEMUFile *f)
823{
824 SaveStateEntry *se;
825
826 qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
827 qemu_put_be32(f, QEMU_VM_FILE_VERSION);
828
829 for (se = first_se; se != NULL; se = se->next) {
830 int len;
831
832 if (se->save_live_state == NULL)
833 continue;
834
835 /* Section type */
836 qemu_put_byte(f, QEMU_VM_SECTION_START);
837 qemu_put_be32(f, se->section_id);
838
839 /* ID string */
840 len = strlen(se->idstr);
841 qemu_put_byte(f, len);
842 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
843
844 qemu_put_be32(f, se->instance_id);
845 qemu_put_be32(f, se->version_id);
846
847 se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
848 }
849
850 if (qemu_file_has_error(f))
851 return -EIO;
852
853 return 0;
854}
855
856int qemu_savevm_state_iterate(QEMUFile *f)
857{
858 SaveStateEntry *se;
859 int ret = 1;
860
861 for (se = first_se; se != NULL; se = se->next) {
862 if (se->save_live_state == NULL)
863 continue;
864
865 /* Section type */
866 qemu_put_byte(f, QEMU_VM_SECTION_PART);
867 qemu_put_be32(f, se->section_id);
868
869 ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
870 }
871
872 if (ret)
873 return 1;
874
875 if (qemu_file_has_error(f))
876 return -EIO;
877
878 return 0;
879}
880
881int qemu_savevm_state_complete(QEMUFile *f)
882{
883 SaveStateEntry *se;
884
885 for (se = first_se; se != NULL; se = se->next) {
886 if (se->save_live_state == NULL)
887 continue;
888
889 /* Section type */
890 qemu_put_byte(f, QEMU_VM_SECTION_END);
891 qemu_put_be32(f, se->section_id);
892
893 se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
894 }
895
896 for(se = first_se; se != NULL; se = se->next) {
897 int len;
898
Ot ten Thije8f2de6d2010-09-30 14:17:10 +0100899 if (se->save_state == NULL)
900 continue;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -0700901
902 /* Section type */
903 qemu_put_byte(f, QEMU_VM_SECTION_FULL);
904 qemu_put_be32(f, se->section_id);
905
906 /* ID string */
907 len = strlen(se->idstr);
908 qemu_put_byte(f, len);
909 qemu_put_buffer(f, (uint8_t *)se->idstr, len);
910
911 qemu_put_be32(f, se->instance_id);
912 qemu_put_be32(f, se->version_id);
913
914 se->save_state(f, se->opaque);
915 }
916
917 qemu_put_byte(f, QEMU_VM_EOF);
918
919 if (qemu_file_has_error(f))
920 return -EIO;
921
922 return 0;
923}
924
925int qemu_savevm_state(QEMUFile *f)
926{
927 int saved_vm_running;
928 int ret;
929
930 saved_vm_running = vm_running;
931 vm_stop(0);
932
933 bdrv_flush_all();
934
935 ret = qemu_savevm_state_begin(f);
936 if (ret < 0)
937 goto out;
938
939 do {
940 ret = qemu_savevm_state_iterate(f);
941 if (ret < 0)
942 goto out;
943 } while (ret == 0);
944
945 ret = qemu_savevm_state_complete(f);
946
947out:
948 if (qemu_file_has_error(f))
949 ret = -EIO;
950
951 if (!ret && saved_vm_running)
952 vm_start();
953
954 return ret;
955}
956
957static SaveStateEntry *find_se(const char *idstr, int instance_id)
958{
959 SaveStateEntry *se;
960
961 for(se = first_se; se != NULL; se = se->next) {
962 if (!strcmp(se->idstr, idstr) &&
963 instance_id == se->instance_id)
964 return se;
965 }
966 return NULL;
967}
968
969typedef struct LoadStateEntry {
970 SaveStateEntry *se;
971 int section_id;
972 int version_id;
973 struct LoadStateEntry *next;
974} LoadStateEntry;
975
976static int qemu_loadvm_state_v2(QEMUFile *f)
977{
978 SaveStateEntry *se;
979 int len, ret, instance_id, record_len, version_id;
980 int64_t total_len, end_pos, cur_pos;
981 char idstr[256];
982
983 total_len = qemu_get_be64(f);
984 end_pos = total_len + qemu_ftell(f);
985 for(;;) {
986 if (qemu_ftell(f) >= end_pos)
987 break;
988 len = qemu_get_byte(f);
989 qemu_get_buffer(f, (uint8_t *)idstr, len);
990 idstr[len] = '\0';
991 instance_id = qemu_get_be32(f);
992 version_id = qemu_get_be32(f);
993 record_len = qemu_get_be32(f);
994 cur_pos = qemu_ftell(f);
995 se = find_se(idstr, instance_id);
996 if (!se) {
997 fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
998 instance_id, idstr);
999 } else {
1000 ret = se->load_state(f, se->opaque, version_id);
1001 if (ret < 0) {
1002 fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
1003 instance_id, idstr);
1004 return ret;
1005 }
1006 }
1007 /* always seek to exact end of record */
1008 qemu_fseek(f, cur_pos + record_len, SEEK_SET);
1009 }
1010
1011 if (qemu_file_has_error(f))
1012 return -EIO;
1013
1014 return 0;
1015}
1016
1017int qemu_loadvm_state(QEMUFile *f)
1018{
1019 LoadStateEntry *first_le = NULL;
1020 uint8_t section_type;
1021 unsigned int v;
1022 int ret;
1023
1024 v = qemu_get_be32(f);
1025 if (v != QEMU_VM_FILE_MAGIC)
1026 return -EINVAL;
1027
1028 v = qemu_get_be32(f);
1029 if (v == QEMU_VM_FILE_VERSION_COMPAT)
1030 return qemu_loadvm_state_v2(f);
1031 if (v != QEMU_VM_FILE_VERSION)
1032 return -ENOTSUP;
1033
1034 while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
1035 uint32_t instance_id, version_id, section_id;
1036 LoadStateEntry *le;
1037 SaveStateEntry *se;
1038 char idstr[257];
1039 int len;
1040
1041 switch (section_type) {
1042 case QEMU_VM_SECTION_START:
1043 case QEMU_VM_SECTION_FULL:
1044 /* Read section start */
1045 section_id = qemu_get_be32(f);
1046 len = qemu_get_byte(f);
1047 qemu_get_buffer(f, (uint8_t *)idstr, len);
1048 idstr[len] = 0;
1049 instance_id = qemu_get_be32(f);
1050 version_id = qemu_get_be32(f);
1051
1052 /* Find savevm section */
1053 se = find_se(idstr, instance_id);
1054 if (se == NULL) {
1055 fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
1056 ret = -EINVAL;
1057 goto out;
1058 }
1059
1060 /* Validate version */
1061 if (version_id > se->version_id) {
1062 fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
1063 version_id, idstr, se->version_id);
1064 ret = -EINVAL;
1065 goto out;
1066 }
1067
1068 /* Add entry */
1069 le = qemu_mallocz(sizeof(*le));
1070
1071 le->se = se;
1072 le->section_id = section_id;
1073 le->version_id = version_id;
1074 le->next = first_le;
1075 first_le = le;
1076
1077 le->se->load_state(f, le->se->opaque, le->version_id);
1078 break;
1079 case QEMU_VM_SECTION_PART:
1080 case QEMU_VM_SECTION_END:
1081 section_id = qemu_get_be32(f);
1082
1083 for (le = first_le; le && le->section_id != section_id; le = le->next);
1084 if (le == NULL) {
1085 fprintf(stderr, "Unknown savevm section %d\n", section_id);
1086 ret = -EINVAL;
1087 goto out;
1088 }
1089
1090 le->se->load_state(f, le->se->opaque, le->version_id);
1091 break;
1092 default:
1093 fprintf(stderr, "Unknown savevm section type %d\n", section_type);
1094 ret = -EINVAL;
1095 goto out;
1096 }
1097 }
1098
1099 ret = 0;
1100
1101out:
1102 while (first_le) {
1103 LoadStateEntry *le = first_le;
1104 first_le = first_le->next;
1105 qemu_free(le);
1106 }
1107
1108 if (qemu_file_has_error(f))
1109 ret = -EIO;
1110
1111 return ret;
1112}
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001113#if 0
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001114static BlockDriverState *get_bs_snapshots(void)
1115{
1116 BlockDriverState *bs;
1117 int i;
1118
1119 if (bs_snapshots)
1120 return bs_snapshots;
1121 for(i = 0; i <= nb_drives; i++) {
1122 bs = drives_table[i].bdrv;
1123 if (bdrv_can_snapshot(bs))
1124 goto ok;
1125 }
1126 return NULL;
1127 ok:
1128 bs_snapshots = bs;
1129 return bs;
1130}
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001131#endif
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001132static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
1133 const char *name)
1134{
1135 QEMUSnapshotInfo *sn_tab, *sn;
1136 int nb_sns, i, ret;
1137
1138 ret = -ENOENT;
1139 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1140 if (nb_sns < 0)
1141 return ret;
1142 for(i = 0; i < nb_sns; i++) {
1143 sn = &sn_tab[i];
1144 if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
1145 *sn_info = *sn;
1146 ret = 0;
1147 break;
1148 }
1149 }
1150 qemu_free(sn_tab);
1151 return ret;
1152}
1153
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001154static int
1155monitor_output_channel_cb(void* opaque, const char* fmt, va_list ap)
1156{
1157 return monitor_vprintf((Monitor*) opaque, fmt, ap);
1158}
1159
1160
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001161void do_savevm(Monitor *mon, const char *name)
1162{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001163 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1164 do_savevm_oc(oc, name);
1165 output_channel_free(oc);
1166}
1167
1168void do_savevm_oc(OutputChannel *err, const char *name)
1169{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001170 BlockDriverState *bs, *bs1;
1171 QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001172 int must_delete, ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001173 BlockDriverInfo bdi1, *bdi = &bdi1;
1174 QEMUFile *f;
1175 int saved_vm_running;
1176 uint32_t vm_state_size;
1177#ifdef _WIN32
1178 struct _timeb tb;
1179#else
1180 struct timeval tv;
1181#endif
1182
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001183 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001184 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001185 output_channel_printf(err, "No block device can accept snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001186 return;
1187 }
1188
1189 /* ??? Should this occur after vm_stop? */
1190 qemu_aio_flush();
1191
1192 saved_vm_running = vm_running;
1193 vm_stop(0);
1194
1195 must_delete = 0;
1196 if (name) {
1197 ret = bdrv_snapshot_find(bs, old_sn, name);
1198 if (ret >= 0) {
1199 must_delete = 1;
1200 }
1201 }
1202 memset(sn, 0, sizeof(*sn));
1203 if (must_delete) {
1204 pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
1205 pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
1206 } else {
1207 if (name)
1208 pstrcpy(sn->name, sizeof(sn->name), name);
1209 }
1210
1211 /* fill auxiliary fields */
1212#ifdef _WIN32
1213 _ftime(&tb);
1214 sn->date_sec = tb.time;
1215 sn->date_nsec = tb.millitm * 1000000;
1216#else
1217 gettimeofday(&tv, NULL);
1218 sn->date_sec = tv.tv_sec;
1219 sn->date_nsec = tv.tv_usec * 1000;
1220#endif
1221 sn->vm_clock_nsec = qemu_get_clock(vm_clock);
1222
1223 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001224 output_channel_printf(err, "Device %s does not support VM state snapshots\n",
1225 bdrv_get_device_name(bs));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001226 goto the_end;
1227 }
1228
1229 /* save the VM state */
1230 f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1);
1231 if (!f) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001232 output_channel_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001233 goto the_end;
1234 }
1235 ret = qemu_savevm_state(f);
1236 vm_state_size = qemu_ftell(f);
1237 qemu_fclose(f);
1238 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001239 output_channel_printf(err, "Error %d while writing VM\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001240 goto the_end;
1241 }
1242
1243 /* create the snapshots */
1244
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001245 bs1 = NULL;
1246 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001247 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001248 if (must_delete) {
1249 ret = bdrv_snapshot_delete(bs1, old_sn->id_str);
1250 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001251 output_channel_printf(err,
1252 "Error while deleting snapshot on '%s'\n",
1253 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001254 }
1255 }
1256 /* Write VM state size only to the image that contains the state */
1257 sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
1258 ret = bdrv_snapshot_create(bs1, sn);
1259 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001260 output_channel_printf(err, "Error while creating snapshot on '%s'\n",
1261 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001262 }
1263 }
1264 }
1265
1266 the_end:
1267 if (saved_vm_running)
1268 vm_start();
1269}
1270
1271void do_loadvm(Monitor *mon, const char *name)
1272{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001273 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
Tim Baverstock622b8f42010-12-07 11:36:59 +00001274 android_snapshot_update_time_request = 1;
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001275 do_loadvm_oc(oc, name);
1276 output_channel_free(oc);
1277}
1278
1279void do_loadvm_oc(OutputChannel *err, const char *name)
1280{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001281 BlockDriverState *bs, *bs1;
1282 BlockDriverInfo bdi1, *bdi = &bdi1;
1283 QEMUSnapshotInfo sn;
1284 QEMUFile *f;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001285 int ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001286 int saved_vm_running;
1287
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001288 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001289 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001290 output_channel_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001291 return;
1292 }
1293
1294 /* Flush all IO requests so they don't interfere with the new state. */
1295 qemu_aio_flush();
1296
1297 saved_vm_running = vm_running;
1298 vm_stop(0);
1299
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001300 bs1 = NULL;
1301 while ((bs1 = bdrv_next(bs))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001302 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001303 ret = bdrv_snapshot_goto(bs1, name);
1304 if (ret < 0) {
1305 if (bs != bs1)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001306 output_channel_printf(err, "Warning: ");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001307 switch(ret) {
1308 case -ENOTSUP:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001309 output_channel_printf(err,
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001310 "Snapshots not supported on device '%s'\n",
1311 bdrv_get_device_name(bs1));
1312 break;
1313 case -ENOENT:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001314 output_channel_printf(err, "Could not find snapshot '%s' on "
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001315 "device '%s'\n",
1316 name, bdrv_get_device_name(bs1));
1317 break;
1318 default:
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001319 output_channel_printf(err, "Error %d while activating snapshot on"
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001320 " '%s'\n", ret, bdrv_get_device_name(bs1));
1321 break;
1322 }
1323 /* fatal on snapshot block device */
1324 if (bs == bs1)
1325 goto the_end;
1326 }
1327 }
1328 }
1329
1330 if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001331 output_channel_printf(err, "Device %s does not support VM state snapshots\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001332 bdrv_get_device_name(bs));
1333 return;
1334 }
1335
1336 /* Don't even try to load empty VM states */
1337 ret = bdrv_snapshot_find(bs, &sn, name);
1338 if ((ret >= 0) && (sn.vm_state_size == 0))
1339 goto the_end;
1340
1341 /* restore the VM state */
1342 f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0);
1343 if (!f) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001344 output_channel_printf(err, "Could not open VM state file\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001345 goto the_end;
1346 }
1347 ret = qemu_loadvm_state(f);
1348 qemu_fclose(f);
1349 if (ret < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001350 output_channel_printf(err, "Error %d while loading VM state\n", ret);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001351 }
1352 the_end:
1353 if (saved_vm_running)
1354 vm_start();
1355}
1356
1357void do_delvm(Monitor *mon, const char *name)
1358{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001359 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1360 do_delvm_oc(oc, name);
1361 output_channel_free(oc);
1362}
1363void do_delvm_oc(OutputChannel *err, const char *name)
1364{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001365 BlockDriverState *bs, *bs1;
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001366 int ret;
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001367
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001368 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001369 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001370 output_channel_printf(err, "No block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001371 return;
1372 }
1373
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001374 bs1 = NULL;
1375 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001376 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001377 ret = bdrv_snapshot_delete(bs1, name);
1378 if (ret < 0) {
1379 if (ret == -ENOTSUP)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001380 output_channel_printf(err,
1381 "Snapshots not supported on device '%s'\n",
1382 bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001383 else
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001384 output_channel_printf(err, "Error %d while deleting snapshot on "
1385 "'%s'\n", ret, bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001386 }
1387 }
1388 }
1389}
1390
1391void do_info_snapshots(Monitor *mon)
1392{
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001393 OutputChannel *oc = output_channel_alloc(mon, monitor_output_channel_cb);
1394 do_info_snapshots_oc(oc, oc);
1395 output_channel_free(oc);
1396}
1397
1398void do_info_snapshots_oc(OutputChannel *out, OutputChannel *err)
1399{
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001400 BlockDriverState *bs, *bs1;
1401 QEMUSnapshotInfo *sn_tab, *sn;
1402 int nb_sns, i;
1403 char buf[256];
1404
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001405 bs = bdrv_snapshots();
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001406 if (!bs) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001407 output_channel_printf(err, "No available block device supports snapshots\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001408 return;
1409 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001410 output_channel_printf(out, "Snapshot devices:");
David 'Digit' Turnercb42a1b2010-12-23 02:54:08 +01001411 bs1 = NULL;
1412 while ((bs1 = bdrv_next(bs1))) {
Ot ten Thije8f2de6d2010-09-30 14:17:10 +01001413 if (bdrv_can_snapshot(bs1)) {
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001414 if (bs == bs1)
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001415 output_channel_printf(out, " %s", bdrv_get_device_name(bs1));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001416 }
1417 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001418 output_channel_printf(out, "\n");
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001419
1420 nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1421 if (nb_sns < 0) {
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001422 output_channel_printf(err, "bdrv_snapshot_list: error %d\n", nb_sns);
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001423 return;
1424 }
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001425 output_channel_printf(out, "Snapshot list (from %s):\n",
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001426 bdrv_get_device_name(bs));
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001427 output_channel_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001428 for(i = 0; i < nb_sns; i++) {
1429 sn = &sn_tab[i];
Ot ten Thije2ff39a32010-10-06 17:48:15 +01001430 output_channel_printf(out, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
David 'Digit' Turner5d8f37a2009-09-14 14:32:27 -07001431 }
1432 qemu_free(sn_tab);
1433}