migration.c 9.4 KB
Newer Older
A
aliguori 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/*
 * QEMU live migration
 *
 * Copyright IBM, Corp. 2008
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
 */

#include "qemu-common.h"
#include "migration.h"
A
aliguori 已提交
16
#include "monitor.h"
17 18 19 20 21 22 23 24 25 26 27 28 29 30
#include "buffered_file.h"
#include "sysemu.h"
#include "block.h"
#include "qemu_socket.h"

//#define DEBUG_MIGRATION

#ifdef DEBUG_MIGRATION
#define dprintf(fmt, ...) \
    do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
#else
#define dprintf(fmt, ...) \
    do { } while (0)
#endif
A
aliguori 已提交
31 32 33 34 35 36 37 38

/* Migration speed throttling */
static uint32_t max_throttle = (32 << 20);

static MigrationState *current_migration;

void qemu_start_incoming_migration(const char *uri)
{
A
aliguori 已提交
39 40 41 42
    const char *p;

    if (strstart(uri, "tcp:", &p))
        tcp_start_incoming_migration(p);
43 44 45
#if !defined(WIN32)
    else if (strstart(uri, "exec:", &p))
        exec_start_incoming_migration(p);
C
Chris Lalancette 已提交
46 47
    else if (strstart(uri, "unix:", &p))
        unix_start_incoming_migration(p);
P
Paolo Bonzini 已提交
48 49
    else if (strstart(uri, "fd:", &p))
        fd_start_incoming_migration(p);
50
#endif
A
aliguori 已提交
51 52
    else
        fprintf(stderr, "unknown migration protocol: %s\n", uri);
A
aliguori 已提交
53 54
}

55
void do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
56
{
A
aliguori 已提交
57 58
    MigrationState *s = NULL;
    const char *p;
59 60
    int detach = qdict_get_int(qdict, "detach");
    const char *uri = qdict_get_str(qdict, "uri");
61 62 63 64 65 66 67

    if (current_migration &&
        current_migration->get_status(current_migration) == MIG_STATE_ACTIVE) {
        monitor_printf(mon, "migration already in progress\n");
        return;
    }

A
aliguori 已提交
68
    if (strstart(uri, "tcp:", &p))
69
        s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
70 71
                                         (int)qdict_get_int(qdict, "blk"), 
                                         (int)qdict_get_int(qdict, "inc"));
72 73
#if !defined(WIN32)
    else if (strstart(uri, "exec:", &p))
74
        s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
75 76
                                          (int)qdict_get_int(qdict, "blk"), 
                                          (int)qdict_get_int(qdict, "inc"));
C
Chris Lalancette 已提交
77
    else if (strstart(uri, "unix:", &p))
78
        s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
79 80
					  (int)qdict_get_int(qdict, "blk"), 
                                          (int)qdict_get_int(qdict, "inc"));
P
Paolo Bonzini 已提交
81
    else if (strstart(uri, "fd:", &p))
L
lirans@il.ibm.com 已提交
82 83 84
        s = fd_start_outgoing_migration(mon, p, max_throttle, detach, 
                                        (int)qdict_get_int(qdict, "blk"), 
                                        (int)qdict_get_int(qdict, "inc"));
85
#endif
A
aliguori 已提交
86
    else
A
aliguori 已提交
87
        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
A
aliguori 已提交
88 89

    if (s == NULL)
A
aliguori 已提交
90
        monitor_printf(mon, "migration failed\n");
A
aliguori 已提交
91
    else {
A
aliguori 已提交
92 93
        if (current_migration)
            current_migration->release(current_migration);
A
aliguori 已提交
94

A
aliguori 已提交
95
        current_migration = s;
A
aliguori 已提交
96
    }
A
aliguori 已提交
97 98
}

99
void do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
100 101 102 103
{
    MigrationState *s = current_migration;

    if (s)
A
aliguori 已提交
104
        s->cancel(s);
A
aliguori 已提交
105 106
}

