Statistics
| Branch: | Revision:

root / savevm.c @ 0e286705

History | View | Annotate | Download (56.7 kB)

1 a672b469 aliguori
/*
2 a672b469 aliguori
 * QEMU System Emulator
3 a672b469 aliguori
 *
4 a672b469 aliguori
 * Copyright (c) 2003-2008 Fabrice Bellard
5 a672b469 aliguori
 *
6 a672b469 aliguori
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 a672b469 aliguori
 * of this software and associated documentation files (the "Software"), to deal
8 a672b469 aliguori
 * in the Software without restriction, including without limitation the rights
9 a672b469 aliguori
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 a672b469 aliguori
 * copies of the Software, and to permit persons to whom the Software is
11 a672b469 aliguori
 * furnished to do so, subject to the following conditions:
12 a672b469 aliguori
 *
13 a672b469 aliguori
 * The above copyright notice and this permission notice shall be included in
14 a672b469 aliguori
 * all copies or substantial portions of the Software.
15 a672b469 aliguori
 *
16 a672b469 aliguori
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 a672b469 aliguori
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 a672b469 aliguori
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 a672b469 aliguori
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 a672b469 aliguori
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 a672b469 aliguori
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 a672b469 aliguori
 * THE SOFTWARE.
23 a672b469 aliguori
 */
24 a672b469 aliguori
#include <unistd.h>
25 a672b469 aliguori
#include <fcntl.h>
26 a672b469 aliguori
#include <time.h>
27 a672b469 aliguori
#include <errno.h>
28 a672b469 aliguori
#include <sys/time.h>
29 a672b469 aliguori
#include <zlib.h>
30 a672b469 aliguori
31 71e72a19 Juan Quintela
/* Needed early for CONFIG_BSD etc. */
32 d40cdb10 blueswir1
#include "config-host.h"
33 d40cdb10 blueswir1
34 a672b469 aliguori
#ifndef _WIN32
35 a672b469 aliguori
#include <sys/times.h>
36 a672b469 aliguori
#include <sys/wait.h>
37 a672b469 aliguori
#include <termios.h>
38 a672b469 aliguori
#include <sys/mman.h>
39 a672b469 aliguori
#include <sys/ioctl.h>
40 a672b469 aliguori
#include <sys/resource.h>
41 a672b469 aliguori
#include <sys/socket.h>
42 a672b469 aliguori
#include <netinet/in.h>
43 a672b469 aliguori
#include <net/if.h>
44 a672b469 aliguori
#include <arpa/inet.h>
45 a672b469 aliguori
#include <dirent.h>
46 a672b469 aliguori
#include <netdb.h>
47 a672b469 aliguori
#include <sys/select.h>
48 71e72a19 Juan Quintela
#ifdef CONFIG_BSD
49 a672b469 aliguori
#include <sys/stat.h>
50 a167ba50 Aurelien Jarno
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
51 a672b469 aliguori
#include <libutil.h>
52 a672b469 aliguori
#else
53 a672b469 aliguori
#include <util.h>
54 a672b469 aliguori
#endif
55 a672b469 aliguori
#ifdef __linux__
56 a672b469 aliguori
#include <pty.h>
57 a672b469 aliguori
#include <malloc.h>
58 a672b469 aliguori
#include <linux/rtc.h>
59 a672b469 aliguori
#endif
60 a672b469 aliguori
#endif
61 a672b469 aliguori
#endif
62 a672b469 aliguori
63 a672b469 aliguori
#ifdef _WIN32
64 49dc768d aliguori
#include <windows.h>
65 a672b469 aliguori
#include <malloc.h>
66 a672b469 aliguori
#include <sys/timeb.h>
67 a672b469 aliguori
#include <mmsystem.h>
68 a672b469 aliguori
#define getopt_long_only getopt_long
69 a672b469 aliguori
#define memalign(align, size) malloc(size)
70 a672b469 aliguori
#endif
71 a672b469 aliguori
72 511d2b14 blueswir1
#include "qemu-common.h"
73 511d2b14 blueswir1
#include "hw/hw.h"
74 7685ee6a Alex Williamson
#include "hw/qdev.h"
75 511d2b14 blueswir1
#include "net.h"
76 511d2b14 blueswir1
#include "monitor.h"
77 511d2b14 blueswir1
#include "sysemu.h"
78 511d2b14 blueswir1
#include "qemu-timer.h"
79 511d2b14 blueswir1
#include "qemu-char.h"
80 511d2b14 blueswir1
#include "audio/audio.h"
81 511d2b14 blueswir1
#include "migration.h"
82 511d2b14 blueswir1
#include "qemu_socket.h"
83 72cf2d4f Blue Swirl
#include "qemu-queue.h"
84 2ff68d07 Paolo Bonzini
#include "qemu-timer.h"
85 17a4663e Blue Swirl
#include "cpus.h"
86 511d2b14 blueswir1
87 a672b469 aliguori
#define SELF_ANNOUNCE_ROUNDS 5
88 a672b469 aliguori
89 18995b98 Nolan
#ifndef ETH_P_RARP
90 f8778a77 Stefan Berger
#define ETH_P_RARP 0x8035
91 18995b98 Nolan
#endif
92 18995b98 Nolan
#define ARP_HTYPE_ETH 0x0001
93 18995b98 Nolan
#define ARP_PTYPE_IP 0x0800
94 18995b98 Nolan
#define ARP_OP_REQUEST_REV 0x3
95 18995b98 Nolan
96 18995b98 Nolan
static int announce_self_create(uint8_t *buf,
97 a672b469 aliguori
                                uint8_t *mac_addr)
98 a672b469 aliguori
{
99 18995b98 Nolan
    /* Ethernet header. */
100 18995b98 Nolan
    memset(buf, 0xff, 6);         /* destination MAC addr */
101 18995b98 Nolan
    memcpy(buf + 6, mac_addr, 6); /* source MAC addr */
102 18995b98 Nolan
    *(uint16_t *)(buf + 12) = htons(ETH_P_RARP); /* ethertype */
103 18995b98 Nolan
104 18995b98 Nolan
    /* RARP header. */
105 18995b98 Nolan
    *(uint16_t *)(buf + 14) = htons(ARP_HTYPE_ETH); /* hardware addr space */
106 18995b98 Nolan
    *(uint16_t *)(buf + 16) = htons(ARP_PTYPE_IP); /* protocol addr space */
107 18995b98 Nolan
    *(buf + 18) = 6; /* hardware addr length (ethernet) */
108 18995b98 Nolan
    *(buf + 19) = 4; /* protocol addr length (IPv4) */
109 18995b98 Nolan
    *(uint16_t *)(buf + 20) = htons(ARP_OP_REQUEST_REV); /* opcode */
110 18995b98 Nolan
    memcpy(buf + 22, mac_addr, 6); /* source hw addr */
111 18995b98 Nolan
    memset(buf + 28, 0x00, 4);     /* source protocol addr */
112 18995b98 Nolan
    memcpy(buf + 32, mac_addr, 6); /* target hw addr */
113 18995b98 Nolan
    memset(buf + 38, 0x00, 4);     /* target protocol addr */
114 18995b98 Nolan
115 18995b98 Nolan
    /* Padding to get up to 60 bytes (ethernet min packet size, minus FCS). */
116 18995b98 Nolan
    memset(buf + 42, 0x00, 18);
117 18995b98 Nolan
118 18995b98 Nolan
    return 60; /* len (FCS will be added by hardware) */
119 a672b469 aliguori
}
120 a672b469 aliguori
121 f401ca22 Mark McLoughlin
static void qemu_announce_self_iter(NICState *nic, void *opaque)
122 a672b469 aliguori
{
123 18995b98 Nolan
    uint8_t buf[60];
124 f401ca22 Mark McLoughlin
    int len;
125 f401ca22 Mark McLoughlin
126 f401ca22 Mark McLoughlin
    len = announce_self_create(buf, nic->conf->macaddr.a);
127 f401ca22 Mark McLoughlin
128 f401ca22 Mark McLoughlin
    qemu_send_packet_raw(&nic->nc, buf, len);
129 f401ca22 Mark McLoughlin
}
130 f401ca22 Mark McLoughlin
131 f401ca22 Mark McLoughlin
132 f401ca22 Mark McLoughlin
static void qemu_announce_self_once(void *opaque)
133 f401ca22 Mark McLoughlin
{
134 ed8b330b Gleb Natapov
    static int count = SELF_ANNOUNCE_ROUNDS;
135 ed8b330b Gleb Natapov
    QEMUTimer *timer = *(QEMUTimer **)opaque;
136 a672b469 aliguori
137 f401ca22 Mark McLoughlin
    qemu_foreach_nic(qemu_announce_self_iter, NULL);
138 f401ca22 Mark McLoughlin
139 18995b98 Nolan
    if (--count) {
140 18995b98 Nolan
        /* delay 50ms, 150ms, 250ms, ... */
141 7bd427d8 Paolo Bonzini
        qemu_mod_timer(timer, qemu_get_clock_ms(rt_clock) +
142 18995b98 Nolan
                       50 + (SELF_ANNOUNCE_ROUNDS - count - 1) * 100);
143 ed8b330b Gleb Natapov
    } else {
144 ed8b330b Gleb Natapov
            qemu_del_timer(timer);
145 ed8b330b Gleb Natapov
            qemu_free_timer(timer);
146 ed8b330b Gleb Natapov
    }
147 ed8b330b Gleb Natapov
}
148 ed8b330b Gleb Natapov
149 ed8b330b Gleb Natapov
void qemu_announce_self(void)
150 ed8b330b Gleb Natapov
{
151 ed8b330b Gleb Natapov
        static QEMUTimer *timer;
152 7bd427d8 Paolo Bonzini
        timer = qemu_new_timer_ms(rt_clock, qemu_announce_self_once, &timer);
153 ed8b330b Gleb Natapov
        qemu_announce_self_once(&timer);
154 a672b469 aliguori
}
155 a672b469 aliguori
156 a672b469 aliguori
/***********************************************************/
157 a672b469 aliguori
/* savevm/loadvm support */
158 a672b469 aliguori
159 a672b469 aliguori
#define IO_BUF_SIZE 32768
160 a672b469 aliguori
161 a672b469 aliguori
struct QEMUFile {
162 a672b469 aliguori
    QEMUFilePutBufferFunc *put_buffer;
163 a672b469 aliguori
    QEMUFileGetBufferFunc *get_buffer;
164 a672b469 aliguori
    QEMUFileCloseFunc *close;
165 a672b469 aliguori
    QEMUFileRateLimit *rate_limit;
166 19629537 Glauber Costa
    QEMUFileSetRateLimit *set_rate_limit;
167 c163b5ca lirans@il.ibm.com
    QEMUFileGetRateLimit *get_rate_limit;
168 a672b469 aliguori
    void *opaque;
169 a672b469 aliguori
    int is_write;
170 a672b469 aliguori
171 a672b469 aliguori
    int64_t buf_offset; /* start of buffer when writing, end of buffer
172 a672b469 aliguori
                           when reading */
173 a672b469 aliguori
    int buf_index;
174 a672b469 aliguori
    int buf_size; /* 0 when writing */
175 a672b469 aliguori
    uint8_t buf[IO_BUF_SIZE];
176 a672b469 aliguori
177 3961b4dd Juan Quintela
    int last_error;
178 a672b469 aliguori
};
179 a672b469 aliguori
180 7f79dd28 Paolo Bonzini
typedef struct QEMUFileStdio
181 a672b469 aliguori
{
182 7f79dd28 Paolo Bonzini
    FILE *stdio_file;
183 a672b469 aliguori
    QEMUFile *file;
184 7f79dd28 Paolo Bonzini
} QEMUFileStdio;
185 a672b469 aliguori
186 a672b469 aliguori
typedef struct QEMUFileSocket
187 a672b469 aliguori
{
188 a672b469 aliguori
    int fd;
189 a672b469 aliguori
    QEMUFile *file;
190 a672b469 aliguori
} QEMUFileSocket;
191 a672b469 aliguori
192 a672b469 aliguori
static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
193 a672b469 aliguori
{
194 a672b469 aliguori
    QEMUFileSocket *s = opaque;
195 a672b469 aliguori
    ssize_t len;
196 a672b469 aliguori
197 a672b469 aliguori
    do {
198 00aa0040 Blue Swirl
        len = qemu_recv(s->fd, buf, size, 0);
199 a672b469 aliguori
    } while (len == -1 && socket_error() == EINTR);
200 a672b469 aliguori
201 a672b469 aliguori
    if (len == -1)
202 a672b469 aliguori
        len = -socket_error();
203 a672b469 aliguori
204 a672b469 aliguori
    return len;
205 a672b469 aliguori
}
206 a672b469 aliguori
207 a672b469 aliguori
static int socket_close(void *opaque)
208 a672b469 aliguori
{
209 a672b469 aliguori
    QEMUFileSocket *s = opaque;
210 7267c094 Anthony Liguori
    g_free(s);
211 a672b469 aliguori
    return 0;
212 a672b469 aliguori
}
213 a672b469 aliguori
214 7f79dd28 Paolo Bonzini
static int stdio_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
215 a672b469 aliguori
{
216 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
217 7f79dd28 Paolo Bonzini
    return fwrite(buf, 1, size, s->stdio_file);
218 a672b469 aliguori
}
219 a672b469 aliguori
220 7f79dd28 Paolo Bonzini
static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
221 a672b469 aliguori
{
222 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
223 7f79dd28 Paolo Bonzini
    FILE *fp = s->stdio_file;
224 8a67ec4d Uri Lublin
    int bytes;
225 8a67ec4d Uri Lublin
226 8a67ec4d Uri Lublin
    do {
227 8a67ec4d Uri Lublin
        clearerr(fp);
228 8a67ec4d Uri Lublin
        bytes = fread(buf, 1, size, fp);
229 8a67ec4d Uri Lublin
    } while ((bytes == 0) && ferror(fp) && (errno == EINTR));
230 8a67ec4d Uri Lublin
    return bytes;
231 a672b469 aliguori
}
232 a672b469 aliguori
233 7f79dd28 Paolo Bonzini
static int stdio_pclose(void *opaque)
234 7f79dd28 Paolo Bonzini
{
235 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
236 41ef56e6 Anthony Liguori
    int ret;
237 41ef56e6 Anthony Liguori
    ret = pclose(s->stdio_file);
238 26f1af0a Eduardo Habkost
    if (ret == -1) {
239 26f1af0a Eduardo Habkost
        ret = -errno;
240 26f1af0a Eduardo Habkost
    }
241 7267c094 Anthony Liguori
    g_free(s);
242 41ef56e6 Anthony Liguori
    return ret;
243 7f79dd28 Paolo Bonzini
}
244 7f79dd28 Paolo Bonzini
245 7f79dd28 Paolo Bonzini
static int stdio_fclose(void *opaque)
246 a672b469 aliguori
{
247 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s = opaque;
248 0e286705 Eduardo Habkost
    int ret = 0;
249 0e286705 Eduardo Habkost
    if (fclose(s->stdio_file) == EOF) {
250 0e286705 Eduardo Habkost
        ret = -errno;
251 0e286705 Eduardo Habkost
    }
252 7267c094 Anthony Liguori
    g_free(s);
253 0e286705 Eduardo Habkost
    return ret;
254 a672b469 aliguori
}
255 a672b469 aliguori
256 7f79dd28 Paolo Bonzini
QEMUFile *qemu_popen(FILE *stdio_file, const char *mode)
257 a672b469 aliguori
{
258 7f79dd28 Paolo Bonzini
    QEMUFileStdio *s;
259 a672b469 aliguori
260 7f79dd28 Paolo Bonzini
    if (stdio_file == NULL || mode == NULL || (mode[0] != 'r' && mode[0] != 'w') || mode[1] != 0) {
261 a672b469 aliguori
        fprintf(stderr, "qemu_popen: Argument validity check failed\n");
262 a672b469 aliguori
        return NULL;
263 a672b469 aliguori
    }
264 a672b469 aliguori
265 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
266 a672b469 aliguori
267 7f79dd28 Paolo Bonzini
    s->stdio_file = stdio_file;
268 a672b469 aliguori
269 a672b469 aliguori
    if(mode[0] == 'r') {
270 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_pclose, 
271 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
272 a672b469 aliguori
    } else {
273 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_pclose, 
274 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
275 a672b469 aliguori
    }
276 a672b469 aliguori
    return s->file;
277 a672b469 aliguori
}
278 a672b469 aliguori
279 a672b469 aliguori
QEMUFile *qemu_popen_cmd(const char *command, const char *mode)
280 a672b469 aliguori
{
281 a672b469 aliguori
    FILE *popen_file;
282 a672b469 aliguori
283 a672b469 aliguori
    popen_file = popen(command, mode);
284 a672b469 aliguori
    if(popen_file == NULL) {
285 a672b469 aliguori
        return NULL;
286 a672b469 aliguori
    }
287 a672b469 aliguori
288 a672b469 aliguori
    return qemu_popen(popen_file, mode);
289 a672b469 aliguori
}
290 a672b469 aliguori
291 7f79dd28 Paolo Bonzini
int qemu_stdio_fd(QEMUFile *f)
292 8a43b1ea Chris Lalancette
{
293 7f79dd28 Paolo Bonzini
    QEMUFileStdio *p;
294 8a43b1ea Chris Lalancette
    int fd;
295 8a43b1ea Chris Lalancette
296 7f79dd28 Paolo Bonzini
    p = (QEMUFileStdio *)f->opaque;
297 7f79dd28 Paolo Bonzini
    fd = fileno(p->stdio_file);
298 8a43b1ea Chris Lalancette
299 8a43b1ea Chris Lalancette
    return fd;
300 8a43b1ea Chris Lalancette
}
301 8a43b1ea Chris Lalancette
302 5ac1fad3 Paolo Bonzini
QEMUFile *qemu_fdopen(int fd, const char *mode)
303 5ac1fad3 Paolo Bonzini
{
304 5ac1fad3 Paolo Bonzini
    QEMUFileStdio *s;
305 5ac1fad3 Paolo Bonzini
306 5ac1fad3 Paolo Bonzini
    if (mode == NULL ||
307 5ac1fad3 Paolo Bonzini
        (mode[0] != 'r' && mode[0] != 'w') ||
308 5ac1fad3 Paolo Bonzini
        mode[1] != 'b' || mode[2] != 0) {
309 5ac1fad3 Paolo Bonzini
        fprintf(stderr, "qemu_fdopen: Argument validity check failed\n");
310 5ac1fad3 Paolo Bonzini
        return NULL;
311 5ac1fad3 Paolo Bonzini
    }
312 5ac1fad3 Paolo Bonzini
313 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
314 5ac1fad3 Paolo Bonzini
    s->stdio_file = fdopen(fd, mode);
315 5ac1fad3 Paolo Bonzini
    if (!s->stdio_file)
316 5ac1fad3 Paolo Bonzini
        goto fail;
317 5ac1fad3 Paolo Bonzini
318 5ac1fad3 Paolo Bonzini
    if(mode[0] == 'r') {
319 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, stdio_get_buffer, stdio_fclose, 
320 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
321 5ac1fad3 Paolo Bonzini
    } else {
322 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, stdio_put_buffer, NULL, stdio_fclose, 
323 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
324 5ac1fad3 Paolo Bonzini
    }
325 5ac1fad3 Paolo Bonzini
    return s->file;
326 5ac1fad3 Paolo Bonzini
327 5ac1fad3 Paolo Bonzini
fail:
328 7267c094 Anthony Liguori
    g_free(s);
329 5ac1fad3 Paolo Bonzini
    return NULL;
330 5ac1fad3 Paolo Bonzini
}
331 5ac1fad3 Paolo Bonzini
332 a672b469 aliguori
QEMUFile *qemu_fopen_socket(int fd)
333 a672b469 aliguori
{
334 7267c094 Anthony Liguori
    QEMUFileSocket *s = g_malloc0(sizeof(QEMUFileSocket));
335 a672b469 aliguori
336 a672b469 aliguori
    s->fd = fd;
337 c163b5ca lirans@il.ibm.com
    s->file = qemu_fopen_ops(s, NULL, socket_get_buffer, socket_close, 
338 c163b5ca lirans@il.ibm.com
                             NULL, NULL, NULL);
339 a672b469 aliguori
    return s->file;
340 a672b469 aliguori
}
341 a672b469 aliguori
342 a672b469 aliguori
static int file_put_buffer(void *opaque, const uint8_t *buf,
343 a672b469 aliguori
                            int64_t pos, int size)
