15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU live migration 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright IBM, Corp. 2008 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Authors: 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Anthony Liguori <aliguori@us.ibm.com> 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This work is licensed under the terms of the GNU GPL, version 2. See 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the COPYING file in the top-level directory. 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "migration.h" 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h" 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "buffered_file.h" 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h" 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "block.h" 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu_socket.h" 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner//#define DEBUG_MIGRATION 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_MIGRATION 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define dprintf(fmt, ...) \ 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { printf("migration: " fmt, ## __VA_ARGS__); } while (0) 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define dprintf(fmt, ...) \ 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { } while (0) 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Migration speed throttling */ 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint32_t max_throttle = (32 << 20); 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic MigrationState *current_migration; 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_start_incoming_migration(const char *uri) 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(uri, "tcp:", &p)) 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tcp_start_incoming_migration(p); 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if !defined(WIN32) 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strstart(uri, "exec:", &p)) 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exec_start_incoming_migration(p); 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "unknown migration protocol: %s\n", uri); 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_migrate(Monitor *mon, int detach, const char *uri) 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MigrationState *s = NULL; 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strstart(uri, "tcp:", &p)) 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = tcp_start_outgoing_migration(p, max_throttle, detach); 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if !defined(WIN32) 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strstart(uri, "exec:", &p)) 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = exec_start_outgoing_migration(p, max_throttle, detach); 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "unknown migration protocol: %s\n", uri); 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s == NULL) 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "migration failed\n"); 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else { 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (current_migration) 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner current_migration->release(current_migration); 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner current_migration = s; 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_migrate_cancel(Monitor *mon) 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MigrationState *s = current_migration; 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s) 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->cancel(s); 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_migrate_set_speed(Monitor *mon, const char *value) 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner double d; 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *ptr; 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s; 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d = strtod(value, &ptr); 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (*ptr) { 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'G': case 'g': 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1024; 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'M': case 'm': 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1024; 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 'K': case 'k': 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1024; 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max_throttle = (uint32_t)d; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = migrate_to_fms(current_migration); 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s) { 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_file_set_rate_limit(s->file, max_throttle); 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* amount of nanoseconds we are willing to wait for migration to be down. 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * the choice of nanoseconds is because it is the maximum resolution that 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * get_clock() can achieve. It is an internal measure. All user-visible 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * units must be in seconds */ 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic uint64_t max_downtime = 30000000; 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turneruint64_t migrate_max_downtime(void) 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return max_downtime; 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_migrate_set_downtime(Monitor *mon, const char *value) 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *ptr; 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner double d; 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d = strtod(value, &ptr); 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(ptr,"ms")) { 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1000000; 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (!strcmp(ptr,"us")) { 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1000; 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (!strcmp(ptr,"ns")) { 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* all else considered to be seconds */ 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner d *= 1000000000; 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max_downtime = (uint64_t)d; 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_info_migrate(Monitor *mon) 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner MigrationState *s = current_migration; 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s) { 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "Migration status: "); 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch (s->get_status(s)) { 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case MIG_STATE_ACTIVE: 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "active\n"); 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", ram_bytes_transferred() >> 10); 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", ram_bytes_remaining() >> 10); 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", ram_bytes_total() >> 10); 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case MIG_STATE_COMPLETED: 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "completed\n"); 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case MIG_STATE_ERROR: 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "failed\n"); 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case MIG_STATE_CANCELLED: 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "cancelled\n"); 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* shared migration helpers */ 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_monitor_suspend(FdMigrationState *s) 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->mon_resume = cur_mon; 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (monitor_suspend(cur_mon) == 0) 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("suspending monitor\n"); 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(cur_mon, "terminal does not allow synchronous " 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "migration, continuing detached\n"); 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_error(FdMigrationState *s) 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("setting error state\n"); 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = MIG_STATE_ERROR; 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_cleanup(s); 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_cleanup(FdMigrationState *s) 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->file) { 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("closing file\n"); 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_fclose(s->file); 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd != -1) 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Don't resume monitor until we've flushed all of the buffers */ 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->mon_resume) 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_resume(s->mon_resume); 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = -1; 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_put_notify(void *opaque) 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = opaque; 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_file_put_notify(s->file); 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size) 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = opaque; 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t ret; 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = s->write(s, data, size); 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ret == -1 && ((s->get_error(s)) == EINTR)); 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == -1) 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -(s->get_error(s)); 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == -EAGAIN) 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_connect(FdMigrationState *s) 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->file = qemu_fopen_ops_buffered(s, 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->bandwidth_limit, 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_put_buffer, 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_put_ready, 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_wait_for_unfreeze, 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_close); 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("beginning savevm\n"); 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = qemu_savevm_state_begin(s->file); 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("failed, %d\n", ret); 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_error(s); 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_put_ready(s); 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_put_ready(void *opaque) 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = opaque; 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->state != MIG_STATE_ACTIVE) { 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("put_ready returning because of non-active state\n"); 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("iterate\n"); 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (qemu_savevm_state_iterate(s->file) == 1) { 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int state; 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("done iterating\n"); 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vm_stop(0); 2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner bdrv_flush_all(); 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((qemu_savevm_state_complete(s->file)) < 0) { 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vm_start(); 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner state = MIG_STATE_ERROR; 2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner state = MIG_STATE_COMPLETED; 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_cleanup(s); 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = state; 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint migrate_fd_get_status(MigrationState *mig_state) 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = migrate_to_fms(mig_state); 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->state; 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_cancel(MigrationState *mig_state) 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = migrate_to_fms(mig_state); 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->state != MIG_STATE_ACTIVE) 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("cancelling migration\n"); 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = MIG_STATE_CANCELLED; 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_cleanup(s); 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_release(MigrationState *mig_state) 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = migrate_to_fms(mig_state); 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("releasing state\n"); 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->state == MIG_STATE_ACTIVE) { 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = MIG_STATE_CANCELLED; 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner migrate_fd_cleanup(s); 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(s); 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid migrate_fd_wait_for_unfreeze(void *opaque) 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = opaque; 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dprintf("wait for unfreeze\n"); 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->state != MIG_STATE_ACTIVE) 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd_set wfds; 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_ZERO(&wfds); 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FD_SET(s->fd, &wfds); 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = select(s->fd + 1, NULL, &wfds, NULL, NULL); 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ret == -1 && (s->get_error(s)) == EINTR); 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint migrate_fd_close(void *opaque) 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FdMigrationState *s = opaque; 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s->close(s); 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 338