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 * Contributions after 2012-01-13 are licensed under the terms of the
  15 * GNU GPL, version 2 or (at your option) any later version.
  16 */
  17
  18#include "qemu-common.h"
  19#include "qemu_socket.h"
  20#include "migration.h"
  21#include "qemu-char.h"
  22#include "buffered_file.h"
  23#include "block.h"
  24#include <sys/types.h>
  25#include <sys/wait.h>
  26
  27//#define DEBUG_MIGRATION_EXEC
  28
  29#ifdef DEBUG_MIGRATION_EXEC
  30#define DPRINTF(fmt, ...) \
  31    do { printf("migration-exec: " fmt, ## __VA_ARGS__); } while (0)
  32#else
  33#define DPRINTF(fmt, ...) \
  34    do { } while (0)
  35#endif
  36
  37static int file_errno(MigrationState *s)
  38{
  39    return errno;
  40}
  41
  42static int file_write(MigrationState *s, const void * buf, size_t size)
  43{
  44    return write(s->fd, buf, size);
  45}
  46
  47static int exec_close(MigrationState *s)
  48{
  49    int ret = 0;
  50    DPRINTF("exec_close\n");
  51    if (s->opaque) {
  52        ret = qemu_fclose(s->opaque);
  53        s->opaque = NULL;
  54        s->fd = -1;
  55        if (ret >= 0 && !(WIFEXITED(ret) && WEXITSTATUS(ret) == 0)) {
  56            /* close succeeded, but non-zero exit code: */
  57            ret = -EIO; /* fake errno value */
  58        }
  59    }
  60    return ret;
  61}
  62
  63int exec_start_outgoing_migration(MigrationState *s, const char *command)
  64{
  65    FILE *f;
  66
  67    f = popen(command, "w");
  68    if (f == NULL) {
  69        DPRINTF("Unable to popen exec target\n");
  70        goto err_after_popen;
  71    }
  72
  73    s->fd = fileno(f);
  74    if (s->fd == -1) {
  75        DPRINTF("Unable to retrieve file descriptor for popen'd handle\n");
  76        goto err_after_open;
  77    }
  78
  79    socket_set_nonblock(s->fd);
  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
  87    migrate_fd_connect(s);
  88    return 0;
  89
  90err_after_open:
  91    pclose(f);
  92err_after_popen:
  93    return -1;
  94}
  95
  96static void exec_accept_incoming_migration(void *opaque)
  97{
  98    QEMUFile *f = opaque;
  99
 100    process_incoming_migration(f);
 101    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
 102    qemu_fclose(f);
 103}
 104
 105int exec_start_incoming_migration(const char *command)
 106{
 107    QEMUFile *f;
 108
 109    DPRINTF("Attempting to start an incoming migration\n");
 110    f = qemu_popen_cmd(command, "r");
 111    if(f == NULL) {
 112        DPRINTF("Unable to apply qemu wrapper to popen file\n");
 113        return -errno;
 114    }
 115
 116    qemu_set_fd_handler2(qemu_stdio_fd(f), NULL,
 117                         exec_accept_incoming_migration, NULL, f);
 118
 119    return 0;
 120}
 121