344 a672b469 aliguori
{
345 a672b469 aliguori
    QEMUFileStdio *s = opaque;
346 7f79dd28 Paolo Bonzini
    fseek(s->stdio_file, pos, SEEK_SET);
347 5fdb3aa1 Kirill A. Shutemov
    return fwrite(buf, 1, size, s->stdio_file);
348 a672b469 aliguori
}
349 a672b469 aliguori
350 a672b469 aliguori
static int file_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
351 a672b469 aliguori
{
352 a672b469 aliguori
    QEMUFileStdio *s = opaque;
353 7f79dd28 Paolo Bonzini
    fseek(s->stdio_file, pos, SEEK_SET);
354 7f79dd28 Paolo Bonzini
    return fread(buf, 1, size, s->stdio_file);
355 a672b469 aliguori
}
356 a672b469 aliguori
357 a672b469 aliguori
QEMUFile *qemu_fopen(const char *filename, const char *mode)
358 a672b469 aliguori
{
359 a672b469 aliguori
    QEMUFileStdio *s;
360 a672b469 aliguori
361 7f79dd28 Paolo Bonzini
    if (mode == NULL ||
362 7f79dd28 Paolo Bonzini
        (mode[0] != 'r' && mode[0] != 'w') ||
363 7f79dd28 Paolo Bonzini
        mode[1] != 'b' || mode[2] != 0) {
364 090414a3 Blue Swirl
        fprintf(stderr, "qemu_fopen: Argument validity check failed\n");
365 7f79dd28 Paolo Bonzini
        return NULL;
366 7f79dd28 Paolo Bonzini
    }
367 7f79dd28 Paolo Bonzini
368 7267c094 Anthony Liguori
    s = g_malloc0(sizeof(QEMUFileStdio));
369 a672b469 aliguori
370 7f79dd28 Paolo Bonzini
    s->stdio_file = fopen(filename, mode);
371 7f79dd28 Paolo Bonzini
    if (!s->stdio_file)
372 a672b469 aliguori
        goto fail;
373 c163b5ca lirans@il.ibm.com
    
374 7f79dd28 Paolo Bonzini
    if(mode[0] == 'w') {
375 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, file_put_buffer, NULL, stdio_fclose, 
376 c163b5ca lirans@il.ibm.com
                                 NULL, NULL, NULL);
377 7f79dd28 Paolo Bonzini
    } else {
378 c163b5ca lirans@il.ibm.com
        s->file = qemu_fopen_ops(s, NULL, file_get_buffer, stdio_fclose, 
379 c163b5ca lirans@il.ibm.com
                               NULL, NULL, NULL);
380 7f79dd28 Paolo Bonzini
    }
381 7f79dd28 Paolo Bonzini
    return s->file;
382 a672b469 aliguori
fail:
383 7267c094 Anthony Liguori
    g_free(s);
384 a672b469 aliguori
    return NULL;
385 a672b469 aliguori
}
386 a672b469 aliguori
387 178e08a5 aliguori
static int block_put_buffer(void *opaque, const uint8_t *buf,
388 a672b469 aliguori
                           int64_t pos, int size)
389 a672b469 aliguori
{
390 45566e9c Christoph Hellwig
    bdrv_save_vmstate(opaque, buf, pos, size);
391 a672b469 aliguori
    return size;
392 a672b469 aliguori
}
393 a672b469 aliguori
394 178e08a5 aliguori
static int block_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
395 a672b469 aliguori
{
396 45566e9c Christoph Hellwig
    return bdrv_load_vmstate(opaque, buf, pos, size);
397 a672b469 aliguori
}
398 a672b469 aliguori
399 a672b469 aliguori
static int bdrv_fclose(void *opaque)
400 a672b469 aliguori
{
401 a672b469 aliguori
    return 0;
402 a672b469 aliguori
}
403 a672b469 aliguori
404 45566e9c Christoph Hellwig
static QEMUFile *qemu_fopen_bdrv(BlockDriverState *bs, int is_writable)
405 a672b469 aliguori
{
406 a672b469 aliguori
    if (is_writable)
407 c163b5ca lirans@il.ibm.com
        return qemu_fopen_ops(bs, block_put_buffer, NULL, bdrv_fclose, 
408 c163b5ca lirans@il.ibm.com
                              NULL, NULL, NULL);
409 c163b5ca lirans@il.ibm.com
    return qemu_fopen_ops(bs, NULL, block_get_buffer, bdrv_fclose, NULL, NULL, NULL);
410 a672b469 aliguori
}
411 a672b469 aliguori
412 a672b469 aliguori
QEMUFile *qemu_fopen_ops(void *opaque, QEMUFilePutBufferFunc *put_buffer,
413 a672b469 aliguori
                         QEMUFileGetBufferFunc *get_buffer,
414 a672b469 aliguori
                         QEMUFileCloseFunc *close,
415 19629537 Glauber Costa
                         QEMUFileRateLimit *rate_limit,
416 c163b5ca lirans@il.ibm.com
                         QEMUFileSetRateLimit *set_rate_limit,
417 c163b5ca lirans@il.ibm.com
                         QEMUFileGetRateLimit *get_rate_limit)
418 a672b469 aliguori
{
419 a672b469 aliguori
    QEMUFile *f;
420 a672b469 aliguori
421 7267c094 Anthony Liguori
    f = g_malloc0(sizeof(QEMUFile));
422 a672b469 aliguori
423 a672b469 aliguori
    f->opaque = opaque;
424 a672b469 aliguori
    f->put_buffer = put_buffer;
425 a672b469 aliguori
    f->get_buffer = get_buffer;
426 a672b469 aliguori
    f->close = close;
427 a672b469 aliguori
    f->rate_limit = rate_limit;
428 19629537 Glauber Costa
    f->set_rate_limit = set_rate_limit;
429 c163b5ca lirans@il.ibm.com
    f->get_rate_limit = get_rate_limit;
430 a672b469 aliguori
    f->is_write = 0;
431 a672b469 aliguori
432 a672b469 aliguori
    return f;
433 a672b469 aliguori
}
434 a672b469 aliguori
435 624b9cc2 Juan Quintela
int qemu_file_get_error(QEMUFile *f)
436 a672b469 aliguori
{
437 3961b4dd Juan Quintela
    return f->last_error;
438 a672b469 aliguori
}
439 a672b469 aliguori
440 dcd1d224 Juan Quintela
void qemu_file_set_error(QEMUFile *f, int ret)
441 4dabe248 aliguori
{
442 3961b4dd Juan Quintela
    f->last_error = ret;
443 4dabe248 aliguori
}
444 4dabe248 aliguori
445 d82ca915 Eduardo Habkost
/** Sets last_error conditionally
446 d82ca915 Eduardo Habkost
 *
447 d82ca915 Eduardo Habkost
 * Sets last_error only if ret is negative _and_ no error
448 d82ca915 Eduardo Habkost
 * was set before.
449 d82ca915 Eduardo Habkost
 */
450 d82ca915 Eduardo Habkost
static void qemu_file_set_if_error(QEMUFile *f, int ret)
451 d82ca915 Eduardo Habkost
{
452 d82ca915 Eduardo Habkost
    if (ret < 0 && !f->last_error) {
453 d82ca915 Eduardo Habkost
        qemu_file_set_error(f, ret);
454 d82ca915 Eduardo Habkost
    }
455 d82ca915 Eduardo Habkost
}
456 d82ca915 Eduardo Habkost
457 d82ca915 Eduardo Habkost
/** Flushes QEMUFile buffer
458 d82ca915 Eduardo Habkost
 *
459 d82ca915 Eduardo Habkost
 * In case of error, last_error is set.
460 d82ca915 Eduardo Habkost
 */
461 a672b469 aliguori
void qemu_fflush(QEMUFile *f)
462 a672b469 aliguori
{
463 a672b469 aliguori
    if (!f->put_buffer)
464 a672b469 aliguori
        return;
465 a672b469 aliguori
466 a672b469 aliguori
    if (f->is_write && f->buf_index > 0) {
467 a672b469 aliguori
        int len;
468 a672b469 aliguori
469 a672b469 aliguori
        len = f->put_buffer(f->opaque, f->buf, f->buf_offset, f->buf_index);
470 a672b469 aliguori
        if (len > 0)
471 a672b469 aliguori
            f->buf_offset += f->buf_index;
472 a672b469 aliguori
        else
473 c29110d5 Eduardo Habkost
            qemu_file_set_error(f, -EINVAL);
474 a672b469 aliguori
        f->buf_index = 0;
475 a672b469 aliguori
    }
476 a672b469 aliguori
}
477 a672b469 aliguori
478 a672b469 aliguori
static void qemu_fill_buffer(QEMUFile *f)
479 a672b469 aliguori
{
480 a672b469 aliguori
    int len;
481 0046c45b Juan Quintela
    int pending;
482 a672b469 aliguori
483 a672b469 aliguori
    if (!f->get_buffer)
484 a672b469 aliguori
        return;
485 a672b469 aliguori
486 a672b469 aliguori
    if (f->is_write)
487 a672b469 aliguori
        abort();
488 a672b469 aliguori
489 0046c45b Juan Quintela
    pending = f->buf_size - f->buf_index;
490 0046c45b Juan Quintela
    if (pending > 0) {
491 0046c45b Juan Quintela
        memmove(f->buf, f->buf + f->buf_index, pending);
492 0046c45b Juan Quintela
    }
493 0046c45b Juan Quintela
    f->buf_index = 0;
494 0046c45b Juan Quintela
    f->buf_size = pending;
495 0046c45b Juan Quintela
496 0046c45b Juan Quintela
    len = f->get_buffer(f->opaque, f->buf + pending, f->buf_offset,
497 0046c45b Juan Quintela
                        IO_BUF_SIZE - pending);
498 a672b469 aliguori
    if (len > 0) {
499 0046c45b Juan Quintela
        f->buf_size += len;
500 a672b469 aliguori
        f->buf_offset += len;
501 fa39a30f Juan Quintela
    } else if (len == 0) {
502 fa39a30f Juan Quintela
        f->last_error = -EIO;
503 a672b469 aliguori
    } else if (len != -EAGAIN)
504 c29110d5 Eduardo Habkost
        qemu_file_set_error(f, len);
505 a672b469 aliguori
}
506 a672b469 aliguori
507 d82ca915 Eduardo Habkost
/** Calls close function and set last_error if needed
508 d82ca915 Eduardo Habkost
 *
509 d82ca915 Eduardo Habkost
 * Internal function. qemu_fflush() must be called before this.
510 d82ca915 Eduardo Habkost
 *
511 d82ca915 Eduardo Habkost
 * Returns f->close() return value, or 0 if close function is not set.
512 d82ca915 Eduardo Habkost
 */
513 d82ca915 Eduardo Habkost
static int qemu_close(QEMUFile *f)
514 a672b469 aliguori
{
515 a672b469 aliguori
    int ret = 0;
516 d82ca915 Eduardo Habkost
    if (f->close) {
517 a672b469 aliguori
        ret = f->close(f->opaque);
518 d82ca915 Eduardo Habkost
        qemu_file_set_if_error(f, ret);
519 d82ca915 Eduardo Habkost
    }
520 d82ca915 Eduardo Habkost
    return ret;
521 d82ca915 Eduardo Habkost
}
522 d82ca915 Eduardo Habkost
523 d82ca915 Eduardo Habkost
/** Closes the file
524 d82ca915 Eduardo Habkost
 *
525 d82ca915 Eduardo Habkost
 * Returns negative error value if any error happened on previous operations or
526 d82ca915 Eduardo Habkost
 * while closing the file. Returns 0 or positive number on success.
527 d82ca915 Eduardo Habkost
 *
528 d82ca915 Eduardo Habkost
 * The meaning of return value on success depends on the specific backend
529 d82ca915 Eduardo Habkost
 * being used.
530 d82ca915 Eduardo Habkost
 */
531 d82ca915 Eduardo Habkost
int qemu_fclose(QEMUFile *f)
532 d82ca915 Eduardo Habkost
{
533 d82ca915 Eduardo Habkost
    int ret;
534 d82ca915 Eduardo Habkost
    qemu_fflush(f);
535 d82ca915 Eduardo Habkost
    ret = qemu_close(f);
536 d82ca915 Eduardo Habkost
    /* If any error was spotted before closing, we should report it
537 d82ca915 Eduardo Habkost
     * instead of the close() return value.
538 d82ca915 Eduardo Habkost
     */
539 d82ca915 Eduardo Habkost
    if (f->last_error) {
540 d82ca915 Eduardo Habkost
        ret = f->last_error;
541 d82ca915 Eduardo Habkost
    }
542 7267c094 Anthony Liguori
    g_free(f);
543 a672b469 aliguori
    return ret;
544 a672b469 aliguori
}
545 a672b469 aliguori
546 a672b469 aliguori
void qemu_file_put_notify(QEMUFile *f)
547 a672b469 aliguori
{
548 a672b469 aliguori
    f->put_buffer(f->opaque, NULL, 0, 0);
549 a672b469 aliguori
}
550 a672b469 aliguori
551 a672b469 aliguori
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
552 a672b469 aliguori
{
553 a672b469 aliguori
    int l;
554 a672b469 aliguori
555 3961b4dd Juan Quintela
    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
556 a672b469 aliguori
        fprintf(stderr,
557 a672b469 aliguori
                "Attempted to write to buffer while read buffer is not empty\n");
558 a672b469 aliguori
        abort();
559 a672b469 aliguori
    }
560 a672b469 aliguori
561 3961b4dd Juan Quintela
    while (!f->last_error && size > 0) {
562 a672b469 aliguori
        l = IO_BUF_SIZE - f->buf_index;
563 a672b469 aliguori
        if (l > size)
564 a672b469 aliguori
            l = size;
565 a672b469 aliguori
        memcpy(f->buf + f->buf_index, buf, l);
566 a672b469 aliguori
        f->is_write = 1;
567 a672b469 aliguori
        f->buf_index += l;
568 a672b469 aliguori
        buf += l;
569 a672b469 aliguori
        size -= l;
570 a672b469 aliguori
        if (f->buf_index >= IO_BUF_SIZE)
571 a672b469 aliguori
            qemu_fflush(f);
572 a672b469 aliguori
    }
