File:  [Qemu by Fabrice Bellard] / qemu / migration.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:02:11 2018 UTC (3 years, 5 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu0104, qemu0103, qemu0102, HEAD
qemu 0.10.2

    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) {
  215:         int state;
  216:         dprintf("done iterating\n");
  217:         vm_stop(0);
  218: 
  219:         bdrv_flush_all();
  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:         }
  226:         migrate_fd_cleanup(s);
  227:         s->state = state;
  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