qemu/migration-exec.c
<<
>>
Prefs
   1/*
   2 * QEMU live migration
   3 *
   4 * Copyright IBM, Corp. 2008
   5 * Copyright Dell MessageOne 2008
   6 *
   7 * Authors:
   8 *  Anthony Liguori   <aliguori@us.ibm.com>
   9 *  Charles Duffy     <charles_duffy@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
  36static int file_errno(FdMigrationState *s)
  37{
  38    return errno;
  39}
  40
  41static int file_write(FdMigrationState *s, const void * buf, size_t size)
  42{
  43    return write(s->fd, buf, size);
  44}
  45
  46static 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
  65MigrationState *exec_start_outgoing_migration(Monitor *mon,
  66                                              const char *command,
  67                                              int64_t bandwidth_limit,
  68                                              int detach,
  69                                              int blk,
  70                                              int inc)
  71{
  72    FdMigrationState *s;
  73    FILE *f;
  74
  75    s = qemu_mallocz(sizeof(*s));
  76
  77    f = popen(command, "w");
  78    if (f == NULL) {
  79        DPRINTF("Unable to popen exec target\n");
  80        goto err_after_alloc;
  81    }
  82
  83    s->fd = fileno(f);
  84    if (s->fd == -1) {
  85        DPRINTF("Unable to retrieve file descriptor for popen'd handle\n");
  86        goto err_after_open;
  87    }
  88
  89    socket_set_nonblock(s->fd);
  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->mig_state.blk = blk;
 101    s->mig_state.shared = inc;
 102
 103    s->state = MIG_STATE_ACTIVE;
 104    s->mon = NULL;
 105    s->bandwidth_limit = bandwidth_limit;
 106
 107    if (!detach) {
 108        migrate_fd_monitor_suspend(s, mon);
 109    }
 110
 111    migrate_fd_connect(s);
 112    return &s->mig_state;
 113
 114err_after_open:
 115    pclose(f);
 116err_after_alloc:
 117    qemu_free(s);
 118    return NULL;
 119}
 120
 121static void exec_accept_incoming_migration(void *opaque)
 122{
 123    QEMUFile *f = opaque;
 124
 125    process_incoming_migration(f);
 126    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
 127    qemu_fclose(f);
 128}
 129
 130int exec_start_incoming_migration(const char *command)
 131{
 132    QEMUFile *f;
 133
 134    DPRINTF("Attempting to start an incoming migration\n");
 135    f = qemu_popen_cmd(command, "r");
 136    if(f == NULL) {
 137        DPRINTF("Unable to apply qemu wrapper to popen file\n");
 138        return -errno;
 139    }
 140
 141    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
 142                         exec_accept_incoming_migration, NULL, f);
 143
 144    return 0;
 145}
 146