573 a672b469 aliguori
}
574 a672b469 aliguori
575 a672b469 aliguori
void qemu_put_byte(QEMUFile *f, int v)
576 a672b469 aliguori
{
577 3961b4dd Juan Quintela
    if (!f->last_error && f->is_write == 0 && f->buf_index > 0) {
578 a672b469 aliguori
        fprintf(stderr,
579 a672b469 aliguori
                "Attempted to write to buffer while read buffer is not empty\n");
580 a672b469 aliguori
        abort();
581 a672b469 aliguori
    }
582 a672b469 aliguori
583 a672b469 aliguori
    f->buf[f->buf_index++] = v;
584 a672b469 aliguori
    f->is_write = 1;
585 a672b469 aliguori
    if (f->buf_index >= IO_BUF_SIZE)
586 a672b469 aliguori
        qemu_fflush(f);
587 a672b469 aliguori
}
588 a672b469 aliguori
589 c6380724 Juan Quintela
static void qemu_file_skip(QEMUFile *f, int size)
590 a672b469 aliguori
{
591 c6380724 Juan Quintela
    if (f->buf_index + size <= f->buf_size) {
592 c6380724 Juan Quintela
        f->buf_index += size;
593 c6380724 Juan Quintela
    }
594 c6380724 Juan Quintela
}
595 c6380724 Juan Quintela
596 c6380724 Juan Quintela
static int qemu_peek_buffer(QEMUFile *f, uint8_t *buf, int size, size_t offset)
597 a672b469 aliguori
{
598 c6380724 Juan Quintela
    int pending;
599 c6380724 Juan Quintela
    int index;
600 a672b469 aliguori
601 b9ce1454 Juan Quintela
    if (f->is_write) {
602 a672b469 aliguori
        abort();
603 b9ce1454 Juan Quintela
    }
604 a672b469 aliguori
605 c6380724 Juan Quintela
    index = f->buf_index + offset;
606 c6380724 Juan Quintela
    pending = f->buf_size - index;
607 c6380724 Juan Quintela
    if (pending < size) {
608 c6380724 Juan Quintela
        qemu_fill_buffer(f);
609 c6380724 Juan Quintela
        index = f->buf_index + offset;
610 c6380724 Juan Quintela
        pending = f->buf_size - index;
611 c6380724 Juan Quintela
    }
612 c6380724 Juan Quintela
613 c6380724 Juan Quintela
    if (pending <= 0) {
614 c6380724 Juan Quintela
        return 0;
615 c6380724 Juan Quintela
    }
616 c6380724 Juan Quintela
    if (size > pending) {
617 c6380724 Juan Quintela
        size = pending;
618 c6380724 Juan Quintela
    }
619 c6380724 Juan Quintela
620 c6380724 Juan Quintela
    memcpy(buf, f->buf + index, size);
621 c6380724 Juan Quintela
    return size;
622 c6380724 Juan Quintela
}
623 c6380724 Juan Quintela
624 c6380724 Juan Quintela
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
625 c6380724 Juan Quintela
{
626 c6380724 Juan Quintela
    int pending = size;
627 c6380724 Juan Quintela
    int done = 0;
628 c6380724 Juan Quintela
629 c6380724 Juan Quintela
    while (pending > 0) {
630 c6380724 Juan Quintela
        int res;
631 c6380724 Juan Quintela
632 c6380724 Juan Quintela
        res = qemu_peek_buffer(f, buf, pending, 0);
633 c6380724 Juan Quintela
        if (res == 0) {
634 c6380724 Juan Quintela
            return done;
635 a672b469 aliguori
        }
636 c6380724 Juan Quintela
        qemu_file_skip(f, res);
637 c6380724 Juan Quintela
        buf += res;
638 c6380724 Juan Quintela
        pending -= res;
639 c6380724 Juan Quintela
        done += res;
640 a672b469 aliguori
    }
641 c6380724 Juan Quintela
    return done;
642 a672b469 aliguori
}
643 a672b469 aliguori
644 c6380724 Juan Quintela
static int qemu_peek_byte(QEMUFile *f, int offset)
645 811814bd Juan Quintela
{
646 c6380724 Juan Quintela
    int index = f->buf_index + offset;
647 c6380724 Juan Quintela
648 b9ce1454 Juan Quintela
    if (f->is_write) {
649 811814bd Juan Quintela
        abort();
650 b9ce1454 Juan Quintela
    }
651 811814bd Juan Quintela
652 c6380724 Juan Quintela
    if (index >= f->buf_size) {
653 811814bd Juan Quintela
        qemu_fill_buffer(f);
654 c6380724 Juan Quintela
        index = f->buf_index + offset;
655 c6380724 Juan Quintela
        if (index >= f->buf_size) {
656 811814bd Juan Quintela
            return 0;
657 b9ce1454 Juan Quintela
        }
658 811814bd Juan Quintela
    }
659 c6380724 Juan Quintela
    return f->buf[index];
660 811814bd Juan Quintela
}
661 811814bd Juan Quintela
662 a672b469 aliguori
int qemu_get_byte(QEMUFile *f)
663 a672b469 aliguori
{
664 65f3bb3d Juan Quintela
    int result;
665 a672b469 aliguori
666 c6380724 Juan Quintela
    result = qemu_peek_byte(f, 0);
667 c6380724 Juan Quintela
    qemu_file_skip(f, 1);
668 65f3bb3d Juan Quintela
    return result;
669 a672b469 aliguori
}
670 a672b469 aliguori
671 a672b469 aliguori
int64_t qemu_ftell(QEMUFile *f)
672 a672b469 aliguori
{
673 a672b469 aliguori
    return f->buf_offset - f->buf_size + f->buf_index;
674 a672b469 aliguori
}
675 a672b469 aliguori
676 a672b469 aliguori
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
677 a672b469 aliguori
{
678 a672b469 aliguori
    if (whence == SEEK_SET) {
679 a672b469 aliguori
        /* nothing to do */
680 a672b469 aliguori
    } else if (whence == SEEK_CUR) {
681 a672b469 aliguori
        pos += qemu_ftell(f);
682 a672b469 aliguori
    } else {
683 a672b469 aliguori
        /* SEEK_END not supported */
684 a672b469 aliguori
        return -1;
685 a672b469 aliguori
    }
686 a672b469 aliguori
    if (f->put_buffer) {
687 a672b469 aliguori
        qemu_fflush(f);
688 a672b469 aliguori
        f->buf_offset = pos;
689 a672b469 aliguori
    } else {
690 a672b469 aliguori
        f->buf_offset = pos;
691 a672b469 aliguori
        f->buf_index = 0;
692 a672b469 aliguori
        f->buf_size = 0;
693 a672b469 aliguori
    }
694 a672b469 aliguori
    return pos;
695 a672b469 aliguori
}
696 a672b469 aliguori
697 a672b469 aliguori
int qemu_file_rate_limit(QEMUFile *f)
698 a672b469 aliguori
{
699 a672b469 aliguori
    if (f->rate_limit)
700 a672b469 aliguori
        return f->rate_limit(f->opaque);
701 a672b469 aliguori
702 a672b469 aliguori
    return 0;
703 a672b469 aliguori
}
704 a672b469 aliguori
705 3d002df3 Michael S. Tsirkin
int64_t qemu_file_get_rate_limit(QEMUFile *f)
706 c163b5ca lirans@il.ibm.com
{
707 c163b5ca lirans@il.ibm.com
    if (f->get_rate_limit)
708 c163b5ca lirans@il.ibm.com
        return f->get_rate_limit(f->opaque);
709 c163b5ca lirans@il.ibm.com
710 c163b5ca lirans@il.ibm.com
    return 0;
711 c163b5ca lirans@il.ibm.com
}
712 c163b5ca lirans@il.ibm.com
713 3d002df3 Michael S. Tsirkin
int64_t qemu_file_set_rate_limit(QEMUFile *f, int64_t new_rate)
714 19629537 Glauber Costa
{
715 0bb05eaf Glauber Costa
    /* any failed or completed migration keeps its state to allow probing of
716 0bb05eaf Glauber Costa
     * migration data, but has no associated file anymore */
717 0bb05eaf Glauber Costa
    if (f && f->set_rate_limit)
718 19629537 Glauber Costa
        return f->set_rate_limit(f->opaque, new_rate);
719 19629537 Glauber Costa
720 19629537 Glauber Costa
    return 0;
721 19629537 Glauber Costa
}
722 19629537 Glauber Costa
723 a672b469 aliguori
void qemu_put_be16(QEMUFile *f, unsigned int v)
724 a672b469 aliguori
{
725 a672b469 aliguori
    qemu_put_byte(f, v >> 8);
726 a672b469 aliguori
    qemu_put_byte(f, v);
727 a672b469 aliguori
}
728 a672b469 aliguori
729 a672b469 aliguori
void qemu_put_be32(QEMUFile *f, unsigned int v)
730 a672b469 aliguori
{
731 a672b469 aliguori
    qemu_put_byte(f, v >> 24);
732 a672b469 aliguori
    qemu_put_byte(f, v >> 16);
733 a672b469 aliguori
    qemu_put_byte(f, v >> 8);
734 a672b469 aliguori
    qemu_put_byte(f, v);
735 a672b469 aliguori
}
736 a672b469 aliguori
737 a672b469 aliguori
void qemu_put_be64(QEMUFile *f, uint64_t v)
738 a672b469 aliguori
{
739 a672b469 aliguori
    qemu_put_be32(f, v >> 32);
740 a672b469 aliguori
    qemu_put_be32(f, v);
741 a672b469 aliguori
}
742 a672b469 aliguori
743 a672b469 aliguori
unsigned int qemu_get_be16(QEMUFile *f)
744 a672b469 aliguori
{
745 a672b469 aliguori
    unsigned int v;
746 a672b469 aliguori
    v = qemu_get_byte(f) << 8;
747 a672b469 aliguori
    v |= qemu_get_byte(f);
748 a672b469 aliguori
    return v;
749 a672b469 aliguori
}
750 a672b469 aliguori
751 a672b469 aliguori
unsigned int qemu_get_be32(QEMUFile *f)
752 a672b469 aliguori
{
753 a672b469 aliguori
    unsigned int v;
754 a672b469 aliguori
    v = qemu_get_byte(f) << 24;
755 a672b469 aliguori
    v |= qemu_get_byte(f) << 16;
756 a672b469 aliguori
    v |= qemu_get_byte(f) << 8;
757 a672b469 aliguori
    v |= qemu_get_byte(f);
758 a672b469 aliguori
    return v;
759 a672b469 aliguori
}
760 a672b469 aliguori
761 a672b469 aliguori
uint64_t qemu_get_be64(QEMUFile *f)
762 a672b469 aliguori
{
763 a672b469 aliguori
    uint64_t v;
764 a672b469 aliguori
    v = (uint64_t)qemu_get_be32(f) << 32;
765 a672b469 aliguori
    v |= qemu_get_be32(f);
766 a672b469 aliguori
    return v;
767 a672b469 aliguori
}
768 a672b469 aliguori
769 2ff68d07 Paolo Bonzini
770 2ff68d07 Paolo Bonzini
/* timer */
771 2ff68d07 Paolo Bonzini
772 2ff68d07 Paolo Bonzini
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
773 2ff68d07 Paolo Bonzini
{
774 2ff68d07 Paolo Bonzini
    uint64_t expire_time;
775 2ff68d07 Paolo Bonzini
776 2ff68d07 Paolo Bonzini
    expire_time = qemu_timer_expire_time_ns(ts);
777 2ff68d07 Paolo Bonzini
    qemu_put_be64(f, expire_time);
778 2ff68d07 Paolo Bonzini
}
779 2ff68d07 Paolo Bonzini
780 2ff68d07 Paolo Bonzini
void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
781 2ff68d07 Paolo Bonzini
{
782 2ff68d07 Paolo Bonzini
    uint64_t expire_time;
783 2ff68d07 Paolo Bonzini
784 2ff68d07 Paolo Bonzini
    expire_time = qemu_get_be64(f);
785 2ff68d07 Paolo Bonzini
    if (expire_time != -1) {
786 2ff68d07 Paolo Bonzini
        qemu_mod_timer_ns(ts, expire_time);
787 2ff68d07 Paolo Bonzini
    } else {
788 2ff68d07 Paolo Bonzini
        qemu_del_timer(ts);
789 2ff68d07 Paolo Bonzini
    }
790 2ff68d07 Paolo Bonzini
}
791 2ff68d07 Paolo Bonzini
792 2ff68d07 Paolo Bonzini
793 cdae5cfb Gerd Hoffmann
/* bool */
794 cdae5cfb Gerd Hoffmann
795 cdae5cfb Gerd Hoffmann
static int get_bool(QEMUFile *f, void *pv, size_t size)
796 cdae5cfb Gerd Hoffmann
{
797 cdae5cfb Gerd Hoffmann
    bool *v = pv;
798 cdae5cfb Gerd Hoffmann
    *v = qemu_get_byte(f);
799 cdae5cfb Gerd Hoffmann
    return 0;
800 cdae5cfb Gerd Hoffmann
}
801 cdae5cfb Gerd Hoffmann
802 cdae5cfb Gerd Hoffmann
static void put_bool(QEMUFile *f, void *pv, size_t size)
803 cdae5cfb Gerd Hoffmann
{
804 cdae5cfb Gerd Hoffmann
    bool *v = pv;
805 cdae5cfb Gerd Hoffmann
    qemu_put_byte(f, *v);
806 cdae5cfb Gerd Hoffmann
}
807 cdae5cfb Gerd Hoffmann
808 cdae5cfb Gerd Hoffmann
const VMStateInfo vmstate_info_bool = {
809 cdae5cfb Gerd Hoffmann
    .name = "bool",
810 cdae5cfb Gerd Hoffmann
    .get  = get_bool,
811 cdae5cfb Gerd Hoffmann
    .put  = put_bool,
812 cdae5cfb Gerd Hoffmann
};
813 cdae5cfb Gerd Hoffmann
814 9ed7d6ae Juan Quintela
/* 8 bit int */
815 9ed7d6ae Juan Quintela
816 9ed7d6ae Juan Quintela
static int get_int8(QEMUFile *f, void *pv, size_t size)
817 9ed7d6ae Juan Quintela
{
818 9ed7d6ae Juan Quintela
    int8_t *v = pv;
819 9ed7d6ae Juan Quintela
    qemu_get_s8s(f, v);
820 9ed7d6ae Juan Quintela
    return 0;
821 9ed7d6ae Juan Quintela
}
822 9ed7d6ae Juan Quintela
823 84e2e3eb Juan Quintela
static void put_int8(QEMUFile *f, void *pv, size_t size)
824 9ed7d6ae Juan Quintela
{
825 84e2e3eb Juan Quintela
    int8_t *v = pv;
826 9ed7d6ae Juan Quintela
    qemu_put_s8s(f, v);
827 9ed7d6ae Juan Quintela
}
828 9ed7d6ae Juan Quintela
829 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int8 = {
830 9ed7d6ae Juan Quintela
    .name = "int8",
831 9ed7d6ae Juan Quintela
    .get  = get_int8,
832 9ed7d6ae Juan Quintela
    .put  = put_int8,
833 9ed7d6ae Juan Quintela
};
834 9ed7d6ae Juan Quintela
835 9ed7d6ae Juan Quintela
/* 16 bit int */
836 9ed7d6ae Juan Quintela
837 9ed7d6ae Juan Quintela
static int get_int16(QEMUFile *f, void *pv, size_t size)
838 9ed7d6ae Juan Quintela
{
839 9ed7d6ae Juan Quintela
    int16_t *v = pv;
840 9ed7d6ae Juan Quintela
    qemu_get_sbe16s(f, v);
841 9ed7d6ae Juan Quintela
    return 0;
842 9ed7d6ae Juan Quintela
}
843 9ed7d6ae Juan Quintela
844 84e2e3eb Juan Quintela
static void put_int16(QEMUFile *f, void *pv, size_t size)
845 9ed7d6ae Juan Quintela
{
846 84e2e3eb Juan Quintela
    int16_t *v = pv;
847 9ed7d6ae Juan Quintela
    qemu_put_sbe16s(f, v);
848 9ed7d6ae Juan Quintela
}
849 9ed7d6ae Juan Quintela
850 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int16 = {
851 9ed7d6ae Juan Quintela
    .name = "int16",
852 9ed7d6ae Juan Quintela
    .get  = get_int16,
853 9ed7d6ae Juan Quintela
    .put  = put_int16,
854 9ed7d6ae Juan Quintela
};
855 9ed7d6ae Juan Quintela
856 9ed7d6ae Juan Quintela
/* 32 bit int */
857 9ed7d6ae Juan Quintela
858 9ed7d6ae Juan Quintela
static int get_int32(QEMUFile *f, void *pv, size_t size)
859 9ed7d6ae Juan Quintela
{
860 9ed7d6ae Juan Quintela
    int32_t *v = pv;
861 9ed7d6ae Juan Quintela
    qemu_get_sbe32s(f, v);
862 9ed7d6ae Juan Quintela
    return 0;
863 9ed7d6ae Juan Quintela
}
864 9ed7d6ae Juan Quintela
865 84e2e3eb Juan Quintela
static void put_int32(QEMUFile *f, void *pv, size_t size)
866 9ed7d6ae Juan Quintela
{
867 84e2e3eb Juan Quintela
    int32_t *v = pv;
868 9ed7d6ae Juan Quintela
    qemu_put_sbe32s(f, v);
869 9ed7d6ae Juan Quintela
}
870 9ed7d6ae Juan Quintela
871 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int32 = {
872 9ed7d6ae Juan Quintela
    .name = "int32",
873 9ed7d6ae Juan Quintela
    .get  = get_int32,
874 9ed7d6ae Juan Quintela
    .put  = put_int32,
875 9ed7d6ae Juan Quintela
};
876 9ed7d6ae Juan Quintela
877 82501660 Juan Quintela
/* 32 bit int. See that the received value is the same than the one
878 82501660 Juan Quintela
   in the field */
879 82501660 Juan Quintela
880 82501660 Juan Quintela
static int get_int32_equal(QEMUFile *f, void *pv, size_t size)
881 82501660 Juan Quintela
{
882 82501660 Juan Quintela
    int32_t *v = pv;
883 82501660 Juan Quintela
    int32_t v2;
884 82501660 Juan Quintela
    qemu_get_sbe32s(f, &v2);
885 82501660 Juan Quintela
886 82501660 Juan Quintela
    if (*v == v2)
887 82501660 Juan Quintela
        return 0;
888 82501660 Juan Quintela
    return -EINVAL;
889 82501660 Juan Quintela
}
890 82501660 Juan Quintela
891 82501660 Juan Quintela
const VMStateInfo vmstate_info_int32_equal = {
892 82501660 Juan Quintela
    .name = "int32 equal",
893 82501660 Juan Quintela
    .get  = get_int32_equal,
894 82501660 Juan Quintela
    .put  = put_int32,
895 82501660 Juan Quintela
};
896 82501660 Juan Quintela
897 0a031e0a Juan Quintela
/* 32 bit int. See that the received value is the less or the same
898 0a031e0a Juan Quintela
   than the one in the field */
