File:  [Qemu by Fabrice Bellard] / qemu / migration.c
Revision 1.1.1.7 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:34:31 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0150, qemu0141, qemu0140, HEAD
qemu 0.14.0

    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 "monitor.h"
   17: #include "buffered_file.h"
   18: #include "sysemu.h"
   19: #include "block.h"
   20: #include "qemu_socket.h"
   21: #include "block-migration.h"
   22: #include "qemu-objects.h"
   23: 
   24: //#define DEBUG_MIGRATION
   25: 
   26: #ifdef DEBUG_MIGRATION
   27: #define DPRINTF(fmt, ...) \
   28:     do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
   29: #else
   30: #define DPRINTF(fmt, ...) \
   31:     do { } while (0)
   32: #endif
   33: 
   34: /* Migration speed throttling */
   35: static int64_t max_throttle = (32 << 20);
   36: 
   37: static MigrationState *current_migration;
   38: 
   39: static NotifierList migration_state_notifiers =
   40:     NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
   41: 
   42: int qemu_start_incoming_migration(const char *uri)
   43: {
   44:     const char *p;
   45:     int ret;
   46: 
   47:     if (strstart(uri, "tcp:", &p))
   48:         ret = tcp_start_incoming_migration(p);
   49: #if !defined(WIN32)
   50:     else if (strstart(uri, "exec:", &p))
   51:         ret =  exec_start_incoming_migration(p);
   52:     else if (strstart(uri, "unix:", &p))
   53:         ret = unix_start_incoming_migration(p);
   54:     else if (strstart(uri, "fd:", &p))
   55:         ret = fd_start_incoming_migration(p);
   56: #endif
   57:     else {
   58:         fprintf(stderr, "unknown migration protocol: %s\n", uri);
   59:         ret = -EPROTONOSUPPORT;
   60:     }
   61:     return ret;
   62: }
   63: 
   64: void process_incoming_migration(QEMUFile *f)
   65: {
   66:     if (qemu_loadvm_state(f) < 0) {
   67:         fprintf(stderr, "load of migration failed\n");
   68:         exit(0);
   69:     }
   70:     qemu_announce_self();
   71:     DPRINTF("successfully loaded vm state\n");
   72: 
   73:     incoming_expected = false;
   74: 
   75:     if (autostart)
   76:         vm_start();
   77: }
   78: 
   79: int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
   80: {
   81:     MigrationState *s = NULL;
   82:     const char *p;
   83:     int detach = qdict_get_try_bool(qdict, "detach", 0);
   84:     int blk = qdict_get_try_bool(qdict, "blk", 0);
   85:     int inc = qdict_get_try_bool(qdict, "inc", 0);
   86:     const char *uri = qdict_get_str(qdict, "uri");
   87: 
   88:     if (current_migration &&
   89:         current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
   90:         monitor_printf(mon, "migration already in progress\n");
   91:         return -1;
   92:     }
   93: 
   94:     if (qemu_savevm_state_blocked(mon)) {
   95:         return -1;
   96:     }
   97: 
   98:     if (strstart(uri, "tcp:", &p)) {
   99:         s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
  100:                                          blk, inc);
  101: #if !defined(WIN32)
  102:     } else if (strstart(uri, "exec:", &p)) {
  103:         s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
  104:                                           blk, inc);
  105:     } else if (strstart(uri, "unix:", &p)) {
  106:         s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
  107:                                           blk, inc);
  108:     } else if (strstart(uri, "fd:", &p)) {
  109:         s = fd_start_outgoing_migration(mon, p, max_throttle, detach, 
  110:                                         blk, inc);
  111: #endif
  112:     } else {
  113:         monitor_printf(mon, "unknown migration protocol: %s\n", uri);
  114:         return -1;
  115:     }
  116: 
  117:     if (s == NULL) {
  118:         monitor_printf(mon, "migration failed\n");
  119:         return -1;
  120:     }
  121: 
  122:     if (current_migration) {
  123:         current_migration->release(current_migration);
  124:     }
  125: 
  126:     current_migration = s;
  127:     notifier_list_notify(&migration_state_notifiers);
  128:     return 0;
  129: }
  130: 
  131: int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
  132: {
  133:     MigrationState *s = current_migration;
  134: 
  135:     if (s)
  136:         s->cancel(s);
  137: 
  138:     return 0;
  139: }
  140: 
  141: int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
  142: {
  143:     int64_t d;
  144:     FdMigrationState *s;
  145: 
  146:     d = qdict_get_int(qdict, "value");
  147:     if (d < 0) {
  148:         d = 0;
  149:     }
  150:     max_throttle = d;
  151: 
  152:     s = migrate_to_fms(current_migration);
  153:     if (s && s->file) {
  154:         qemu_file_set_rate_limit(s->file, max_throttle);
  155:     }
  156: 
  157:     return 0;
  158: }
  159: 
  160: /* amount of nanoseconds we are willing to wait for migration to be down.
  161:  * the choice of nanoseconds is because it is the maximum resolution that
  162:  * get_clock() can achieve. It is an internal measure. All user-visible
  163:  * units must be in seconds */
  164: static uint64_t max_downtime = 30000000;
  165: 
  166: uint64_t migrate_max_downtime(void)
  167: {
  168:     return max_downtime;
  169: }
  170: 
  171: int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
  172:                             QObject **ret_data)
  173: {
  174:     double d;
  175: 
  176:     d = qdict_get_double(qdict, "value") * 1e9;
  177:     d = MAX(0, MIN(UINT64_MAX, d));
  178:     max_downtime = (uint64_t)d;
  179: 
  180:     return 0;
  181: }
  182: 
  183: static void migrate_print_status(Monitor *mon, const char *name,
  184:                                  const QDict *status_dict)
  185: {
  186:     QDict *qdict;
  187: 
  188:     qdict = qobject_to_qdict(qdict_get(status_dict, name));
  189: 
  190:     monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name,
  191:                         qdict_get_int(qdict, "transferred") >> 10);
  192:     monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name,
  193:                         qdict_get_int(qdict, "remaining") >> 10);
  194:     monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name,
  195:                         qdict_get_int(qdict, "total") >> 10);
  196: }
  197: 
  198: void do_info_migrate_print(Monitor *mon, const QObject *data)
  199: {
  200:     QDict *qdict;
  201: 
  202:     qdict = qobject_to_qdict(data);
  203: 
  204:     monitor_printf(mon, "Migration status: %s\n",
  205:                    qdict_get_str(qdict, "status"));
  206: 
  207:     if (qdict_haskey(qdict, "ram")) {
  208:         migrate_print_status(mon, "ram", qdict);
  209:     }
  210: 
  211:     if (qdict_haskey(qdict, "disk")) {
  212:         migrate_print_status(mon, "disk", qdict);
  213:     }
  214: }
  215: 
  216: static void migrate_put_status(QDict *qdict, const char *name,
  217:                                uint64_t trans, uint64_t rem, uint64_t total)
  218: {
  219:     QObject *obj;
  220: 
  221:     obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "
  222:                                "'remaining': %" PRId64 ", "
  223:                                "'total': %" PRId64 " }", trans, rem, total);
  224:     qdict_put_obj(qdict, name, obj);
  225: }
  226: 
  227: void do_info_migrate(Monitor *mon, QObject **ret_data)
  228: {
  229:     QDict *qdict;
  230:     MigrationState *s = current_migration;
  231: 
  232:     if (s) {
  233:         switch (s->get_status(s)) {
  234:         case MIG_STATE_ACTIVE:
  235:             qdict = qdict_new();
  236:             qdict_put(qdict, "status", qstring_from_str("active"));
  237: 
  238:             migrate_put_status(qdict, "ram", ram_bytes_transferred(),
  239:                                ram_bytes_remaining(), ram_bytes_total());
  240: 
  241:             if (blk_mig_active()) {
  242:                 migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
  243:                                    blk_mig_bytes_remaining(),
  244:                                    blk_mig_bytes_total());
  245:             }
  246: 
  247:             *ret_data = QOBJECT(qdict);
  248:             break;
  249:         case MIG_STATE_COMPLETED:
  250:             *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
  251:             break;
  252:         case MIG_STATE_ERROR:
  253:             *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
  254:             break;
  255:         case MIG_STATE_CANCELLED:
  256:             *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
  257:             break;
  258:         }
  259:     }
  260: }
  261: 
  262: /* shared migration helpers */
  263: 
  264: void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
  265: {
  266:     s->mon = mon;
  267:     if (monitor_suspend(mon) == 0) {
  268:         DPRINTF("suspending monitor\n");
  269:     } else {
  270:         monitor_printf(mon, "terminal does not allow synchronous "
  271:                        "migration, continuing detached\n");
  272:     }
  273: }
  274: 
  275: void migrate_fd_error(FdMigrationState *s)
  276: {
  277:     DPRINTF("setting error state\n");
  278:     s->state = MIG_STATE_ERROR;
  279:     notifier_list_notify(&migration_state_notifiers);
  280:     migrate_fd_cleanup(s);
  281: }
  282: 
  283: int migrate_fd_cleanup(FdMigrationState *s)
  284: {
  285:     int ret = 0;
  286: 
  287:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
  288: 
  289:     if (s->file) {
  290:         DPRINTF("closing file\n");
  291:         if (qemu_fclose(s->file) != 0) {
  292:             ret = -1;
  293:         }
  294:         s->file = NULL;
  295:     }
  296: 
  297:     if (s->fd != -1)
  298:         close(s->fd);
  299: 
  300:     /* Don't resume monitor until we've flushed all of the buffers */
  301:     if (s->mon) {
  302:         monitor_resume(s->mon);
  303:     }
  304: 
  305:     s->fd = -1;
  306: 
  307:     return ret;
  308: }
  309: 
  310: void migrate_fd_put_notify(void *opaque)
  311: {
  312:     FdMigrationState *s = opaque;
  313: 
  314:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
  315:     qemu_file_put_notify(s->file);
  316: }
  317: 
  318: ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
  319: {
  320:     FdMigrationState *s = opaque;
  321:     ssize_t ret;
  322: 
  323:     do {
  324:         ret = s->write(s, data, size);
  325:     } while (ret == -1 && ((s->get_error(s)) == EINTR));
  326: 
  327:     if (ret == -1)
  328:         ret = -(s->get_error(s));
  329: 
  330:     if (ret == -EAGAIN) {
  331:         qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
  332:     } else if (ret < 0) {
  333:         if (s->mon) {
  334:             monitor_resume(s->mon);
  335:         }
  336:         s->state = MIG_STATE_ERROR;
  337:         notifier_list_notify(&migration_state_notifiers);
  338:     }
  339: 
  340:     return ret;
  341: }
  342: 
  343: void migrate_fd_connect(FdMigrationState *s)
  344: {
  345:     int ret;
  346: 
  347:     s->file = qemu_fopen_ops_buffered(s,
  348:                                       s->bandwidth_limit,
  349:                                       migrate_fd_put_buffer,
  350:                                       migrate_fd_put_ready,
  351:                                       migrate_fd_wait_for_unfreeze,
  352:                                       migrate_fd_close);
  353: 
  354:     DPRINTF("beginning savevm\n");
  355:     ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
  356:                                   s->mig_state.shared);
  357:     if (ret < 0) {
  358:         DPRINTF("failed, %d\n", ret);
  359:         migrate_fd_error(s);
  360:         return;
  361:     }
  362:     
  363:     migrate_fd_put_ready(s);
  364: }
  365: 
  366: void migrate_fd_put_ready(void *opaque)
  367: {
  368:     FdMigrationState *s = opaque;
  369: 
  370:     if (s->state != MIG_STATE_ACTIVE) {
  371:         DPRINTF("put_ready returning because of non-active state\n");
  372:         return;
  373:     }
  374: 
  375:     DPRINTF("iterate\n");
  376:     if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
  377:         int state;
  378:         int old_vm_running = vm_running;
  379: 
  380:         DPRINTF("done iterating\n");
  381:         vm_stop(0);
  382: 
  383:         if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
  384:             if (old_vm_running) {
  385:                 vm_start();
  386:             }
  387:             state = MIG_STATE_ERROR;
  388:         } else {
  389:             state = MIG_STATE_COMPLETED;
  390:         }
  391:         if (migrate_fd_cleanup(s) < 0) {
  392:             if (old_vm_running) {
  393:                 vm_start();
  394:             }
  395:             state = MIG_STATE_ERROR;
  396:         }
  397:         s->state = state;
  398:         notifier_list_notify(&migration_state_notifiers);
  399:     }
  400: }
  401: 
  402: int migrate_fd_get_status(MigrationState *mig_state)
  403: {
  404:     FdMigrationState *s = migrate_to_fms(mig_state);
  405:     return s->state;
  406: }
  407: 
  408: void migrate_fd_cancel(MigrationState *mig_state)
  409: {
  410:     FdMigrationState *s = migrate_to_fms(mig_state);
  411: 
  412:     if (s->state != MIG_STATE_ACTIVE)
  413:         return;
  414: 
  415:     DPRINTF("cancelling migration\n");
  416: 
  417:     s->state = MIG_STATE_CANCELLED;
  418:     notifier_list_notify(&migration_state_notifiers);
  419:     qemu_savevm_state_cancel(s->mon, s->file);
  420: 
  421:     migrate_fd_cleanup(s);
  422: }
  423: 
  424: void migrate_fd_release(MigrationState *mig_state)
  425: {
  426:     FdMigrationState *s = migrate_to_fms(mig_state);
  427: 
  428:     DPRINTF("releasing state\n");
  429:    
  430:     if (s->state == MIG_STATE_ACTIVE) {
  431:         s->state = MIG_STATE_CANCELLED;
  432:         notifier_list_notify(&migration_state_notifiers);
  433:         migrate_fd_cleanup(s);
  434:     }
  435:     qemu_free(s);
  436: }
  437: 
  438: void migrate_fd_wait_for_unfreeze(void *opaque)
  439: {
  440:     FdMigrationState *s = opaque;
  441:     int ret;
  442: 
  443:     DPRINTF("wait for unfreeze\n");
  444:     if (s->state != MIG_STATE_ACTIVE)
  445:         return;
  446: 
  447:     do {
  448:         fd_set wfds;
  449: 
  450:         FD_ZERO(&wfds);
  451:         FD_SET(s->fd, &wfds);
  452: 
  453:         ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
  454:     } while (ret == -1 && (s->get_error(s)) == EINTR);
  455: }
  456: 
  457: int migrate_fd_close(void *opaque)
  458: {
  459:     FdMigrationState *s = opaque;
  460: 
  461:     qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
  462:     return s->close(s);
  463: }
  464: 
  465: void add_migration_state_change_notifier(Notifier *notify)
  466: {
  467:     notifier_list_add(&migration_state_notifiers, notify);
  468: }
  469: 
  470: void remove_migration_state_change_notifier(Notifier *notify)
  471: {
  472:     notifier_list_remove(&migration_state_notifiers, notify);
  473: }
  474: 
  475: int get_migration_state(void)
  476: {
  477:     if (current_migration) {
  478:         return migrate_fd_get_status(current_migration);
  479:     } else {
  480:         return MIG_STATE_ERROR;
  481:     }
  482: }

unix.superglobalmegacorp.com