Annotation of qemu/savevm.c, revision 1.1.1.4

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

unix.superglobalmegacorp.com