899 0a031e0a Juan Quintela
900 0a031e0a Juan Quintela
static int get_int32_le(QEMUFile *f, void *pv, size_t size)
901 0a031e0a Juan Quintela
{
902 0a031e0a Juan Quintela
    int32_t *old = pv;
903 0a031e0a Juan Quintela
    int32_t new;
904 0a031e0a Juan Quintela
    qemu_get_sbe32s(f, &new);
905 0a031e0a Juan Quintela
906 0a031e0a Juan Quintela
    if (*old <= new)
907 0a031e0a Juan Quintela
        return 0;
908 0a031e0a Juan Quintela
    return -EINVAL;
909 0a031e0a Juan Quintela
}
910 0a031e0a Juan Quintela
911 0a031e0a Juan Quintela
const VMStateInfo vmstate_info_int32_le = {
912 0a031e0a Juan Quintela
    .name = "int32 equal",
913 0a031e0a Juan Quintela
    .get  = get_int32_le,
914 0a031e0a Juan Quintela
    .put  = put_int32,
915 0a031e0a Juan Quintela
};
916 0a031e0a Juan Quintela
917 9ed7d6ae Juan Quintela
/* 64 bit int */
918 9ed7d6ae Juan Quintela
919 9ed7d6ae Juan Quintela
static int get_int64(QEMUFile *f, void *pv, size_t size)
920 9ed7d6ae Juan Quintela
{
921 9ed7d6ae Juan Quintela
    int64_t *v = pv;
922 9ed7d6ae Juan Quintela
    qemu_get_sbe64s(f, v);
923 9ed7d6ae Juan Quintela
    return 0;
924 9ed7d6ae Juan Quintela
}
925 9ed7d6ae Juan Quintela
926 84e2e3eb Juan Quintela
static void put_int64(QEMUFile *f, void *pv, size_t size)
927 9ed7d6ae Juan Quintela
{
928 84e2e3eb Juan Quintela
    int64_t *v = pv;
929 9ed7d6ae Juan Quintela
    qemu_put_sbe64s(f, v);
930 9ed7d6ae Juan Quintela
}
931 9ed7d6ae Juan Quintela
932 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_int64 = {
933 9ed7d6ae Juan Quintela
    .name = "int64",
934 9ed7d6ae Juan Quintela
    .get  = get_int64,
935 9ed7d6ae Juan Quintela
    .put  = put_int64,
936 9ed7d6ae Juan Quintela
};
937 9ed7d6ae Juan Quintela
938 9ed7d6ae Juan Quintela
/* 8 bit unsigned int */
939 9ed7d6ae Juan Quintela
940 9ed7d6ae Juan Quintela
static int get_uint8(QEMUFile *f, void *pv, size_t size)
941 9ed7d6ae Juan Quintela
{
942 9ed7d6ae Juan Quintela
    uint8_t *v = pv;
943 9ed7d6ae Juan Quintela
    qemu_get_8s(f, v);
944 9ed7d6ae Juan Quintela
    return 0;
945 9ed7d6ae Juan Quintela
}
946 9ed7d6ae Juan Quintela
947 84e2e3eb Juan Quintela
static void put_uint8(QEMUFile *f, void *pv, size_t size)
948 9ed7d6ae Juan Quintela
{
949 84e2e3eb Juan Quintela
    uint8_t *v = pv;
950 9ed7d6ae Juan Quintela
    qemu_put_8s(f, v);
951 9ed7d6ae Juan Quintela
}
952 9ed7d6ae Juan Quintela
953 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint8 = {
954 9ed7d6ae Juan Quintela
    .name = "uint8",
955 9ed7d6ae Juan Quintela
    .get  = get_uint8,
956 9ed7d6ae Juan Quintela
    .put  = put_uint8,
957 9ed7d6ae Juan Quintela
};
958 9ed7d6ae Juan Quintela
959 9ed7d6ae Juan Quintela
/* 16 bit unsigned int */
960 9ed7d6ae Juan Quintela
961 9ed7d6ae Juan Quintela
static int get_uint16(QEMUFile *f, void *pv, size_t size)
962 9ed7d6ae Juan Quintela
{
963 9ed7d6ae Juan Quintela
    uint16_t *v = pv;
964 9ed7d6ae Juan Quintela
    qemu_get_be16s(f, v);
965 9ed7d6ae Juan Quintela
    return 0;
966 9ed7d6ae Juan Quintela
}
967 9ed7d6ae Juan Quintela
968 84e2e3eb Juan Quintela
static void put_uint16(QEMUFile *f, void *pv, size_t size)
969 9ed7d6ae Juan Quintela
{
970 84e2e3eb Juan Quintela
    uint16_t *v = pv;
971 9ed7d6ae Juan Quintela
    qemu_put_be16s(f, v);
972 9ed7d6ae Juan Quintela
}
973 9ed7d6ae Juan Quintela
974 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint16 = {
975 9ed7d6ae Juan Quintela
    .name = "uint16",
976 9ed7d6ae Juan Quintela
    .get  = get_uint16,
977 9ed7d6ae Juan Quintela
    .put  = put_uint16,
978 9ed7d6ae Juan Quintela
};
979 9ed7d6ae Juan Quintela
980 9ed7d6ae Juan Quintela
/* 32 bit unsigned int */
981 9ed7d6ae Juan Quintela
982 9ed7d6ae Juan Quintela
static int get_uint32(QEMUFile *f, void *pv, size_t size)
983 9ed7d6ae Juan Quintela
{
984 9ed7d6ae Juan Quintela
    uint32_t *v = pv;
985 9ed7d6ae Juan Quintela
    qemu_get_be32s(f, v);
986 9ed7d6ae Juan Quintela
    return 0;
987 9ed7d6ae Juan Quintela
}
988 9ed7d6ae Juan Quintela
989 84e2e3eb Juan Quintela
static void put_uint32(QEMUFile *f, void *pv, size_t size)
990 9ed7d6ae Juan Quintela
{
991 84e2e3eb Juan Quintela
    uint32_t *v = pv;
992 9ed7d6ae Juan Quintela
    qemu_put_be32s(f, v);
993 9ed7d6ae Juan Quintela
}
994 9ed7d6ae Juan Quintela
995 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint32 = {
996 9ed7d6ae Juan Quintela
    .name = "uint32",
997 9ed7d6ae Juan Quintela
    .get  = get_uint32,
998 9ed7d6ae Juan Quintela
    .put  = put_uint32,
999 9ed7d6ae Juan Quintela
};
1000 9ed7d6ae Juan Quintela
1001 9122a8fe Juan Quintela
/* 32 bit uint. See that the received value is the same than the one
1002 9122a8fe Juan Quintela
   in the field */
1003 9122a8fe Juan Quintela
1004 9122a8fe Juan Quintela
static int get_uint32_equal(QEMUFile *f, void *pv, size_t size)
1005 9122a8fe Juan Quintela
{
1006 9122a8fe Juan Quintela
    uint32_t *v = pv;
1007 9122a8fe Juan Quintela
    uint32_t v2;
1008 9122a8fe Juan Quintela
    qemu_get_be32s(f, &v2);
1009 9122a8fe Juan Quintela
1010 9122a8fe Juan Quintela
    if (*v == v2) {
1011 9122a8fe Juan Quintela
        return 0;
1012 9122a8fe Juan Quintela
    }
1013 9122a8fe Juan Quintela
    return -EINVAL;
1014 9122a8fe Juan Quintela
}
1015 9122a8fe Juan Quintela
1016 9122a8fe Juan Quintela
const VMStateInfo vmstate_info_uint32_equal = {
1017 9122a8fe Juan Quintela
    .name = "uint32 equal",
1018 9122a8fe Juan Quintela
    .get  = get_uint32_equal,
1019 9122a8fe Juan Quintela
    .put  = put_uint32,
1020 9122a8fe Juan Quintela
};
1021 9122a8fe Juan Quintela
1022 9ed7d6ae Juan Quintela
/* 64 bit unsigned int */
1023 9ed7d6ae Juan Quintela
1024 9ed7d6ae Juan Quintela
static int get_uint64(QEMUFile *f, void *pv, size_t size)
1025 9ed7d6ae Juan Quintela
{
1026 9ed7d6ae Juan Quintela
    uint64_t *v = pv;
1027 9ed7d6ae Juan Quintela
    qemu_get_be64s(f, v);
1028 9ed7d6ae Juan Quintela
    return 0;
1029 9ed7d6ae Juan Quintela
}
1030 9ed7d6ae Juan Quintela
1031 84e2e3eb Juan Quintela
static void put_uint64(QEMUFile *f, void *pv, size_t size)
1032 9ed7d6ae Juan Quintela
{
1033 84e2e3eb Juan Quintela
    uint64_t *v = pv;
1034 9ed7d6ae Juan Quintela
    qemu_put_be64s(f, v);
1035 9ed7d6ae Juan Quintela
}
1036 9ed7d6ae Juan Quintela
1037 9ed7d6ae Juan Quintela
const VMStateInfo vmstate_info_uint64 = {
1038 9ed7d6ae Juan Quintela
    .name = "uint64",
1039 9ed7d6ae Juan Quintela
    .get  = get_uint64,
1040 9ed7d6ae Juan Quintela
    .put  = put_uint64,
1041 9ed7d6ae Juan Quintela
};
1042 9ed7d6ae Juan Quintela
1043 80cd83e7 Juan Quintela
/* 8 bit int. See that the received value is the same than the one
1044 80cd83e7 Juan Quintela
   in the field */
1045 80cd83e7 Juan Quintela
1046 80cd83e7 Juan Quintela
static int get_uint8_equal(QEMUFile *f, void *pv, size_t size)
1047 80cd83e7 Juan Quintela
{
1048 80cd83e7 Juan Quintela
    uint8_t *v = pv;
1049 80cd83e7 Juan Quintela
    uint8_t v2;
1050 80cd83e7 Juan Quintela
    qemu_get_8s(f, &v2);
1051 80cd83e7 Juan Quintela
1052 80cd83e7 Juan Quintela
    if (*v == v2)
1053 80cd83e7 Juan Quintela
        return 0;
1054 80cd83e7 Juan Quintela
    return -EINVAL;
1055 80cd83e7 Juan Quintela
}
1056 80cd83e7 Juan Quintela
1057 80cd83e7 Juan Quintela
const VMStateInfo vmstate_info_uint8_equal = {
1058 aa1cce69 Juan Quintela
    .name = "uint8 equal",
1059 80cd83e7 Juan Quintela
    .get  = get_uint8_equal,
1060 80cd83e7 Juan Quintela
    .put  = put_uint8,
1061 80cd83e7 Juan Quintela
};
1062 80cd83e7 Juan Quintela
1063 dc3b83a0 Juan Quintela
/* 16 bit unsigned int int. See that the received value is the same than the one
1064 dc3b83a0 Juan Quintela
   in the field */
1065 dc3b83a0 Juan Quintela
1066 dc3b83a0 Juan Quintela
static int get_uint16_equal(QEMUFile *f, void *pv, size_t size)
1067 dc3b83a0 Juan Quintela
{
1068 dc3b83a0 Juan Quintela
    uint16_t *v = pv;
1069 dc3b83a0 Juan Quintela
    uint16_t v2;
1070 dc3b83a0 Juan Quintela
    qemu_get_be16s(f, &v2);
1071 dc3b83a0 Juan Quintela
1072 dc3b83a0 Juan Quintela
    if (*v == v2)
1073 dc3b83a0 Juan Quintela
        return 0;
1074 dc3b83a0 Juan Quintela
    return -EINVAL;
1075 dc3b83a0 Juan Quintela
}
1076 dc3b83a0 Juan Quintela
1077 dc3b83a0 Juan Quintela
const VMStateInfo vmstate_info_uint16_equal = {
1078 dc3b83a0 Juan Quintela
    .name = "uint16 equal",
1079 dc3b83a0 Juan Quintela
    .get  = get_uint16_equal,
1080 dc3b83a0 Juan Quintela
    .put  = put_uint16,
1081 dc3b83a0 Juan Quintela
};
1082 dc3b83a0 Juan Quintela
1083 dde0463b Juan Quintela
/* timers  */
1084 dde0463b Juan Quintela
1085 dde0463b Juan Quintela
static int get_timer(QEMUFile *f, void *pv, size_t size)
1086 dde0463b Juan Quintela
{
1087 dde0463b Juan Quintela
    QEMUTimer *v = pv;
1088 dde0463b Juan Quintela
    qemu_get_timer(f, v);
1089 dde0463b Juan Quintela
    return 0;
1090 dde0463b Juan Quintela
}
1091 dde0463b Juan Quintela
1092 84e2e3eb Juan Quintela
static void put_timer(QEMUFile *f, void *pv, size_t size)
1093 dde0463b Juan Quintela
{
1094 84e2e3eb Juan Quintela
    QEMUTimer *v = pv;
1095 dde0463b Juan Quintela
    qemu_put_timer(f, v);
1096 dde0463b Juan Quintela
}
1097 dde0463b Juan Quintela
1098 dde0463b Juan Quintela
const VMStateInfo vmstate_info_timer = {
1099 dde0463b Juan Quintela
    .name = "timer",
1100 dde0463b Juan Quintela
    .get  = get_timer,
1101 dde0463b Juan Quintela
    .put  = put_timer,
1102 dde0463b Juan Quintela
};
1103 dde0463b Juan Quintela
1104 6f67c50f Juan Quintela
/* uint8_t buffers */
1105 6f67c50f Juan Quintela
1106 6f67c50f Juan Quintela
static int get_buffer(QEMUFile *f, void *pv, size_t size)
1107 6f67c50f Juan Quintela
{
1108 6f67c50f Juan Quintela
    uint8_t *v = pv;
1109 6f67c50f Juan Quintela
    qemu_get_buffer(f, v, size);
1110 6f67c50f Juan Quintela
    return 0;
1111 6f67c50f Juan Quintela
}
1112 6f67c50f Juan Quintela
1113 84e2e3eb Juan Quintela
static void put_buffer(QEMUFile *f, void *pv, size_t size)
1114 6f67c50f Juan Quintela
{
1115 84e2e3eb Juan Quintela
    uint8_t *v = pv;
1116 6f67c50f Juan Quintela
    qemu_put_buffer(f, v, size);
1117 6f67c50f Juan Quintela
}
1118 6f67c50f Juan Quintela
1119 6f67c50f Juan Quintela
const VMStateInfo vmstate_info_buffer = {
1120 6f67c50f Juan Quintela
    .name = "buffer",
1121 6f67c50f Juan Quintela
    .get  = get_buffer,
1122 6f67c50f Juan Quintela
    .put  = put_buffer,
1123 6f67c50f Juan Quintela
};
1124 6f67c50f Juan Quintela
1125 76507c75 Juan Quintela
/* unused buffers: space that was used for some fields that are
1126 61cc8701 Stefan Weil
   not useful anymore */
1127 76507c75 Juan Quintela
1128 76507c75 Juan Quintela
static int get_unused_buffer(QEMUFile *f, void *pv, size_t size)
1129 76507c75 Juan Quintela
{
1130 21174c34 Jan Kiszka
    uint8_t buf[1024];
1131 21174c34 Jan Kiszka
    int block_len;
1132 21174c34 Jan Kiszka
1133 21174c34 Jan Kiszka
    while (size > 0) {
1134 21174c34 Jan Kiszka
        block_len = MIN(sizeof(buf), size);
1135 21174c34 Jan Kiszka
        size -= block_len;
1136 21174c34 Jan Kiszka
        qemu_get_buffer(f, buf, block_len);
1137 21174c34 Jan Kiszka
    }
1138 21174c34 Jan Kiszka
   return 0;
1139 76507c75 Juan Quintela
}
1140 76507c75 Juan Quintela
1141 76507c75 Juan Quintela
static void put_unused_buffer(QEMUFile *f, void *pv, size_t size)
1142 76507c75 Juan Quintela
{
1143 21174c34 Jan Kiszka
    static const uint8_t buf[1024];
1144 21174c34 Jan Kiszka
    int block_len;
1145 21174c34 Jan Kiszka
1146 21174c34 Jan Kiszka
    while (size > 0) {
1147 21174c34 Jan Kiszka
        block_len = MIN(sizeof(buf), size);
1148 21174c34 Jan Kiszka
        size -= block_len;
1149 21174c34 Jan Kiszka
        qemu_put_buffer(f, buf, block_len);
1150 21174c34 Jan Kiszka
    }
1151 76507c75 Juan Quintela
}
1152 76507c75 Juan Quintela
1153 76507c75 Juan Quintela
const VMStateInfo vmstate_info_unused_buffer = {
1154 76507c75 Juan Quintela
    .name = "unused_buffer",
1155 76507c75 Juan Quintela
    .get  = get_unused_buffer,
1156 76507c75 Juan Quintela
    .put  = put_unused_buffer,
1157 76507c75 Juan Quintela
};
1158 76507c75 Juan Quintela
1159 7685ee6a Alex Williamson
typedef struct CompatEntry {
1160 7685ee6a Alex Williamson
    char idstr[256];
1161 7685ee6a Alex Williamson
    int instance_id;
1162 7685ee6a Alex Williamson
} CompatEntry;
1163 7685ee6a Alex Williamson
1164 a672b469 aliguori
typedef struct SaveStateEntry {
1165 72cf2d4f Blue Swirl
    QTAILQ_ENTRY(SaveStateEntry) entry;
1166 a672b469 aliguori
    char idstr[256];
1167 a672b469 aliguori
    int instance_id;
1168 4d2ffa08 Jan Kiszka
    int alias_id;
1169 a672b469 aliguori
    int version_id;
1170 a672b469 aliguori
    int section_id;
1171 c163b5ca lirans@il.ibm.com
    SaveSetParamsHandler *set_params;
1172 a672b469 aliguori
    SaveLiveStateHandler *save_live_state;
1173 a672b469 aliguori
    SaveStateHandler *save_state;
1174 a672b469 aliguori
    LoadStateHandler *load_state;
1175 9ed7d6ae Juan Quintela
    const VMStateDescription *vmsd;
1176 a672b469 aliguori
    void *opaque;
1177 7685ee6a Alex Williamson
    CompatEntry *compat;
1178 24312968 Cam Macdonell
    int no_migrate;
1179 a672b469 aliguori
} SaveStateEntry;
1180 a672b469 aliguori
1181 c163b5ca lirans@il.ibm.com
1182 72cf2d4f Blue Swirl
static QTAILQ_HEAD(savevm_handlers, SaveStateEntry) savevm_handlers =
1183 72cf2d4f Blue Swirl
    QTAILQ_HEAD_INITIALIZER(savevm_handlers);
