Annotation of qemu/migration.c, revision 1.1.1.2

1.1       root        1: /*
                      2:  * QEMU live migration
                      3:  *
                      4:  * Copyright IBM, Corp. 2008
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <aliguori@us.ibm.com>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU GPL, version 2.  See
                     10:  * the COPYING file in the top-level directory.
                     11:  *
                     12:  */
                     13: 
                     14: #include "qemu-common.h"
                     15: #include "migration.h"
                     16: #include "console.h"
                     17: #include "buffered_file.h"
                     18: #include "sysemu.h"
                     19: #include "block.h"
                     20: #include "qemu_socket.h"
                     21: 
                     22: //#define DEBUG_MIGRATION
                     23: 
                     24: #ifdef DEBUG_MIGRATION
                     25: #define dprintf(fmt, ...) \
                     26:     do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
                     27: #else
                     28: #define dprintf(fmt, ...) \
                     29:     do { } while (0)
                     30: #endif
                     31: 
                     32: /* Migration speed throttling */
                     33: static uint32_t max_throttle = (32 << 20);
                     34: 
                     35: static MigrationState *current_migration;
                     36: 
                     37: void qemu_start_incoming_migration(const char *uri)
                     38: {
                     39:     const char *p;
                     40: 
                     41:     if (strstart(uri, "tcp:", &p))
                     42:         tcp_start_incoming_migration(p);
                     43: #if !defined(WIN32)
                     44:     else if (strstart(uri, "exec:", &p))
                     45:         exec_start_incoming_migration(p);
                     46: #endif
                     47:     else
                     48:         fprintf(stderr, "unknown migration protocol: %s\n", uri);
                     49: }
                     50: 
                     51: void do_migrate(int detach, const char *uri)
                     52: {
                     53:     MigrationState *s = NULL;
                     54:     const char *p;
                     55: 
                     56:     if (strstart(uri, "tcp:", &p))
                     57:         s = tcp_start_outgoing_migration(p, max_throttle, detach);
                     58: #if !defined(WIN32)
                     59:     else if (strstart(uri, "exec:", &p))
                     60:         s = exec_start_outgoing_migration(p, max_throttle, detach);
                     61: #endif
                     62:     else
                     63:         term_printf("unknown migration protocol: %s\n", uri);
                     64: 
                     65:     if (s == NULL)
                     66:         term_printf("migration failed\n");
                     67:     else {
                     68:         if (current_migration)
                     69:             current_migration->release(current_migration);
                     70: 
                     71:         current_migration = s;
                     72:     }
                     73: }
                     74: 
                     75: void do_migrate_cancel(void)
                     76: {
                     77:     MigrationState *s = current_migration;
                     78: 
                     79:     if (s)
                     80:         s->cancel(s);
                     81: }
                     82: 
                     83: void do_migrate_set_speed(const char *value)
                     84: {
                     85:     double d;
                     86:     char *ptr;
                     87: 
                     88:     d = strtod(value, &ptr);
                     89:     switch (*ptr) {
                     90:     case 'G': case 'g':
                     91:         d *= 1024;
                     92:     case 'M': case 'm':
                     93:         d *= 1024;
                     94:     case 'K': case 'k':
                     95:         d *= 1024;
                     96:     default:
                     97:         break;
                     98:     }
                     99: 
                    100:     max_throttle = (uint32_t)d;
                    101: }
                    102: 
                    103: void do_info_migrate(void)
                    104: {
                    105:     MigrationState *s = current_migration;
                    106:     
                    107:     if (s) {
                    108:         term_printf("Migration status: ");
                    109:         switch (s->get_status(s)) {
                    110:         case MIG_STATE_ACTIVE:
                    111:             term_printf("active\n");
                    112:             break;
                    113:         case MIG_STATE_COMPLETED:
                    114:             term_printf("completed\n");
                    115:             break;
                    116:         case MIG_STATE_ERROR:
                    117:             term_printf("failed\n");
                    118:             break;
                    119:         case MIG_STATE_CANCELLED:
                    120:             term_printf("cancelled\n");
                    121:             break;
                    122:         }
                    123:     }
                    124: }
                    125: 
                    126: /* shared migration helpers */
                    127: 
                    128: void migrate_fd_error(FdMigrationState *s)
                    129: {
                    130:     dprintf("setting error state\n");
                    131:     s->state = MIG_STATE_ERROR;
                    132:     migrate_fd_cleanup(s);
                    133: }
                    134: 
                    135: void migrate_fd_cleanup(FdMigrationState *s)
                    136: {
                    137:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
                    138: 
                    139:     if (s->file) {
                    140:         dprintf("closing file\n");
                    141:         qemu_fclose(s->file);
                    142:     }
                    143: 
                    144:     if (s->fd != -1)
                    145:         close(s->fd);
                    146: 
                    147:     /* Don't resume monitor until we've flushed all of the buffers */
                    148:     if (s->detach == 2) {
                    149:         monitor_resume();
                    150:         s->detach = 0;
                    151:     }
                    152: 
                    153:     s->fd = -1;
                    154: }
                    155: 
                    156: void migrate_fd_put_notify(void *opaque)
                    157: {
                    158:     FdMigrationState *s = opaque;
                    159: 
                    160:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
                    161:     qemu_file_put_notify(s->file);
                    162: }
                    163: 
                    164: ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
                    165: {
                    166:     FdMigrationState *s = opaque;
                    167:     ssize_t ret;
                    168: 
                    169:     do {
                    170:         ret = s->write(s, data, size);
                    171:     } while (ret == -1 && ((s->get_error(s)) == EINTR || (s->get_error(s)) == EWOULDBLOCK));
                    172: 
                    173:     if (ret == -1)
                    174:         ret = -(s->get_error(s));
                    175: 
                    176:     if (ret == -EAGAIN)
                    177:         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
                    178: 
                    179:     return ret;
                    180: }
                    181: 
                    182: void migrate_fd_connect(FdMigrationState *s)
                    183: {
                    184:     int ret;
                    185: 
                    186:     s->file = qemu_fopen_ops_buffered(s,
                    187:                                       s->bandwidth_limit,
                    188:                                       migrate_fd_put_buffer,
                    189:                                       migrate_fd_put_ready,
                    190:                                       migrate_fd_wait_for_unfreeze,
                    191:                                       migrate_fd_close);
                    192: 
                    193:     dprintf("beginning savevm\n");
                    194:     ret = qemu_savevm_state_begin(s->file);
                    195:     if (ret < 0) {
                    196:         dprintf("failed, %d\n", ret);
                    197:         migrate_fd_error(s);
                    198:         return;
                    199:     }
                    200: 
                    201:     migrate_fd_put_ready(s);
                    202: }
                    203: 
                    204: void migrate_fd_put_ready(void *opaque)
                    205: {
                    206:     FdMigrationState *s = opaque;
                    207: 
                    208:     if (s->state != MIG_STATE_ACTIVE) {
                    209:         dprintf("put_ready returning because of non-active state\n");
                    210:         return;
                    211:     }
                    212: 
                    213:     dprintf("iterate\n");
                    214:     if (qemu_savevm_state_iterate(s->file) == 1) {
1.1.1.2 ! root      215:         int state;
1.1       root      216:         dprintf("done iterating\n");
                    217:         vm_stop(0);
                    218: 
                    219:         bdrv_flush_all();
1.1.1.2 ! root      220:         if ((qemu_savevm_state_complete(s->file)) < 0) {
        !           221:             vm_start();
        !           222:             state = MIG_STATE_ERROR;
        !           223:         } else {
        !           224:             state = MIG_STATE_COMPLETED;
        !           225:         }
1.1       root      226:         migrate_fd_cleanup(s);
1.1.1.2 ! root      227:         s->state = state;
1.1       root      228:     }
                    229: }
                    230: 
                    231: int migrate_fd_get_status(MigrationState *mig_state)
                    232: {
                    233:     FdMigrationState *s = migrate_to_fms(mig_state);
                    234:     return s->state;
                    235: }
                    236: 
                    237: void migrate_fd_cancel(MigrationState *mig_state)
                    238: {
                    239:     FdMigrationState *s = migrate_to_fms(mig_state);
                    240: 
                    241:     if (s->state != MIG_STATE_ACTIVE)
                    242:         return;
                    243: 
                    244:     dprintf("cancelling migration\n");
                    245: 
                    246:     s->state = MIG_STATE_CANCELLED;
                    247: 
                    248:     migrate_fd_cleanup(s);
                    249: }
                    250: 
                    251: void migrate_fd_release(MigrationState *mig_state)
                    252: {
                    253:     FdMigrationState *s = migrate_to_fms(mig_state);
                    254: 
                    255:     dprintf("releasing state\n");
                    256:    
                    257:     if (s->state == MIG_STATE_ACTIVE) {
                    258:         s->state = MIG_STATE_CANCELLED;
                    259:         migrate_fd_cleanup(s);
                    260:     }
                    261:     free(s);
                    262: }
                    263: 
                    264: void migrate_fd_wait_for_unfreeze(void *opaque)
                    265: {
                    266:     FdMigrationState *s = opaque;
                    267:     int ret;
                    268: 
                    269:     dprintf("wait for unfreeze\n");
                    270:     if (s->state != MIG_STATE_ACTIVE)
                    271:         return;
                    272: 
                    273:     do {
                    274:         fd_set wfds;
                    275: 
                    276:         FD_ZERO(&wfds);
                    277:         FD_SET(s->fd, &wfds);
                    278: 
                    279:         ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
                    280:     } while (ret == -1 && (s->get_error(s)) == EINTR);
                    281: }
                    282: 
                    283: int migrate_fd_close(void *opaque)
                    284: {
                    285:     FdMigrationState *s = opaque;
                    286:     return s->close(s);
                    287: }

unix.superglobalmegacorp.com