Home | History | Annotate | Download | only in qemu
      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 #include <sys/types.h>
     24 #include <sys/wait.h>
     25 
     26 //#define DEBUG_MIGRATION_EXEC
     27 
     28 #ifdef DEBUG_MIGRATION_EXEC
     29 #define DPRINTF(fmt, ...) \
     30     do { printf("migration-exec: " fmt, ## __VA_ARGS__); } while (0)
     31 #else
     32 #define DPRINTF(fmt, ...) \
     33     do { } while (0)
     34 #endif
     35 
     36 static int file_errno(FdMigrationState *s)
     37 {
     38     return errno;
     39 }
     40 
     41 static int file_write(FdMigrationState *s, const void * buf, size_t size)
     42 {
     43     return write(s->fd, buf, size);
     44 }
     45 
     46 static int exec_close(FdMigrationState *s)
     47 {
     48     int ret = 0;
     49     DPRINTF("exec_close\n");
     50     if (s->opaque) {
     51         ret = qemu_fclose(s->opaque);
     52         s->opaque = NULL;
     53         s->fd = -1;
     54         if (ret != -1 &&
     55             WIFEXITED(ret)
     56             && WEXITSTATUS(ret) == 0) {
     57             ret = 0;
     58         } else {
     59             ret = -1;
     60     }
     61     }
     62     return ret;
     63 }
     64 
     65 MigrationState *exec_start_outgoing_migration(const char *command,
     66                                              int64_t bandwidth_limit,
     67                                              int detach)
     68 {
     69     FdMigrationState *s;
     70     FILE *f;
     71 
     72     s = qemu_mallocz(sizeof(*s));
     73 
     74     f = popen(command, "w");
     75     if (f == NULL) {
     76         DPRINTF("Unable to popen exec target\n");
     77         goto err_after_alloc;
     78     }
     79 
     80     s->fd = fileno(f);
     81     if (s->fd == -1) {
     82         DPRINTF("Unable to retrieve file descriptor for popen'd handle\n");
     83         goto err_after_open;
     84     }
     85 
     86     if (fcntl(s->fd, F_SETFD, O_NONBLOCK) == -1) {
     87         DPRINTF("Unable to set nonblocking mode on file descriptor\n");
     88         goto err_after_open;
     89     }
     90 
     91     s->opaque = qemu_popen(f, "w");
     92 
     93     s->close = exec_close;
     94     s->get_error = file_errno;
     95     s->write = file_write;
     96     s->mig_state.cancel = migrate_fd_cancel;
     97     s->mig_state.get_status = migrate_fd_get_status;
     98     s->mig_state.release = migrate_fd_release;
     99 
    100     s->state = MIG_STATE_ACTIVE;
    101     s->mon_resume = NULL;
    102     s->bandwidth_limit = bandwidth_limit;
    103 
    104     if (!detach)
    105         migrate_fd_monitor_suspend(s);
    106 
    107     migrate_fd_connect(s);
    108     return &s->mig_state;
    109 
    110 err_after_open:
    111     pclose(f);
    112 err_after_alloc:
    113     qemu_free(s);
    114     return NULL;
    115 }
    116 
    117 static void exec_accept_incoming_migration(void *opaque)
    118 {
    119     QEMUFile *f = opaque;
    120     int ret;
    121 
    122     vm_stop(0); /* just in case */
    123     ret = qemu_loadvm_state(f);
    124     if (ret < 0) {
    125         fprintf(stderr, "load of migration failed\n");
    126         goto err;
    127     }
    128     qemu_announce_self();
    129     DPRINTF("successfully loaded vm state\n");
    130     /* we've successfully migrated, close the fd */
    131     qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
    132     vm_start();
    133 
    134 err:
    135     qemu_fclose(f);
    136 }
    137 
    138 int exec_start_incoming_migration(const char *command)
    139 {
    140     QEMUFile *f;
    141 
    142     DPRINTF("Attempting to start an incoming migration\n");
    143     f = qemu_popen_cmd(command, "r");
    144     if(f == NULL) {
    145         DPRINTF("Unable to apply qemu wrapper to popen file\n");
    146         return -errno;
    147     }
    148 
    149     qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
    150 			 exec_accept_incoming_migration, NULL,
    151 			 (void *)(unsigned long)f);
    152 
    153     return 0;
    154 }
    155