1184 9ed7d6ae Juan Quintela
static int global_section_id;
1185 a672b469 aliguori
1186 8718e999 Juan Quintela
static int calculate_new_instance_id(const char *idstr)
1187 8718e999 Juan Quintela
{
1188 8718e999 Juan Quintela
    SaveStateEntry *se;
1189 8718e999 Juan Quintela
    int instance_id = 0;
1190 8718e999 Juan Quintela
1191 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1192 8718e999 Juan Quintela
        if (strcmp(idstr, se->idstr) == 0
1193 8718e999 Juan Quintela
            && instance_id <= se->instance_id) {
1194 8718e999 Juan Quintela
            instance_id = se->instance_id + 1;
1195 8718e999 Juan Quintela
        }
1196 8718e999 Juan Quintela
    }
1197 8718e999 Juan Quintela
    return instance_id;
1198 8718e999 Juan Quintela
}
1199 8718e999 Juan Quintela
1200 7685ee6a Alex Williamson
static int calculate_compat_instance_id(const char *idstr)
1201 7685ee6a Alex Williamson
{
1202 7685ee6a Alex Williamson
    SaveStateEntry *se;
1203 7685ee6a Alex Williamson
    int instance_id = 0;
1204 7685ee6a Alex Williamson
1205 7685ee6a Alex Williamson
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1206 7685ee6a Alex Williamson
        if (!se->compat)
1207 7685ee6a Alex Williamson
            continue;
1208 7685ee6a Alex Williamson
1209 7685ee6a Alex Williamson
        if (strcmp(idstr, se->compat->idstr) == 0
1210 7685ee6a Alex Williamson
            && instance_id <= se->compat->instance_id) {
1211 7685ee6a Alex Williamson
            instance_id = se->compat->instance_id + 1;
1212 7685ee6a Alex Williamson
        }
1213 7685ee6a Alex Williamson
    }
1214 7685ee6a Alex Williamson
    return instance_id;
1215 7685ee6a Alex Williamson
}
1216 7685ee6a Alex Williamson
1217 a672b469 aliguori
/* TODO: Individual devices generally have very little idea about the rest
1218 a672b469 aliguori
   of the system, so instance_id should be removed/replaced.
1219 a672b469 aliguori
   Meanwhile pass -1 as instance_id if you do not already have a clearly
1220 a672b469 aliguori
   distinguishing id for all instances of your device class. */
1221 0be71e32 Alex Williamson
int register_savevm_live(DeviceState *dev,
1222 0be71e32 Alex Williamson
                         const char *idstr,
1223 a672b469 aliguori
                         int instance_id,
1224 a672b469 aliguori
                         int version_id,
1225 c163b5ca lirans@il.ibm.com
                         SaveSetParamsHandler *set_params,
1226 a672b469 aliguori
                         SaveLiveStateHandler *save_live_state,
1227 a672b469 aliguori
                         SaveStateHandler *save_state,
1228 a672b469 aliguori
                         LoadStateHandler *load_state,
1229 a672b469 aliguori
                         void *opaque)
1230 a672b469 aliguori
{
1231 8718e999 Juan Quintela
    SaveStateEntry *se;
1232 a672b469 aliguori
1233 7267c094 Anthony Liguori
    se = g_malloc0(sizeof(SaveStateEntry));
1234 a672b469 aliguori
    se->version_id = version_id;
1235 a672b469 aliguori
    se->section_id = global_section_id++;
1236 c163b5ca lirans@il.ibm.com
    se->set_params = set_params;
1237 a672b469 aliguori
    se->save_live_state = save_live_state;
1238 a672b469 aliguori
    se->save_state = save_state;
1239 a672b469 aliguori
    se->load_state = load_state;
1240 a672b469 aliguori
    se->opaque = opaque;
1241 9ed7d6ae Juan Quintela
    se->vmsd = NULL;
1242 24312968 Cam Macdonell
    se->no_migrate = 0;
1243 a672b469 aliguori
1244 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1245 7685ee6a Alex Williamson
        char *id = dev->parent_bus->info->get_dev_path(dev);
1246 7685ee6a Alex Williamson
        if (id) {
1247 7685ee6a Alex Williamson
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1248 7685ee6a Alex Williamson
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1249 7267c094 Anthony Liguori
            g_free(id);
1250 7685ee6a Alex Williamson
1251 7267c094 Anthony Liguori
            se->compat = g_malloc0(sizeof(CompatEntry));
1252 7685ee6a Alex Williamson
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), idstr);
1253 7685ee6a Alex Williamson
            se->compat->instance_id = instance_id == -1 ?
1254 7685ee6a Alex Williamson
                         calculate_compat_instance_id(idstr) : instance_id;
1255 7685ee6a Alex Williamson
            instance_id = -1;
1256 7685ee6a Alex Williamson
        }
1257 7685ee6a Alex Williamson
    }
1258 7685ee6a Alex Williamson
    pstrcat(se->idstr, sizeof(se->idstr), idstr);
1259 7685ee6a Alex Williamson
1260 8718e999 Juan Quintela
    if (instance_id == -1) {
1261 7685ee6a Alex Williamson
        se->instance_id = calculate_new_instance_id(se->idstr);
1262 8718e999 Juan Quintela
    } else {
1263 8718e999 Juan Quintela
        se->instance_id = instance_id;
1264 a672b469 aliguori
    }
1265 7685ee6a Alex Williamson
    assert(!se->compat || se->instance_id == 0);
1266 8718e999 Juan Quintela
    /* add at the end of list */
1267 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1268 a672b469 aliguori
    return 0;
1269 a672b469 aliguori
}
1270 a672b469 aliguori
1271 0be71e32 Alex Williamson
int register_savevm(DeviceState *dev,
1272 0be71e32 Alex Williamson
                    const char *idstr,
1273 a672b469 aliguori
                    int instance_id,
1274 a672b469 aliguori
                    int version_id,
1275 a672b469 aliguori
                    SaveStateHandler *save_state,
1276 a672b469 aliguori
                    LoadStateHandler *load_state,
1277 a672b469 aliguori
                    void *opaque)
1278 a672b469 aliguori
{
1279 0be71e32 Alex Williamson
    return register_savevm_live(dev, idstr, instance_id, version_id,
1280 c163b5ca lirans@il.ibm.com
                                NULL, NULL, save_state, load_state, opaque);
1281 a672b469 aliguori
}
1282 a672b469 aliguori
1283 0be71e32 Alex Williamson
void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
1284 41bd13af aliguori
{
1285 8718e999 Juan Quintela
    SaveStateEntry *se, *new_se;
1286 7685ee6a Alex Williamson
    char id[256] = "";
1287 7685ee6a Alex Williamson
1288 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1289 7685ee6a Alex Williamson
        char *path = dev->parent_bus->info->get_dev_path(dev);
1290 7685ee6a Alex Williamson
        if (path) {
1291 7685ee6a Alex Williamson
            pstrcpy(id, sizeof(id), path);
1292 7685ee6a Alex Williamson
            pstrcat(id, sizeof(id), "/");
1293 7267c094 Anthony Liguori
            g_free(path);
1294 7685ee6a Alex Williamson
        }
1295 7685ee6a Alex Williamson
    }
1296 7685ee6a Alex Williamson
    pstrcat(id, sizeof(id), idstr);
1297 41bd13af aliguori
1298 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
1299 7685ee6a Alex Williamson
        if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
1300 72cf2d4f Blue Swirl
            QTAILQ_REMOVE(&savevm_handlers, se, entry);
1301 69e58af9 Alex Williamson
            if (se->compat) {
1302 7267c094 Anthony Liguori
                g_free(se->compat);
1303 69e58af9 Alex Williamson
            }
1304 7267c094 Anthony Liguori
            g_free(se);
1305 41bd13af aliguori
        }
1306 41bd13af aliguori
    }
1307 41bd13af aliguori
}
1308 41bd13af aliguori
1309 0be71e32 Alex Williamson
int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
1310 4d2ffa08 Jan Kiszka
                                   const VMStateDescription *vmsd,
1311 4d2ffa08 Jan Kiszka
                                   void *opaque, int alias_id,
1312 4d2ffa08 Jan Kiszka
                                   int required_for_version)
1313 9ed7d6ae Juan Quintela
{
1314 8718e999 Juan Quintela
    SaveStateEntry *se;
1315 9ed7d6ae Juan Quintela
1316 4d2ffa08 Jan Kiszka
    /* If this triggers, alias support can be dropped for the vmsd. */
1317 4d2ffa08 Jan Kiszka
    assert(alias_id == -1 || required_for_version >= vmsd->minimum_version_id);
1318 4d2ffa08 Jan Kiszka
1319 7267c094 Anthony Liguori
    se = g_malloc0(sizeof(SaveStateEntry));
1320 9ed7d6ae Juan Quintela
    se->version_id = vmsd->version_id;
1321 9ed7d6ae Juan Quintela
    se->section_id = global_section_id++;
1322 9ed7d6ae Juan Quintela
    se->save_live_state = NULL;
1323 9ed7d6ae Juan Quintela
    se->save_state = NULL;
1324 9ed7d6ae Juan Quintela
    se->load_state = NULL;
1325 9ed7d6ae Juan Quintela
    se->opaque = opaque;
1326 9ed7d6ae Juan Quintela
    se->vmsd = vmsd;
1327 4d2ffa08 Jan Kiszka
    se->alias_id = alias_id;
1328 2837c8ea Gerd Hoffmann
    se->no_migrate = vmsd->unmigratable;
1329 9ed7d6ae Juan Quintela
1330 7685ee6a Alex Williamson
    if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
1331 7685ee6a Alex Williamson
        char *id = dev->parent_bus->info->get_dev_path(dev);
1332 7685ee6a Alex Williamson
        if (id) {
1333 7685ee6a Alex Williamson
            pstrcpy(se->idstr, sizeof(se->idstr), id);
1334 7685ee6a Alex Williamson
            pstrcat(se->idstr, sizeof(se->idstr), "/");
1335 7267c094 Anthony Liguori
            g_free(id);
1336 7685ee6a Alex Williamson
1337 7267c094 Anthony Liguori
            se->compat = g_malloc0(sizeof(CompatEntry));
1338 7685ee6a Alex Williamson
            pstrcpy(se->compat->idstr, sizeof(se->compat->idstr), vmsd->name);
1339 7685ee6a Alex Williamson
            se->compat->instance_id = instance_id == -1 ?
1340 7685ee6a Alex Williamson
                         calculate_compat_instance_id(vmsd->name) : instance_id;
1341 7685ee6a Alex Williamson
            instance_id = -1;
1342 7685ee6a Alex Williamson
        }
1343 7685ee6a Alex Williamson
    }
1344 7685ee6a Alex Williamson
    pstrcat(se->idstr, sizeof(se->idstr), vmsd->name);
1345 7685ee6a Alex Williamson
1346 8718e999 Juan Quintela
    if (instance_id == -1) {
1347 7685ee6a Alex Williamson
        se->instance_id = calculate_new_instance_id(se->idstr);
1348 8718e999 Juan Quintela
    } else {
1349 8718e999 Juan Quintela
        se->instance_id = instance_id;
1350 9ed7d6ae Juan Quintela
    }
1351 7685ee6a Alex Williamson
    assert(!se->compat || se->instance_id == 0);
1352 8718e999 Juan Quintela
    /* add at the end of list */
1353 72cf2d4f Blue Swirl
    QTAILQ_INSERT_TAIL(&savevm_handlers, se, entry);
1354 9ed7d6ae Juan Quintela
    return 0;
1355 9ed7d6ae Juan Quintela
}
1356 9ed7d6ae Juan Quintela
1357 0be71e32 Alex Williamson
int vmstate_register(DeviceState *dev, int instance_id,
1358 0be71e32 Alex Williamson
                     const VMStateDescription *vmsd, void *opaque)
1359 4d2ffa08 Jan Kiszka
{
1360 0be71e32 Alex Williamson
    return vmstate_register_with_alias_id(dev, instance_id, vmsd,
1361 0be71e32 Alex Williamson
                                          opaque, -1, 0);
1362 4d2ffa08 Jan Kiszka
}
1363 4d2ffa08 Jan Kiszka
1364 0be71e32 Alex Williamson
void vmstate_unregister(DeviceState *dev, const VMStateDescription *vmsd,
1365 0be71e32 Alex Williamson
                        void *opaque)
1366 9ed7d6ae Juan Quintela
{
1367 1eb7538b Juan Quintela
    SaveStateEntry *se, *new_se;
1368 1eb7538b Juan Quintela
1369 72cf2d4f Blue Swirl
    QTAILQ_FOREACH_SAFE(se, &savevm_handlers, entry, new_se) {
1370 1eb7538b Juan Quintela
        if (se->vmsd == vmsd && se->opaque == opaque) {
1371 72cf2d4f Blue Swirl
            QTAILQ_REMOVE(&savevm_handlers, se, entry);
1372 69e58af9 Alex Williamson
            if (se->compat) {
1373 7267c094 Anthony Liguori
                g_free(se->compat);
1374 69e58af9 Alex Williamson
            }
1375 7267c094 Anthony Liguori
            g_free(se);
1376 1eb7538b Juan Quintela
        }
1377 1eb7538b Juan Quintela
    }
1378 9ed7d6ae Juan Quintela
}
1379 9ed7d6ae Juan Quintela
1380 811814bd Juan Quintela
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
1381 811814bd Juan Quintela
                                    void *opaque);
1382 811814bd Juan Quintela
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
1383 811814bd Juan Quintela
                                   void *opaque);
1384 811814bd Juan Quintela
1385 9ed7d6ae Juan Quintela
int vmstate_load_state(QEMUFile *f, const VMStateDescription *vmsd,
1386 9ed7d6ae Juan Quintela
                       void *opaque, int version_id)
1387 9ed7d6ae Juan Quintela
{
1388 9ed7d6ae Juan Quintela
    VMStateField *field = vmsd->fields;
1389 811814bd Juan Quintela
    int ret;
1390 9ed7d6ae Juan Quintela
1391 9ed7d6ae Juan Quintela
    if (version_id > vmsd->version_id) {
1392 9ed7d6ae Juan Quintela
        return -EINVAL;
1393 9ed7d6ae Juan Quintela
    }
1394 9ed7d6ae Juan Quintela
    if (version_id < vmsd->minimum_version_id_old) {
1395 9ed7d6ae Juan Quintela
        return -EINVAL;
1396 9ed7d6ae Juan Quintela
    }
1397 9ed7d6ae Juan Quintela
    if  (version_id < vmsd->minimum_version_id) {
1398 9ed7d6ae Juan Quintela
        return vmsd->load_state_old(f, opaque, version_id);
1399 9ed7d6ae Juan Quintela
    }
1400 fd4d52de Juan Quintela
    if (vmsd->pre_load) {
1401 fd4d52de Juan Quintela
        int ret = vmsd->pre_load(opaque);
1402 fd4d52de Juan Quintela
        if (ret)
1403 fd4d52de Juan Quintela
            return ret;
1404 fd4d52de Juan Quintela
    }
1405 9ed7d6ae Juan Quintela
    while(field->name) {
1406 f11f6a5f Juan Quintela
        if ((field->field_exists &&
1407 f11f6a5f Juan Quintela
             field->field_exists(opaque, version_id)) ||
1408 f11f6a5f Juan Quintela
            (!field->field_exists &&
1409 f11f6a5f Juan Quintela
             field->version_id <= version_id)) {
1410 f752a6aa Juan Quintela
            void *base_addr = opaque + field->offset;
1411 811814bd Juan Quintela
            int i, n_elems = 1;
1412 e61a1e0a Juan Quintela
            int size = field->size;
1413 9ed7d6ae Juan Quintela
1414 e61a1e0a Juan Quintela
            if (field->flags & VMS_VBUFFER) {
1415 e61a1e0a Juan Quintela
                size = *(int32_t *)(opaque+field->size_offset);
1416 33599e2a Juan Quintela
                if (field->flags & VMS_MULTIPLY) {
1417 33599e2a Juan Quintela
                    size *= field->size;
1418 33599e2a Juan Quintela
                }
1419 e61a1e0a Juan Quintela
            }
1420 f752a6aa Juan Quintela
            if (field->flags & VMS_ARRAY) {
1421 f752a6aa Juan Quintela
                n_elems = field->num;
1422 d6698281 Juan Quintela
            } else if (field->flags & VMS_VARRAY_INT32) {
1423 d6698281 Juan Quintela
                n_elems = *(int32_t *)(opaque+field->num_offset);
1424 a624b086 Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT32) {
1425 a624b086 Juan Quintela
                n_elems = *(uint32_t *)(opaque+field->num_offset);
1426 bdb4941d Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT16) {
1427 bdb4941d Juan Quintela
                n_elems = *(uint16_t *)(opaque+field->num_offset);
1428 82fa39b7 Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT8) {
1429 82fa39b7 Juan Quintela
                n_elems = *(uint8_t *)(opaque+field->num_offset);
1430 f752a6aa Juan Quintela
            }
1431 dde0463b Juan Quintela
            if (field->flags & VMS_POINTER) {
1432 e61a1e0a Juan Quintela
                base_addr = *(void **)base_addr + field->start;
1433 dde0463b Juan Quintela
            }
1434 f752a6aa Juan Quintela
            for (i = 0; i < n_elems; i++) {
1435 e61a1e0a Juan Quintela
                void *addr = base_addr + size * i;
1436 ec245e21 Juan Quintela
1437 19df438b Juan Quintela
                if (field->flags & VMS_ARRAY_OF_POINTER) {
1438 19df438b Juan Quintela
                    addr = *(void **)addr;
1439 19df438b Juan Quintela
                }
1440 ec245e21 Juan Quintela
                if (field->flags & VMS_STRUCT) {
1441 fa3aad24 Juan Quintela
                    ret = vmstate_load_state(f, field->vmsd, addr, field->vmsd->version_id);
1442 ec245e21 Juan Quintela
                } else {
1443 e61a1e0a Juan Quintela
                    ret = field->info->get(f, addr, size);
1444 ec245e21 Juan Quintela
1445 ec245e21 Juan Quintela
                }
1446 f752a6aa Juan Quintela
                if (ret < 0) {
1447 f752a6aa Juan Quintela
                    return ret;
1448 f752a6aa Juan Quintela
                }
1449 9ed7d6ae Juan Quintela
            }
1450 9ed7d6ae Juan Quintela
        }
1451 9ed7d6ae Juan Quintela
        field++;
1452 9ed7d6ae Juan Quintela
    }
1453 811814bd Juan Quintela
    ret = vmstate_subsection_load(f, vmsd, opaque);
1454 811814bd Juan Quintela
    if (ret != 0) {
1455 811814bd Juan Quintela
        return ret;
1456 811814bd Juan Quintela
    }
1457 752ff2fa Juan Quintela
    if (vmsd->post_load) {
1458 e59fb374 Juan Quintela
        return vmsd->post_load(opaque, version_id);
1459 752ff2fa Juan Quintela
    }
1460 9ed7d6ae Juan Quintela
    return 0;
1461 9ed7d6ae Juan Quintela
}
1462 9ed7d6ae Juan Quintela
1463 9ed7d6ae Juan Quintela
void vmstate_save_state(QEMUFile *f, const VMStateDescription *vmsd,
1464 84e2e3eb Juan Quintela
                        void *opaque)
