1 /* 2 * QEMU live migration 3 * 4 * Copyright IBM, Corp. 2008 5 * Copyright Dell MessageOne 2008 6 * 7 * Authors: 8 * Anthony Liguori <aliguori (at) us.ibm.com> 9 * Charles Duffy <charles_duffy (at) messageone.com> 10 * 11 * This work is licensed under the terms of the GNU GPL, version 2. See 12 * the COPYING file in the top-level directory. 13 * 14 */ 15 16 #include "qemu-common.h" 17 #include "qemu_socket.h" 18 #include "migration.h" 19 #include "qemu-char.h" 20 #include "sysemu.h" 21 #include "buffered_file.h" 22 #include "block.h" 23 24 //#define DEBUG_MIGRATION_EXEC 25 26 #ifdef DEBUG_MIGRATION_EXEC 27 #define dprintf(fmt, ...) \ 28 do { printf("migration-exec: " fmt, ## __VA_ARGS__); } while (0) 29 #else 30 #define dprintf(fmt, ...) \ 31 do { } while (0) 32 #endif 33 34 static int file_errno(FdMigrationState *s) 35 { 36 return errno; 37 } 38 39 static int file_write(FdMigrationState *s, const void * buf, size_t size) 40 { 41 return write(s->fd, buf, size); 42 } 43 44 static int exec_close(FdMigrationState *s) 45 { 46 dprintf("exec_close\n"); 47 if (s->opaque) { 48 qemu_fclose(s->opaque); 49 s->opaque = NULL; 50 s->fd = -1; 51 } 52 return 0; 53 } 54 55 MigrationState *exec_start_outgoing_migration(const char *command, 56 int64_t bandwidth_limit, 57 int detach) 58 { 59 FdMigrationState *s; 60 FILE *f; 61 62 s = qemu_mallocz(sizeof(*s)); 63 64 f = popen(command, "w"); 65 if (f == NULL) { 66 dprintf("Unable to popen exec target\n"); 67 goto err_after_alloc; 68 } 69 70 s->fd = fileno(f); 71 if (s->fd == -1) { 72 dprintf("Unable to retrieve file descriptor for popen'd handle\n"); 73 goto err_after_open; 74 } 75 76 if (fcntl(s->fd, F_SETFD, O_NONBLOCK) == -1) { 77 dprintf("Unable to set nonblocking mode on file descriptor\n"); 78 goto err_after_open; 79 } 80 81 s->opaque = qemu_popen(f, "w"); 82 83 s->close = exec_close; 84 s->get_error = file_errno; 85 s->write = file_write; 86 s->mig_state.cancel = migrate_fd_cancel; 87 s->mig_state.get_status = migrate_fd_get_status; 88 s->mig_state.release = migrate_fd_release; 89 90 s->state = MIG_STATE_ACTIVE; 91 s->mon_resume = NULL; 92 s->bandwidth_limit = bandwidth_limit; 93 94 if (!detach) 95 migrate_fd_monitor_suspend(s); 96 97 migrate_fd_connect(s); 98 return &s->mig_state; 99 100 err_after_open: 101 pclose(f); 102 err_after_alloc: 103 qemu_free(s); 104 return NULL; 105 } 106 107 static void exec_accept_incoming_migration(void *opaque) 108 { 109 QEMUFile *f = opaque; 110 int ret; 111 112 vm_stop(0); /* just in case */ 113 ret = qemu_loadvm_state(f); 114 if (ret < 0) { 115 fprintf(stderr, "load of migration failed\n"); 116 goto err; 117 } 118 qemu_announce_self(); 119 dprintf("successfully loaded vm state\n"); 120 /* we've successfully migrated, close the fd */ 121 qemu_set_fd_handler2(qemu_popen_fd(f), NULL, NULL, NULL, NULL); 122 vm_start(); 123 124 err: 125 qemu_fclose(f); 126 } 127 128 int exec_start_incoming_migration(const char *command) 129 { 130 QEMUFile *f; 131 132 dprintf("Attempting to start an incoming migration\n"); 133 f = qemu_popen_cmd(command, "r"); 134 if(f == NULL) { 135 dprintf("Unable to apply qemu wrapper to popen file\n"); 136 return -errno; 137 } 138 139 qemu_set_fd_handler2(qemu_popen_fd(f), NULL, 140 exec_accept_incoming_migration, NULL, 141 (void *)(unsigned long)f); 142 143 return 0; 144 } 145