107
void do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
108 109 110
{
    double d;
    char *ptr;
111
    FdMigrationState *s;
112
    const char *value = qdict_get_str(qdict, "value");
A
aliguori 已提交
113 114 115 116

    d = strtod(value, &ptr);
    switch (*ptr) {
    case 'G': case 'g':
A
aliguori 已提交
117
        d *= 1024;
A
aliguori 已提交
118
    case 'M': case 'm':
A
aliguori 已提交
119
        d *= 1024;
A
aliguori 已提交
120
    case 'K': case 'k':
A
aliguori 已提交
121
        d *= 1024;
A
aliguori 已提交
122
    default:
A
aliguori 已提交
123
        break;
A
aliguori 已提交
124 125 126
    }

    max_throttle = (uint32_t)d;
127

128 129
    s = migrate_to_fms(current_migration);
    if (s && s->file) {
130 131
        qemu_file_set_rate_limit(s->file, max_throttle);
    }
A
aliguori 已提交
132 133
}

134 135 136 137 138 139 140 141 142 143 144
/* amount of nanoseconds we are willing to wait for migration to be down.
 * the choice of nanoseconds is because it is the maximum resolution that
 * get_clock() can achieve. It is an internal measure. All user-visible
 * units must be in seconds */
static uint64_t max_downtime = 30000000;

uint64_t migrate_max_downtime(void)
{
    return max_downtime;
}

145
void do_migrate_set_downtime(Monitor *mon, const QDict *qdict)
G
Glauber Costa 已提交
146 147 148
{
    char *ptr;
    double d;
149
    const char *value = qdict_get_str(qdict, "value");
G
Glauber Costa 已提交
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164

    d = strtod(value, &ptr);
    if (!strcmp(ptr,"ms")) {
        d *= 1000000;
    } else if (!strcmp(ptr,"us")) {
        d *= 1000;
    } else if (!strcmp(ptr,"ns")) {
    } else {
        /* all else considered to be seconds */
        d *= 1000000000;
    }

    max_downtime = (uint64_t)d;
}

A
aliguori 已提交
165
void do_info_migrate(Monitor *mon)
A
aliguori 已提交
166 167
{
    MigrationState *s = current_migration;
A
aliguori 已提交
168

A
aliguori 已提交
169
    if (s) {
A
aliguori 已提交
170
        monitor_printf(mon, "Migration status: ");
A
aliguori 已提交
171 172
        switch (s->get_status(s)) {
        case MIG_STATE_ACTIVE:
A
aliguori 已提交
173
            monitor_printf(mon, "active\n");
174 175 176
            monitor_printf(mon, "transferred ram: %" PRIu64 " kbytes\n", ram_bytes_transferred() >> 10);
            monitor_printf(mon, "remaining ram: %" PRIu64 " kbytes\n", ram_bytes_remaining() >> 10);
            monitor_printf(mon, "total ram: %" PRIu64 " kbytes\n", ram_bytes_total() >> 10);
A
aliguori 已提交
177 178
            break;
        case MIG_STATE_COMPLETED:
A
aliguori 已提交
179
            monitor_printf(mon, "completed\n");
A
aliguori 已提交
180 181
            break;
        case MIG_STATE_ERROR:
A
aliguori 已提交
182
            monitor_printf(mon, "failed\n");
A
aliguori 已提交
183 184
            break;
        case MIG_STATE_CANCELLED:
A
aliguori 已提交
185
            monitor_printf(mon, "cancelled\n");
A
aliguori 已提交
186 187
            break;
        }
A
aliguori 已提交
188 189 190
    }
}

191 192
/* shared migration helpers */

193
void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
194
{
195 196
    s->mon = mon;
    if (monitor_suspend(mon) == 0) {
197
        dprintf("suspending monitor\n");
198 199
    } else {
        monitor_printf(mon, "terminal does not allow synchronous "
200
                       "migration, continuing detached\n");
201
    }
202 203
}

204 205 206 207 208 209 210 211 212 213 214 215 216 217
void migrate_fd_error(FdMigrationState *s)
{
    dprintf("setting error state\n");
    s->state = MIG_STATE_ERROR;
    migrate_fd_cleanup(s);
}