1465 9ed7d6ae Juan Quintela
{
1466 9ed7d6ae Juan Quintela
    VMStateField *field = vmsd->fields;
1467 9ed7d6ae Juan Quintela
1468 8fb0791d Juan Quintela
    if (vmsd->pre_save) {
1469 8fb0791d Juan Quintela
        vmsd->pre_save(opaque);
1470 8fb0791d Juan Quintela
    }
1471 9ed7d6ae Juan Quintela
    while(field->name) {
1472 f11f6a5f Juan Quintela
        if (!field->field_exists ||
1473 f11f6a5f Juan Quintela
            field->field_exists(opaque, vmsd->version_id)) {
1474 f11f6a5f Juan Quintela
            void *base_addr = opaque + field->offset;
1475 f11f6a5f Juan Quintela
            int i, n_elems = 1;
1476 e61a1e0a Juan Quintela
            int size = field->size;
1477 dde0463b Juan Quintela
1478 e61a1e0a Juan Quintela
            if (field->flags & VMS_VBUFFER) {
1479 e61a1e0a Juan Quintela
                size = *(int32_t *)(opaque+field->size_offset);
1480 33599e2a Juan Quintela
                if (field->flags & VMS_MULTIPLY) {
1481 33599e2a Juan Quintela
                    size *= field->size;
1482 33599e2a Juan Quintela
                }
1483 e61a1e0a Juan Quintela
            }
1484 f11f6a5f Juan Quintela
            if (field->flags & VMS_ARRAY) {
1485 f11f6a5f Juan Quintela
                n_elems = field->num;
1486 d6698281 Juan Quintela
            } else if (field->flags & VMS_VARRAY_INT32) {
1487 d6698281 Juan Quintela
                n_elems = *(int32_t *)(opaque+field->num_offset);
1488 bdb4941d Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT16) {
1489 bdb4941d Juan Quintela
                n_elems = *(uint16_t *)(opaque+field->num_offset);
1490 b784421c Juan Quintela
            } else if (field->flags & VMS_VARRAY_UINT8) {
1491 b784421c Juan Quintela
                n_elems = *(uint8_t *)(opaque+field->num_offset);
1492 f11f6a5f Juan Quintela
            }
1493 f11f6a5f Juan Quintela
            if (field->flags & VMS_POINTER) {
1494 e61a1e0a Juan Quintela
                base_addr = *(void **)base_addr + field->start;
1495 f11f6a5f Juan Quintela
            }
1496 f11f6a5f Juan Quintela
            for (i = 0; i < n_elems; i++) {
1497 e61a1e0a Juan Quintela
                void *addr = base_addr + size * i;
1498 ec245e21 Juan Quintela
1499 8595387e Juan Quintela
                if (field->flags & VMS_ARRAY_OF_POINTER) {
1500 8595387e Juan Quintela
                    addr = *(void **)addr;
1501 8595387e Juan Quintela
                }
1502 f11f6a5f Juan Quintela
                if (field->flags & VMS_STRUCT) {
1503 f11f6a5f Juan Quintela
                    vmstate_save_state(f, field->vmsd, addr);
1504 f11f6a5f Juan Quintela
                } else {
1505 e61a1e0a Juan Quintela
                    field->info->put(f, addr, size);
1506 f11f6a5f Juan Quintela
                }
1507 ec245e21 Juan Quintela
            }
1508 dde0463b Juan Quintela
        }
1509 9ed7d6ae Juan Quintela
        field++;
1510 9ed7d6ae Juan Quintela
    }
1511 811814bd Juan Quintela
    vmstate_subsection_save(f, vmsd, opaque);
1512 9ed7d6ae Juan Quintela
}
1513 9ed7d6ae Juan Quintela
1514 4082be4d Juan Quintela
static int vmstate_load(QEMUFile *f, SaveStateEntry *se, int version_id)
1515 4082be4d Juan Quintela
{
1516 9ed7d6ae Juan Quintela
    if (!se->vmsd) {         /* Old style */
1517 9ed7d6ae Juan Quintela
        return se->load_state(f, se->opaque, version_id);
1518 9ed7d6ae Juan Quintela
    }
1519 9ed7d6ae Juan Quintela
    return vmstate_load_state(f, se->vmsd, se->opaque, version_id);
1520 4082be4d Juan Quintela
}
1521 4082be4d Juan Quintela
1522 dc912121 Alex Williamson
static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
1523 4082be4d Juan Quintela
{
1524 9ed7d6ae Juan Quintela
    if (!se->vmsd) {         /* Old style */
1525 9ed7d6ae Juan Quintela
        se->save_state(f, se->opaque);
1526 dc912121 Alex Williamson
        return;
1527 9ed7d6ae Juan Quintela
    }
1528 9ed7d6ae Juan Quintela
    vmstate_save_state(f,se->vmsd, se->opaque);
1529 4082be4d Juan Quintela
}
1530 4082be4d Juan Quintela
1531 a672b469 aliguori
#define QEMU_VM_FILE_MAGIC           0x5145564d
1532 a672b469 aliguori
#define QEMU_VM_FILE_VERSION_COMPAT  0x00000002
1533 a672b469 aliguori
#define QEMU_VM_FILE_VERSION         0x00000003
1534 a672b469 aliguori
1535 a672b469 aliguori
#define QEMU_VM_EOF                  0x00
1536 a672b469 aliguori
#define QEMU_VM_SECTION_START        0x01
1537 a672b469 aliguori
#define QEMU_VM_SECTION_PART         0x02
1538 a672b469 aliguori
#define QEMU_VM_SECTION_END          0x03
1539 a672b469 aliguori
#define QEMU_VM_SECTION_FULL         0x04
1540 811814bd Juan Quintela
#define QEMU_VM_SUBSECTION           0x05
1541 a672b469 aliguori
1542 dc912121 Alex Williamson
bool qemu_savevm_state_blocked(Monitor *mon)
1543 dc912121 Alex Williamson
{
1544 dc912121 Alex Williamson
    SaveStateEntry *se;
1545 dc912121 Alex Williamson
1546 dc912121 Alex Williamson
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1547 dc912121 Alex Williamson
        if (se->no_migrate) {
1548 dc912121 Alex Williamson
            monitor_printf(mon, "state blocked by non-migratable device '%s'\n",
1549 dc912121 Alex Williamson
                           se->idstr);
1550 dc912121 Alex Williamson
            return true;
1551 dc912121 Alex Williamson
        }
1552 dc912121 Alex Williamson
    }
1553 dc912121 Alex Williamson
    return false;
1554 dc912121 Alex Williamson
}
1555 dc912121 Alex Williamson
1556 f327aa0c Jan Kiszka
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
1557 f327aa0c Jan Kiszka
                            int shared)
1558 a672b469 aliguori
{
1559 a672b469 aliguori
    SaveStateEntry *se;
1560 39346385 Juan Quintela
    int ret;
1561 a672b469 aliguori
1562 c163b5ca lirans@il.ibm.com
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1563 c163b5ca lirans@il.ibm.com
        if(se->set_params == NULL) {
1564 c163b5ca lirans@il.ibm.com
            continue;
1565 c163b5ca lirans@il.ibm.com
        }
1566 c163b5ca lirans@il.ibm.com
        se->set_params(blk_enable, shared, se->opaque);
1567 c163b5ca lirans@il.ibm.com
    }
1568 c163b5ca lirans@il.ibm.com
    
1569 a672b469 aliguori
    qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
1570 a672b469 aliguori
    qemu_put_be32(f, QEMU_VM_FILE_VERSION);
1571 a672b469 aliguori
1572 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1573 a672b469 aliguori
        int len;
1574 a672b469 aliguori
1575 a672b469 aliguori
        if (se->save_live_state == NULL)
1576 a672b469 aliguori
            continue;
1577 a672b469 aliguori
1578 a672b469 aliguori
        /* Section type */
1579 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_START);
1580 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1581 a672b469 aliguori
1582 a672b469 aliguori
        /* ID string */
1583 a672b469 aliguori
        len = strlen(se->idstr);
1584 a672b469 aliguori
        qemu_put_byte(f, len);
1585 a672b469 aliguori
        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1586 a672b469 aliguori
1587 a672b469 aliguori
        qemu_put_be32(f, se->instance_id);
1588 a672b469 aliguori
        qemu_put_be32(f, se->version_id);
1589 a672b469 aliguori
1590 2975725f Juan Quintela
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
1591 2975725f Juan Quintela
        if (ret < 0) {
1592 2975725f Juan Quintela
            qemu_savevm_state_cancel(mon, f);
1593 2975725f Juan Quintela
            return ret;
1594 2975725f Juan Quintela
        }
1595 a672b469 aliguori
    }
1596 624b9cc2 Juan Quintela
    ret = qemu_file_get_error(f);
1597 39346385 Juan Quintela
    if (ret != 0) {
1598 f327aa0c Jan Kiszka
        qemu_savevm_state_cancel(mon, f);
1599 4ec7fcc7 Jan Kiszka
    }
1600 a672b469 aliguori
1601 39346385 Juan Quintela
    return ret;
1602 39346385 Juan Quintela
1603 a672b469 aliguori
}
1604 a672b469 aliguori
1605 39346385 Juan Quintela
/*
1606 07f35073 Dong Xu Wang
 * this function has three return values:
1607 39346385 Juan Quintela
 *   negative: there was one error, and we have -errno.
1608 39346385 Juan Quintela
 *   0 : We haven't finished, caller have to go again
1609 39346385 Juan Quintela
 *   1 : We have finished, we can go to complete phase
1610 39346385 Juan Quintela
 */
1611 f327aa0c Jan Kiszka
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
1612 a672b469 aliguori
{
1613 a672b469 aliguori
    SaveStateEntry *se;
1614 a672b469 aliguori
    int ret = 1;
1615 a672b469 aliguori
1616 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1617 a672b469 aliguori
        if (se->save_live_state == NULL)
1618 a672b469 aliguori
            continue;
1619 a672b469 aliguori
1620 a672b469 aliguori
        /* Section type */
1621 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_PART);
1622 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1623 a672b469 aliguori
1624 90697be8 Jan Kiszka
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
1625 2975725f Juan Quintela
        if (ret <= 0) {
1626 90697be8 Jan Kiszka
            /* Do not proceed to the next vmstate before this one reported
1627 90697be8 Jan Kiszka
               completion of the current stage. This serializes the migration
1628 90697be8 Jan Kiszka
               and reduces the probability that a faster changing state is
1629 90697be8 Jan Kiszka
               synchronized over and over again. */
1630 90697be8 Jan Kiszka
            break;
1631 90697be8 Jan Kiszka
        }
1632 a672b469 aliguori
    }
1633 39346385 Juan Quintela
    if (ret != 0) {
1634 39346385 Juan Quintela
        return ret;
1635 39346385 Juan Quintela
    }
1636 624b9cc2 Juan Quintela
    ret = qemu_file_get_error(f);
1637 39346385 Juan Quintela
    if (ret != 0) {
1638 f327aa0c Jan Kiszka
        qemu_savevm_state_cancel(mon, f);
1639 4ec7fcc7 Jan Kiszka
    }
1640 39346385 Juan Quintela
    return ret;
1641 a672b469 aliguori
}
1642 a672b469 aliguori
1643 f327aa0c Jan Kiszka
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
1644 a672b469 aliguori
{
1645 a672b469 aliguori
    SaveStateEntry *se;
1646 2975725f Juan Quintela
    int ret;
1647 a672b469 aliguori
1648 ea375f9a Jan Kiszka
    cpu_synchronize_all_states();
1649 ea375f9a Jan Kiszka
1650 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1651 a672b469 aliguori
        if (se->save_live_state == NULL)
1652 a672b469 aliguori
            continue;
1653 a672b469 aliguori
1654 a672b469 aliguori
        /* Section type */
1655 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_END);
1656 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1657 a672b469 aliguori
1658 2975725f Juan Quintela
        ret = se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
1659 2975725f Juan Quintela
        if (ret < 0) {
1660 2975725f Juan Quintela
            return ret;
1661 2975725f Juan Quintela
        }
1662 a672b469 aliguori
    }
1663 a672b469 aliguori
1664 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1665 a672b469 aliguori
        int len;
1666 a672b469 aliguori
1667 9ed7d6ae Juan Quintela
        if (se->save_state == NULL && se->vmsd == NULL)
1668 a672b469 aliguori
            continue;
1669 a672b469 aliguori
1670 a672b469 aliguori
        /* Section type */
1671 a672b469 aliguori
        qemu_put_byte(f, QEMU_VM_SECTION_FULL);
1672 a672b469 aliguori
        qemu_put_be32(f, se->section_id);
1673 a672b469 aliguori
1674 a672b469 aliguori
        /* ID string */
1675 a672b469 aliguori
        len = strlen(se->idstr);
1676 a672b469 aliguori
        qemu_put_byte(f, len);
1677 a672b469 aliguori
        qemu_put_buffer(f, (uint8_t *)se->idstr, len);
1678 a672b469 aliguori
1679 a672b469 aliguori
        qemu_put_be32(f, se->instance_id);
1680 a672b469 aliguori
        qemu_put_be32(f, se->version_id);
1681 a672b469 aliguori
1682 dc912121 Alex Williamson
        vmstate_save(f, se);
1683 a672b469 aliguori
    }
1684 a672b469 aliguori
1685 a672b469 aliguori
    qemu_put_byte(f, QEMU_VM_EOF);
1686 a672b469 aliguori
1687 624b9cc2 Juan Quintela
    return qemu_file_get_error(f);
1688 a672b469 aliguori
}
1689 a672b469 aliguori
1690 f327aa0c Jan Kiszka
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
1691 4ec7fcc7 Jan Kiszka
{
1692 4ec7fcc7 Jan Kiszka
    SaveStateEntry *se;
1693 4ec7fcc7 Jan Kiszka
1694 4ec7fcc7 Jan Kiszka
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1695 4ec7fcc7 Jan Kiszka
        if (se->save_live_state) {
1696 f327aa0c Jan Kiszka
            se->save_live_state(mon, f, -1, se->opaque);
1697 4ec7fcc7 Jan Kiszka
        }
1698 4ec7fcc7 Jan Kiszka
    }
1699 4ec7fcc7 Jan Kiszka
}
1700 4ec7fcc7 Jan Kiszka
1701 f327aa0c Jan Kiszka
static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
1702 a672b469 aliguori
{
1703 a672b469 aliguori
    int ret;
1704 a672b469 aliguori
1705 dc912121 Alex Williamson
    if (qemu_savevm_state_blocked(mon)) {
1706 dc912121 Alex Williamson
        ret = -EINVAL;
1707 dc912121 Alex Williamson
        goto out;
1708 dc912121 Alex Williamson
    }
1709 dc912121 Alex Williamson
1710 f327aa0c Jan Kiszka
    ret = qemu_savevm_state_begin(mon, f, 0, 0);
1711 a672b469 aliguori
    if (ret < 0)
1712 a672b469 aliguori
        goto out;
1713 a672b469 aliguori
1714 a672b469 aliguori
    do {
1715 f327aa0c Jan Kiszka
        ret = qemu_savevm_state_iterate(mon, f);
1716 a672b469 aliguori
        if (ret < 0)
1717 a672b469 aliguori
            goto out;
1718 a672b469 aliguori
    } while (ret == 0);
1719 a672b469 aliguori
1720 f327aa0c Jan Kiszka
    ret = qemu_savevm_state_complete(mon, f);
1721 a672b469 aliguori
1722 a672b469 aliguori
out:
1723 39346385 Juan Quintela
    if (ret == 0) {
1724 624b9cc2 Juan Quintela
        ret = qemu_file_get_error(f);
1725 39346385 Juan Quintela
    }
1726 a672b469 aliguori
1727 a672b469 aliguori
    return ret;
1728 a672b469 aliguori
}
1729 a672b469 aliguori
1730 a672b469 aliguori
static SaveStateEntry *find_se(const char *idstr, int instance_id)
1731 a672b469 aliguori
{
1732 a672b469 aliguori
    SaveStateEntry *se;
1733 a672b469 aliguori
1734 72cf2d4f Blue Swirl
    QTAILQ_FOREACH(se, &savevm_handlers, entry) {
1735 a672b469 aliguori
        if (!strcmp(se->idstr, idstr) &&
1736 4d2ffa08 Jan Kiszka
            (instance_id == se->instance_id ||
1737 4d2ffa08 Jan Kiszka
             instance_id == se->alias_id))
1738 a672b469 aliguori
            return se;
1739 7685ee6a Alex Williamson
        /* Migrating from an older version? */
1740 7685ee6a Alex Williamson
        if (strstr(se->idstr, idstr) && se->compat) {
1741 7685ee6a Alex Williamson
            if (!strcmp(se->compat->idstr, idstr) &&
1742 7685ee6a Alex Williamson
                (instance_id == se->compat->instance_id ||
1743 7685ee6a Alex Williamson
                 instance_id == se->alias_id))
1744 7685ee6a Alex Williamson
                return se;
1745 7685ee6a Alex Williamson
        }
1746 a672b469 aliguori
    }
1747 a672b469 aliguori
    return NULL;
1748 a672b469 aliguori
}
1749 a672b469 aliguori
1750 811814bd Juan Quintela
static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection *sub, char *idstr)
1751 811814bd Juan Quintela
{
1752 811814bd Juan Quintela
    while(sub && sub->needed) {
1753 811814bd Juan Quintela
        if (strcmp(idstr, sub->vmsd->name) == 0) {
1754 811814bd Juan Quintela
            return sub->vmsd;
1755 811814bd Juan Quintela
        }
1756 811814bd Juan Quintela
        sub++;
1757 811814bd Juan Quintela
    }
1758 811814bd Juan Quintela
    return NULL;
1759 811814bd Juan Quintela
}
1760 811814bd Juan Quintela
1761 811814bd Juan Quintela
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
1762 811814bd Juan Quintela
                                   void *opaque)
1763 811814bd Juan Quintela
{
1764 c6380724 Juan Quintela
    while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
1765 811814bd Juan Quintela
        char idstr[256];
1766 811814bd Juan Quintela
        int ret;
1767 c6380724 Juan Quintela
        uint8_t version_id, len, size;
1768 811814bd Juan Quintela
        const VMStateDescription *sub_vmsd;
1769 811814bd Juan Quintela
1770 c6380724 Juan Quintela
        len = qemu_peek_byte(f, 1);
1771 c6380724 Juan Quintela
        if (len < strlen(vmsd->name) + 1) {
1772 c6380724 Juan Quintela
            /* subsection name has be be "section_name/a" */
1773 c6380724 Juan Quintela
            return 0;
1774 c6380724 Juan Quintela
        }
1775 c6380724 Juan Quintela
        size = qemu_peek_buffer(f, (uint8_t *)idstr, len, 2);
1776 c6380724 Juan Quintela
        if (size != len) {
1777 c6380724 Juan Quintela
            return 0;
1778 c6380724 Juan Quintela
        }
1779 c6380724 Juan Quintela
        idstr[size] = 0;
1780 811814bd Juan Quintela
1781 c6380724 Juan Quintela
        if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
1782 c6380724 Juan Quintela
            /* it don't have a valid subsection name */
1783 c6380724 Juan Quintela
            return 0;
1784 c6380724 Juan Quintela
        }
1785 3da9eebd Juan Quintela
        sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
1786 811814bd Juan Quintela
        if (sub_vmsd == NULL) {
1787 811814bd Juan Quintela
            return -ENOENT;
1788 811814bd Juan Quintela
        }
1789 c6380724 Juan Quintela
        qemu_file_skip(f, 1); /* subsection */
1790 c6380724 Juan Quintela
        qemu_file_skip(f, 1); /* len */
1791 c6380724 Juan Quintela
        qemu_file_skip(f, len); /* idstr */
1792 c6380724 Juan Quintela
        version_id = qemu_get_be32(f);
1793 c6380724 Juan Quintela
1794 811814bd Juan Quintela
        ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
1795 811814bd Juan Quintela
        if (ret) {
1796 811814bd Juan Quintela
            return ret;
1797 811814bd Juan Quintela
        }
1798 811814bd Juan Quintela
    }
1799 811814bd Juan Quintela
    return 0;
1800 811814bd Juan Quintela
}
1801 811814bd Juan Quintela
1802 811814bd Juan Quintela
static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
1803 811814bd Juan Quintela
                                    void *opaque)
1804 811814bd Juan Quintela
{
1805 811814bd Juan Quintela
    const VMStateSubsection *sub = vmsd->subsections;
1806 811814bd Juan Quintela
1807 811814bd Juan Quintela
    while (sub && sub->needed) {
1808 811814bd Juan Quintela
        if (sub->needed(opaque)) {
1809 811814bd Juan Quintela
            const VMStateDescription *vmsd = sub->vmsd;
1810 811814bd Juan Quintela
            uint8_t len;
1811 811814bd Juan Quintela
1812 811814bd Juan Quintela
            qemu_put_byte(f, QEMU_VM_SUBSECTION);
1813 811814bd Juan Quintela
            len = strlen(vmsd->name);
1814 811814bd Juan Quintela
            qemu_put_byte(f, len);
1815 811814bd Juan Quintela
            qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
1816 811814bd Juan Quintela
            qemu_put_be32(f, vmsd->version_id);
1817 811814bd Juan Quintela
            vmstate_save_state(f, vmsd, opaque);
1818 811814bd Juan Quintela
        }
1819 811814bd Juan Quintela
        sub++;
1820 811814bd Juan Quintela
    }
1821 811814bd Juan Quintela
}
1822 811814bd Juan Quintela
1823 a672b469 aliguori
typedef struct LoadStateEntry {
1824 72cf2d4f Blue Swirl
    QLIST_ENTRY(LoadStateEntry) entry;
1825 a672b469 aliguori
    SaveStateEntry *se;
1826 a672b469 aliguori
    int section_id;
1827 a672b469 aliguori
    int version_id;
1828 a672b469 aliguori
} LoadStateEntry;
1829 a672b469 aliguori
1830 a672b469 aliguori
int qemu_loadvm_state(QEMUFile *f)
1831 a672b469 aliguori
{
1832 72cf2d4f Blue Swirl
    QLIST_HEAD(, LoadStateEntry) loadvm_handlers =
1833 72cf2d4f Blue Swirl
        QLIST_HEAD_INITIALIZER(loadvm_handlers);
1834 f4dbb8dd Juan Quintela
    LoadStateEntry *le, *new_le;
1835 a672b469 aliguori
    uint8_t section_type;
1836 a672b469 aliguori
    unsigned int v;
1837 a672b469 aliguori
    int ret;
1838 a672b469 aliguori
1839 dc912121 Alex Williamson
    if (qemu_savevm_state_blocked(default_mon)) {
1840 dc912121 Alex Williamson
        return -EINVAL;
1841 dc912121 Alex Williamson
    }
1842 dc912121 Alex Williamson
1843 a672b469 aliguori
    v = qemu_get_be32(f);
1844 a672b469 aliguori
    if (v != QEMU_VM_FILE_MAGIC)
1845 a672b469 aliguori
        return -EINVAL;
1846 a672b469 aliguori
1847 a672b469 aliguori
    v = qemu_get_be32(f);
1848 bbfe1408 Juan Quintela
    if (v == QEMU_VM_FILE_VERSION_COMPAT) {
1849 bbfe1408 Juan Quintela
        fprintf(stderr, "SaveVM v2 format is obsolete and don't work anymore\n");
1850 bbfe1408 Juan Quintela
        return -ENOTSUP;
1851 bbfe1408 Juan Quintela
    }
1852 a672b469 aliguori
    if (v != QEMU_VM_FILE_VERSION)
1853 a672b469 aliguori
        return -ENOTSUP;
1854 a672b469 aliguori
1855 a672b469 aliguori
    while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
1856 a672b469 aliguori
        uint32_t instance_id, version_id, section_id;
1857 a672b469 aliguori
        SaveStateEntry *se;
1858 a672b469 aliguori
        char idstr[257];
1859 a672b469 aliguori
        int len;
1860 a672b469 aliguori
1861 a672b469 aliguori
        switch (section_type) {
1862 a672b469 aliguori
        case QEMU_VM_SECTION_START:
1863 a672b469 aliguori
        case QEMU_VM_SECTION_FULL:
1864 a672b469 aliguori
            /* Read section start */
1865 a672b469 aliguori
            section_id = qemu_get_be32(f);
1866 a672b469 aliguori
            len = qemu_get_byte(f);
1867 a672b469 aliguori
            qemu_get_buffer(f, (uint8_t *)idstr, len);
1868 a672b469 aliguori
            idstr[len] = 0;
1869 a672b469 aliguori
            instance_id = qemu_get_be32(f);
1870 a672b469 aliguori
            version_id = qemu_get_be32(f);
1871 a672b469 aliguori
1872 a672b469 aliguori
            /* Find savevm section */
1873 a672b469 aliguori
            se = find_se(idstr, instance_id);
1874 a672b469 aliguori
            if (se == NULL) {
1875 a672b469 aliguori
                fprintf(stderr, "Unknown savevm section or instance '%s' %d\n", idstr, instance_id);
1876 a672b469 aliguori
                ret = -EINVAL;
1877 a672b469 aliguori
                goto out;
1878 a672b469 aliguori
            }
1879 a672b469 aliguori
1880 a672b469 aliguori
            /* Validate version */
1881 a672b469 aliguori
            if (version_id > se->version_id) {
1882 a672b469 aliguori
                fprintf(stderr, "savevm: unsupported version %d for '%s' v%d\n",
1883 a672b469 aliguori
                        version_id, idstr, se->version_id);
1884 a672b469 aliguori
                ret = -EINVAL;
1885 a672b469 aliguori
                goto out;
1886 a672b469 aliguori
            }
1887 a672b469 aliguori
1888 a672b469 aliguori
            /* Add entry */
1889 7267c094 Anthony Liguori
            le = g_malloc0(sizeof(*le));
1890 a672b469 aliguori
1891 a672b469 aliguori
            le->se = se;
1892 a672b469 aliguori
            le->section_id = section_id;
1893 a672b469 aliguori
            le->version_id = version_id;
1894 72cf2d4f Blue Swirl
            QLIST_INSERT_HEAD(&loadvm_handlers, le, entry);
1895 a672b469 aliguori
1896 4082be4d Juan Quintela
            ret = vmstate_load(f, le->se, le->version_id);
1897 b5a22e4a Juan Quintela
            if (ret < 0) {
1898 b5a22e4a Juan Quintela
                fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
1899 b5a22e4a Juan Quintela
                        instance_id, idstr);
1900 b5a22e4a Juan Quintela
                goto out;
1901 b5a22e4a Juan Quintela
            }
1902 a672b469 aliguori
            break;
1903 a672b469 aliguori
        case QEMU_VM_SECTION_PART:
1904 a672b469 aliguori
        case QEMU_VM_SECTION_END:
1905 a672b469 aliguori
            section_id = qemu_get_be32(f);
1906 a672b469 aliguori
1907 72cf2d4f Blue Swirl
            QLIST_FOREACH(le, &loadvm_handlers, entry) {
1908 f4dbb8dd Juan Quintela
                if (le->section_id == section_id) {
1909 f4dbb8dd Juan Quintela
                    break;
1910 f4dbb8dd Juan Quintela
                }
1911 f4dbb8dd Juan Quintela
            }
1912 a672b469 aliguori
            if (le == NULL) {
1913 a672b469 aliguori
                fprintf(stderr, "Unknown savevm section %d\n", section_id);
1914 a672b469 aliguori
                ret = -EINVAL;
1915 a672b469 aliguori
                goto out;
1916 a672b469 aliguori
            }
1917 a672b469 aliguori
1918 4082be4d Juan Quintela
            ret = vmstate_load(f, le->se, le->version_id);
1919 b5a22e4a Juan Quintela
            if (ret < 0) {
1920 b5a22e4a Juan Quintela
                fprintf(stderr, "qemu: warning: error while loading state section id %d\n",
1921 b5a22e4a Juan Quintela
                        section_id);
1922 b5a22e4a Juan Quintela
                goto out;
1923 b5a22e4a Juan Quintela
            }
1924 a672b469 aliguori
            break;
1925 a672b469 aliguori
        default:
1926 a672b469 aliguori
            fprintf(stderr, "Unknown savevm section type %d\n", section_type);
1927 a672b469 aliguori
            ret = -EINVAL;
1928 a672b469 aliguori
            goto out;
1929 a672b469 aliguori
        }
1930 a672b469 aliguori
    }
1931 a672b469 aliguori
1932 ea375f9a Jan Kiszka
    cpu_synchronize_all_post_init();
1933 ea375f9a Jan Kiszka
1934 a672b469 aliguori
    ret = 0;
1935 a672b469 aliguori
1936 a672b469 aliguori
out:
1937 72cf2d4f Blue Swirl
    QLIST_FOREACH_SAFE(le, &loadvm_handlers, entry, new_le) {
1938 72cf2d4f Blue Swirl
        QLIST_REMOVE(le, entry);
1939 7267c094 Anthony Liguori
        g_free(le);
1940 a672b469 aliguori
    }
1941 a672b469 aliguori
1942 42802d47 Juan Quintela
    if (ret == 0) {
1943 42802d47 Juan Quintela
        ret = qemu_file_get_error(f);
1944 624b9cc2 Juan Quintela
    }
1945 a672b469 aliguori
1946 a672b469 aliguori
    return ret;
1947 a672b469 aliguori
}
1948 a672b469 aliguori
1949 a672b469 aliguori
static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info,
1950 a672b469 aliguori
                              const char *name)
1951 a672b469 aliguori
{
1952 a672b469 aliguori
    QEMUSnapshotInfo *sn_tab, *sn;
1953 a672b469 aliguori
    int nb_sns, i, ret;
1954 a672b469 aliguori
1955 a672b469 aliguori
    ret = -ENOENT;
1956 a672b469 aliguori
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
1957 a672b469 aliguori
    if (nb_sns < 0)
1958 a672b469 aliguori
        return ret;
1959 a672b469 aliguori
    for(i = 0; i < nb_sns; i++) {
1960 a672b469 aliguori
        sn = &sn_tab[i];
1961 a672b469 aliguori
        if (!strcmp(sn->id_str, name) || !strcmp(sn->name, name)) {
1962 a672b469 aliguori
            *sn_info = *sn;
1963 a672b469 aliguori
            ret = 0;
1964 a672b469 aliguori
            break;
1965 a672b469 aliguori
        }
1966 a672b469 aliguori
    }
1967 7267c094 Anthony Liguori
    g_free(sn_tab);
1968 a672b469 aliguori
    return ret;
1969 a672b469 aliguori
}
1970 a672b469 aliguori
1971 cb499fb2 Kevin Wolf
/*
1972 cb499fb2 Kevin Wolf
 * Deletes snapshots of a given name in all opened images.
1973 cb499fb2 Kevin Wolf
 */
1974 cb499fb2 Kevin Wolf
static int del_existing_snapshots(Monitor *mon, const char *name)
1975 cb499fb2 Kevin Wolf
{
1976 cb499fb2 Kevin Wolf
    BlockDriverState *bs;
1977 cb499fb2 Kevin Wolf
    QEMUSnapshotInfo sn1, *snapshot = &sn1;
1978 cb499fb2 Kevin Wolf
    int ret;
1979 cb499fb2 Kevin Wolf
1980 dbc13590 Markus Armbruster
    bs = NULL;
1981 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
1982 cb499fb2 Kevin Wolf
        if (bdrv_can_snapshot(bs) &&
1983 cb499fb2 Kevin Wolf
            bdrv_snapshot_find(bs, snapshot, name) >= 0)
1984 cb499fb2 Kevin Wolf
        {
1985 cb499fb2 Kevin Wolf
            ret = bdrv_snapshot_delete(bs, name);
1986 cb499fb2 Kevin Wolf
            if (ret < 0) {
1987 cb499fb2 Kevin Wolf
                monitor_printf(mon,
1988 cb499fb2 Kevin Wolf
                               "Error while deleting snapshot on '%s'\n",
1989 cb499fb2 Kevin Wolf
                               bdrv_get_device_name(bs));
1990 cb499fb2 Kevin Wolf
                return -1;
1991 cb499fb2 Kevin Wolf
            }
1992 cb499fb2 Kevin Wolf
        }
1993 cb499fb2 Kevin Wolf
    }
1994 cb499fb2 Kevin Wolf
1995 cb499fb2 Kevin Wolf
    return 0;
1996 cb499fb2 Kevin Wolf
}
1997 cb499fb2 Kevin Wolf
1998 d54908a5 Luiz Capitulino
void do_savevm(Monitor *mon, const QDict *qdict)
1999 a672b469 aliguori
{
2000 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2001 a672b469 aliguori
    QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
2002 cb499fb2 Kevin Wolf
    int ret;
2003 a672b469 aliguori
    QEMUFile *f;
2004 a672b469 aliguori
    int saved_vm_running;
2005 2d22b18f aliguori
    uint32_t vm_state_size;
2006 a672b469 aliguori
#ifdef _WIN32
2007 a672b469 aliguori
    struct _timeb tb;
2008 7d631a11 Miguel Di Ciurcio Filho
    struct tm *ptm;
2009 a672b469 aliguori
#else
2010 a672b469 aliguori
    struct timeval tv;
2011 7d631a11 Miguel Di Ciurcio Filho
    struct tm tm;
2012 a672b469 aliguori
#endif
2013 d54908a5 Luiz Capitulino
    const char *name = qdict_get_try_str(qdict, "name");
2014 a672b469 aliguori
2015 feeee5ac Miguel Di Ciurcio Filho
    /* Verify if there is a device that doesn't support snapshots and is writable */
2016 dbc13590 Markus Armbruster
    bs = NULL;
2017 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
2018 feeee5ac Miguel Di Ciurcio Filho
2019 07b70bfb Markus Armbruster
        if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
2020 feeee5ac Miguel Di Ciurcio Filho
            continue;
2021 feeee5ac Miguel Di Ciurcio Filho
        }
2022 feeee5ac Miguel Di Ciurcio Filho
2023 feeee5ac Miguel Di Ciurcio Filho
        if (!bdrv_can_snapshot(bs)) {
2024 feeee5ac Miguel Di Ciurcio Filho
            monitor_printf(mon, "Device '%s' is writable but does not support snapshots.\n",
2025 feeee5ac Miguel Di Ciurcio Filho
                               bdrv_get_device_name(bs));
2026 feeee5ac Miguel Di Ciurcio Filho
            return;
2027 feeee5ac Miguel Di Ciurcio Filho
        }
2028 feeee5ac Miguel Di Ciurcio Filho
    }
2029 feeee5ac Miguel Di Ciurcio Filho
2030 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2031 a672b469 aliguori
    if (!bs) {
2032 376253ec aliguori
        monitor_printf(mon, "No block device can accept snapshots\n");
2033 a672b469 aliguori
        return;
2034 a672b469 aliguori
    }
2035 a672b469 aliguori
2036 1354869c Luiz Capitulino
    saved_vm_running = runstate_is_running();