void migrate_fd_cleanup(FdMigrationState *s)
{
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    if (s->file) {
        dprintf("closing file\n");
        qemu_fclose(s->file);
218
        s->file = NULL;
219 220 221 222 223 224
    }

    if (s->fd != -1)
        close(s->fd);

    /* Don't resume monitor until we've flushed all of the buffers */
225 226 227
    if (s->mon) {
        monitor_resume(s->mon);
    }
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246

    s->fd = -1;
}

void migrate_fd_put_notify(void *opaque)
{
    FdMigrationState *s = opaque;

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
    qemu_file_put_notify(s->file);
}

ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
{
    FdMigrationState *s = opaque;
    ssize_t ret;

    do {
        ret = s->write(s, data, size);
247
    } while (ret == -1 && ((s->get_error(s)) == EINTR));
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269

    if (ret == -1)
        ret = -(s->get_error(s));

    if (ret == -EAGAIN)
        qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);

    return ret;
}

void migrate_fd_connect(FdMigrationState *s)
{
    int ret;

    s->file = qemu_fopen_ops_buffered(s,
                                      s->bandwidth_limit,
                                      migrate_fd_put_buffer,
                                      migrate_fd_put_ready,
                                      migrate_fd_wait_for_unfreeze,
                                      migrate_fd_close);

    dprintf("beginning savevm\n");
270
    ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
L
lirans@il.ibm.com 已提交
271
                                  s->mig_state.shared);
272 273 274 275 276
    if (ret < 0) {
        dprintf("failed, %d\n", ret);
        migrate_fd_error(s);
        return;
    }
L
lirans@il.ibm.com 已提交
277
    
278 279 280 281 282 283 284 285 286 287 288 289 290
    migrate_fd_put_ready(s);
}

void migrate_fd_put_ready(void *opaque)
{
    FdMigrationState *s = opaque;

    if (s->state != MIG_STATE_ACTIVE) {
        dprintf("put_ready returning because of non-active state\n");
        return;
    }

    dprintf("iterate\n");
291
    if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
292
        int state;
293 294
        int old_vm_running = vm_running;

295 296 297
        dprintf("done iterating\n");
        vm_stop(0);

G
Glauber Costa 已提交
298
        qemu_aio_flush();
299
        bdrv_flush_all();
300
        if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
301 302 303
            if (old_vm_running) {
                vm_start();
            }
304 305 306 307
            state = MIG_STATE_ERROR;
        } else {
            state = MIG_STATE_COMPLETED;
        }
308
        migrate_fd_cleanup(s);
309
        s->state = state;
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
    }
}

int migrate_fd_get_status(MigrationState *mig_state)
{
    FdMigrationState *s = migrate_to_fms(mig_state);
    return s->state;
}

void migrate_fd_cancel(MigrationState *mig_state)
{
    FdMigrationState *s = migrate_to_fms(mig_state);

    if (s->state != MIG_STATE_ACTIVE)
        return;

    dprintf("cancelling migration\n");

    s->state = MIG_STATE_CANCELLED;
329
    qemu_savevm_state_cancel(s->mon, s->file);
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368

    migrate_fd_cleanup(s);
}

void migrate_fd_release(MigrationState *mig_state)
{
    FdMigrationState *s = migrate_to_fms(mig_state);

    dprintf("releasing state\n");
   
    if (s->state == MIG_STATE_ACTIVE) {
        s->state = MIG_STATE_CANCELLED;
        migrate_fd_cleanup(s);
    }
    free(s);
}

void migrate_fd_wait_for_unfreeze(void *opaque)
{
    FdMigrationState *s = opaque;
    int ret;

    dprintf("wait for unfreeze\n");
    if (s->state != MIG_STATE_ACTIVE)
        return;

    do {
        fd_set wfds;

        FD_ZERO(&wfds);
        FD_SET(s->fd, &wfds);

        ret = select(s->fd + 1, NULL, &wfds, NULL, NULL);
    } while (ret == -1 && (s->get_error(s)) == EINTR);
}

int migrate_fd_close(void *opaque)
{
    FdMigrationState *s = opaque;
369 370

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
371 372
    return s->close(s);
}