2037 0461d5a6 Luiz Capitulino
    vm_stop(RUN_STATE_SAVE_VM);
2038 a672b469 aliguori
2039 cb499fb2 Kevin Wolf
    memset(sn, 0, sizeof(*sn));
2040 a672b469 aliguori
2041 a672b469 aliguori
    /* fill auxiliary fields */
2042 a672b469 aliguori
#ifdef _WIN32
2043 a672b469 aliguori
    _ftime(&tb);
2044 a672b469 aliguori
    sn->date_sec = tb.time;
2045 a672b469 aliguori
    sn->date_nsec = tb.millitm * 1000000;
2046 a672b469 aliguori
#else
2047 a672b469 aliguori
    gettimeofday(&tv, NULL);
2048 a672b469 aliguori
    sn->date_sec = tv.tv_sec;
2049 a672b469 aliguori
    sn->date_nsec = tv.tv_usec * 1000;
2050 a672b469 aliguori
#endif
2051 74475455 Paolo Bonzini
    sn->vm_clock_nsec = qemu_get_clock_ns(vm_clock);
2052 a672b469 aliguori
2053 7d631a11 Miguel Di Ciurcio Filho
    if (name) {
2054 7d631a11 Miguel Di Ciurcio Filho
        ret = bdrv_snapshot_find(bs, old_sn, name);
2055 7d631a11 Miguel Di Ciurcio Filho
        if (ret >= 0) {
2056 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->name, sizeof(sn->name), old_sn->name);
2057 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->id_str, sizeof(sn->id_str), old_sn->id_str);
2058 7d631a11 Miguel Di Ciurcio Filho
        } else {
2059 7d631a11 Miguel Di Ciurcio Filho
            pstrcpy(sn->name, sizeof(sn->name), name);
2060 7d631a11 Miguel Di Ciurcio Filho
        }
2061 7d631a11 Miguel Di Ciurcio Filho
    } else {
2062 7d631a11 Miguel Di Ciurcio Filho
#ifdef _WIN32
2063 7d631a11 Miguel Di Ciurcio Filho
        ptm = localtime(&tb.time);
2064 7d631a11 Miguel Di Ciurcio Filho
        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", ptm);
2065 7d631a11 Miguel Di Ciurcio Filho
#else
2066 d7d9b528 Blue Swirl
        /* cast below needed for OpenBSD where tv_sec is still 'long' */
2067 d7d9b528 Blue Swirl
        localtime_r((const time_t *)&tv.tv_sec, &tm);
2068 7d631a11 Miguel Di Ciurcio Filho
        strftime(sn->name, sizeof(sn->name), "vm-%Y%m%d%H%M%S", &tm);
2069 7d631a11 Miguel Di Ciurcio Filho
#endif
2070 7d631a11 Miguel Di Ciurcio Filho
    }
2071 7d631a11 Miguel Di Ciurcio Filho
2072 cb499fb2 Kevin Wolf
    /* Delete old snapshots of the same name */
2073 f139a412 Marcelo Tosatti
    if (name && del_existing_snapshots(mon, name) < 0) {
2074 cb499fb2 Kevin Wolf
        goto the_end;
2075 cb499fb2 Kevin Wolf
    }
2076 cb499fb2 Kevin Wolf
2077 a672b469 aliguori
    /* save the VM state */
2078 45566e9c Christoph Hellwig
    f = qemu_fopen_bdrv(bs, 1);
2079 a672b469 aliguori
    if (!f) {
2080 376253ec aliguori
        monitor_printf(mon, "Could not open VM state file\n");
2081 a672b469 aliguori
        goto the_end;
2082 a672b469 aliguori
    }
2083 f327aa0c Jan Kiszka
    ret = qemu_savevm_state(mon, f);
2084 2d22b18f aliguori
    vm_state_size = qemu_ftell(f);
2085 a672b469 aliguori
    qemu_fclose(f);
2086 a672b469 aliguori
    if (ret < 0) {
2087 376253ec aliguori
        monitor_printf(mon, "Error %d while writing VM\n", ret);
2088 a672b469 aliguori
        goto the_end;
2089 a672b469 aliguori
    }
2090 a672b469 aliguori
2091 a672b469 aliguori
    /* create the snapshots */
2092 a672b469 aliguori
2093 dbc13590 Markus Armbruster
    bs1 = NULL;
2094 dbc13590 Markus Armbruster
    while ((bs1 = bdrv_next(bs1))) {
2095 feeee5ac Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs1)) {
2096 2d22b18f aliguori
            /* Write VM state size only to the image that contains the state */
2097 2d22b18f aliguori
            sn->vm_state_size = (bs == bs1 ? vm_state_size : 0);
2098 a672b469 aliguori
            ret = bdrv_snapshot_create(bs1, sn);
2099 a672b469 aliguori
            if (ret < 0) {
2100 376253ec aliguori
                monitor_printf(mon, "Error while creating snapshot on '%s'\n",
2101 376253ec aliguori
                               bdrv_get_device_name(bs1));
2102 a672b469 aliguori
            }
2103 a672b469 aliguori
        }
2104 a672b469 aliguori
    }
2105 a672b469 aliguori
2106 a672b469 aliguori
 the_end:
2107 a672b469 aliguori
    if (saved_vm_running)
2108 a672b469 aliguori
        vm_start();
2109 a672b469 aliguori
}
2110 a672b469 aliguori
2111 03cd4655 Markus Armbruster
int load_vmstate(const char *name)
2112 a672b469 aliguori
{
2113 f0aa7a8b Miguel Di Ciurcio Filho
    BlockDriverState *bs, *bs_vm_state;
2114 2d22b18f aliguori
    QEMUSnapshotInfo sn;
2115 a672b469 aliguori
    QEMUFile *f;
2116 751c6a17 Gerd Hoffmann
    int ret;
2117 a672b469 aliguori
2118 f0aa7a8b Miguel Di Ciurcio Filho
    bs_vm_state = bdrv_snapshots();
2119 f0aa7a8b Miguel Di Ciurcio Filho
    if (!bs_vm_state) {
2120 f0aa7a8b Miguel Di Ciurcio Filho
        error_report("No block device supports snapshots");
2121 f0aa7a8b Miguel Di Ciurcio Filho
        return -ENOTSUP;
2122 f0aa7a8b Miguel Di Ciurcio Filho
    }
2123 f0aa7a8b Miguel Di Ciurcio Filho
2124 f0aa7a8b Miguel Di Ciurcio Filho
    /* Don't even try to load empty VM states */
2125 f0aa7a8b Miguel Di Ciurcio Filho
    ret = bdrv_snapshot_find(bs_vm_state, &sn, name);
2126 f0aa7a8b Miguel Di Ciurcio Filho
    if (ret < 0) {
2127 f0aa7a8b Miguel Di Ciurcio Filho
        return ret;
2128 f0aa7a8b Miguel Di Ciurcio Filho
    } else if (sn.vm_state_size == 0) {
2129 e11480db Kevin Wolf
        error_report("This is a disk-only snapshot. Revert to it offline "
2130 e11480db Kevin Wolf
            "using qemu-img.");
2131 f0aa7a8b Miguel Di Ciurcio Filho
        return -EINVAL;
2132 f0aa7a8b Miguel Di Ciurcio Filho
    }
2133 f0aa7a8b Miguel Di Ciurcio Filho
2134 f0aa7a8b Miguel Di Ciurcio Filho
    /* Verify if there is any device that doesn't support snapshots and is
2135 f0aa7a8b Miguel Di Ciurcio Filho
    writable and check if the requested snapshot is available too. */
2136 dbc13590 Markus Armbruster
    bs = NULL;
2137 dbc13590 Markus Armbruster
    while ((bs = bdrv_next(bs))) {
2138 feeee5ac Miguel Di Ciurcio Filho
2139 07b70bfb Markus Armbruster
        if (!bdrv_is_inserted(bs) || bdrv_is_read_only(bs)) {
2140 feeee5ac Miguel Di Ciurcio Filho
            continue;
2141 feeee5ac Miguel Di Ciurcio Filho
        }
2142 feeee5ac Miguel Di Ciurcio Filho
2143 feeee5ac Miguel Di Ciurcio Filho
        if (!bdrv_can_snapshot(bs)) {
2144 feeee5ac Miguel Di Ciurcio Filho
            error_report("Device '%s' is writable but does not support snapshots.",
2145 feeee5ac Miguel Di Ciurcio Filho
                               bdrv_get_device_name(bs));
2146 feeee5ac Miguel Di Ciurcio Filho
            return -ENOTSUP;
2147 feeee5ac Miguel Di Ciurcio Filho
        }
2148 feeee5ac Miguel Di Ciurcio Filho
2149 f0aa7a8b Miguel Di Ciurcio Filho
        ret = bdrv_snapshot_find(bs, &sn, name);
2150 f0aa7a8b Miguel Di Ciurcio Filho
        if (ret < 0) {
2151 f0aa7a8b Miguel Di Ciurcio Filho
            error_report("Device '%s' does not have the requested snapshot '%s'",
2152 f0aa7a8b Miguel Di Ciurcio Filho
                           bdrv_get_device_name(bs), name);
2153 f0aa7a8b Miguel Di Ciurcio Filho
            return ret;
2154 f0aa7a8b Miguel Di Ciurcio Filho
        }
2155 a672b469 aliguori
    }
2156 a672b469 aliguori
2157 a672b469 aliguori
    /* Flush all IO requests so they don't interfere with the new state.  */
2158 922453bc Stefan Hajnoczi
    bdrv_drain_all();
2159 a672b469 aliguori
2160 f0aa7a8b Miguel Di Ciurcio Filho
    bs = NULL;
2161 f0aa7a8b Miguel Di Ciurcio Filho
    while ((bs = bdrv_next(bs))) {
2162 f0aa7a8b Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs)) {
2163 f0aa7a8b Miguel Di Ciurcio Filho
            ret = bdrv_snapshot_goto(bs, name);
2164 a672b469 aliguori
            if (ret < 0) {
2165 f0aa7a8b Miguel Di Ciurcio Filho
                error_report("Error %d while activating snapshot '%s' on '%s'",
2166 f0aa7a8b Miguel Di Ciurcio Filho
                             ret, name, bdrv_get_device_name(bs));
2167 f0aa7a8b Miguel Di Ciurcio Filho
                return ret;
2168 a672b469 aliguori
            }
2169 a672b469 aliguori
        }
2170 a672b469 aliguori
    }
2171 a672b469 aliguori
2172 a672b469 aliguori
    /* restore the VM state */
2173 f0aa7a8b Miguel Di Ciurcio Filho
    f = qemu_fopen_bdrv(bs_vm_state, 0);
2174 a672b469 aliguori
    if (!f) {
2175 1ecda02b Markus Armbruster
        error_report("Could not open VM state file");
2176 05f2401e Juan Quintela
        return -EINVAL;
2177 a672b469 aliguori
    }
2178 f0aa7a8b Miguel Di Ciurcio Filho
2179 5a8a49d7 Jan Kiszka
    qemu_system_reset(VMRESET_SILENT);
2180 a672b469 aliguori
    ret = qemu_loadvm_state(f);
2181 f0aa7a8b Miguel Di Ciurcio Filho
2182 a672b469 aliguori
    qemu_fclose(f);
2183 a672b469 aliguori
    if (ret < 0) {
2184 1ecda02b Markus Armbruster
        error_report("Error %d while loading VM state", ret);
2185 05f2401e Juan Quintela
        return ret;
2186 a672b469 aliguori
    }
2187 f0aa7a8b Miguel Di Ciurcio Filho
2188 05f2401e Juan Quintela
    return 0;
2189 7b630349 Juan Quintela
}
2190 7b630349 Juan Quintela
2191 d54908a5 Luiz Capitulino
void do_delvm(Monitor *mon, const QDict *qdict)
2192 a672b469 aliguori
{
2193 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2194 751c6a17 Gerd Hoffmann
    int ret;
2195 d54908a5 Luiz Capitulino
    const char *name = qdict_get_str(qdict, "name");
2196 a672b469 aliguori
2197 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2198 a672b469 aliguori
    if (!bs) {
2199 376253ec aliguori
        monitor_printf(mon, "No block device supports snapshots\n");
2200 a672b469 aliguori
        return;
2201 a672b469 aliguori
    }
2202 a672b469 aliguori
2203 dbc13590 Markus Armbruster
    bs1 = NULL;
2204 dbc13590 Markus Armbruster
    while ((bs1 = bdrv_next(bs1))) {
2205 feeee5ac Miguel Di Ciurcio Filho
        if (bdrv_can_snapshot(bs1)) {
2206 a672b469 aliguori
            ret = bdrv_snapshot_delete(bs1, name);
2207 a672b469 aliguori
            if (ret < 0) {
2208 a672b469 aliguori
                if (ret == -ENOTSUP)
2209 376253ec aliguori
                    monitor_printf(mon,
2210 376253ec aliguori
                                   "Snapshots not supported on device '%s'\n",
2211 376253ec aliguori
                                   bdrv_get_device_name(bs1));
2212 a672b469 aliguori
                else
2213 376253ec aliguori
                    monitor_printf(mon, "Error %d while deleting snapshot on "
2214 376253ec aliguori
                                   "'%s'\n", ret, bdrv_get_device_name(bs1));
2215 a672b469 aliguori
            }
2216 a672b469 aliguori
        }
2217 a672b469 aliguori
    }
2218 a672b469 aliguori
}
2219 a672b469 aliguori
2220 376253ec aliguori
void do_info_snapshots(Monitor *mon)
2221 a672b469 aliguori
{
2222 a672b469 aliguori
    BlockDriverState *bs, *bs1;
2223 f9209915 Miguel Di Ciurcio Filho
    QEMUSnapshotInfo *sn_tab, *sn, s, *sn_info = &s;
2224 f9209915 Miguel Di Ciurcio Filho
    int nb_sns, i, ret, available;
2225 f9209915 Miguel Di Ciurcio Filho
    int total;
2226 f9209915 Miguel Di Ciurcio Filho
    int *available_snapshots;
2227 a672b469 aliguori
    char buf[256];
2228 a672b469 aliguori
2229 f9092b10 Markus Armbruster
    bs = bdrv_snapshots();
2230 a672b469 aliguori
    if (!bs) {
2231 376253ec aliguori
        monitor_printf(mon, "No available block device supports snapshots\n");
2232 a672b469 aliguori
        return;
2233 a672b469 aliguori
    }
2234 a672b469 aliguori
2235 a672b469 aliguori
    nb_sns = bdrv_snapshot_list(bs, &sn_tab);
2236 a672b469 aliguori
    if (nb_sns < 0) {
2237 376253ec aliguori
        monitor_printf(mon, "bdrv_snapshot_list: error %d\n", nb_sns);
2238 a672b469 aliguori
        return;
2239 a672b469 aliguori
    }
2240 f9209915 Miguel Di Ciurcio Filho
2241 f9209915 Miguel Di Ciurcio Filho
    if (nb_sns == 0) {
2242 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "There is no snapshot available.\n");
2243 f9209915 Miguel Di Ciurcio Filho
        return;
2244 f9209915 Miguel Di Ciurcio Filho
    }
2245 f9209915 Miguel Di Ciurcio Filho
2246 7267c094 Anthony Liguori
    available_snapshots = g_malloc0(sizeof(int) * nb_sns);
2247 f9209915 Miguel Di Ciurcio Filho
    total = 0;
2248 f9209915 Miguel Di Ciurcio Filho
    for (i = 0; i < nb_sns; i++) {
2249 a672b469 aliguori
        sn = &sn_tab[i];
2250 f9209915 Miguel Di Ciurcio Filho
        available = 1;
2251 f9209915 Miguel Di Ciurcio Filho
        bs1 = NULL;
2252 f9209915 Miguel Di Ciurcio Filho
2253 f9209915 Miguel Di Ciurcio Filho
        while ((bs1 = bdrv_next(bs1))) {
2254 f9209915 Miguel Di Ciurcio Filho
            if (bdrv_can_snapshot(bs1) && bs1 != bs) {
2255 f9209915 Miguel Di Ciurcio Filho
                ret = bdrv_snapshot_find(bs1, sn_info, sn->id_str);
2256 f9209915 Miguel Di Ciurcio Filho
                if (ret < 0) {
2257 f9209915 Miguel Di Ciurcio Filho
                    available = 0;
2258 f9209915 Miguel Di Ciurcio Filho
                    break;
2259 f9209915 Miguel Di Ciurcio Filho
                }
2260 f9209915 Miguel Di Ciurcio Filho
            }
2261 f9209915 Miguel Di Ciurcio Filho
        }
2262 f9209915 Miguel Di Ciurcio Filho
2263 f9209915 Miguel Di Ciurcio Filho
        if (available) {
2264 f9209915 Miguel Di Ciurcio Filho
            available_snapshots[total] = i;
2265 f9209915 Miguel Di Ciurcio Filho
            total++;
2266 f9209915 Miguel Di Ciurcio Filho
        }
2267 a672b469 aliguori
    }
2268 f9209915 Miguel Di Ciurcio Filho
2269 f9209915 Miguel Di Ciurcio Filho
    if (total > 0) {
2270 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), NULL));
2271 f9209915 Miguel Di Ciurcio Filho
        for (i = 0; i < total; i++) {
2272 f9209915 Miguel Di Ciurcio Filho
            sn = &sn_tab[available_snapshots[i]];
2273 f9209915 Miguel Di Ciurcio Filho
            monitor_printf(mon, "%s\n", bdrv_snapshot_dump(buf, sizeof(buf), sn));
2274 f9209915 Miguel Di Ciurcio Filho
        }
2275 f9209915 Miguel Di Ciurcio Filho
    } else {
2276 f9209915 Miguel Di Ciurcio Filho
        monitor_printf(mon, "There is no suitable snapshot available\n");
2277 f9209915 Miguel Di Ciurcio Filho
    }
2278 f9209915 Miguel Di Ciurcio Filho
2279 7267c094 Anthony Liguori
    g_free(sn_tab);
2280 7267c094 Anthony Liguori
    g_free(available_snapshots);
2281 f9209915 Miguel Di Ciurcio Filho
2282 a672b469 aliguori
}