migration.c 12.3 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
#include "buffered_file.h"
#include "sysemu.h"
#include "block.h"
#include "qemu_socket.h"
21
#include "block-migration.h"
22
#include "qemu-objects.h"
23 24 25 26

//#define DEBUG_MIGRATION

#ifdef DEBUG_MIGRATION
M
malc 已提交
27
#define DPRINTF(fmt, ...) \
28 29
    do { printf("migration: " fmt, ## __VA_ARGS__); } while (0)
#else
M
malc 已提交
30
#define DPRINTF(fmt, ...) \
31 32
    do { } while (0)
#endif
A
aliguori 已提交
33 34

/* Migration speed throttling */
M
Michael S. Tsirkin 已提交
35
static int64_t max_throttle = (32 << 20);
A
aliguori 已提交
36

37
static MigrationState *current_migration;
A
aliguori 已提交
38

39 40 41
static NotifierList migration_state_notifiers =
    NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);

J
Juan Quintela 已提交
42
int qemu_start_incoming_migration(const char *uri)
A
aliguori 已提交
43
{
A
aliguori 已提交
44
    const char *p;
J
Juan Quintela 已提交
45
    int ret;
A
aliguori 已提交
46 47

    if (strstart(uri, "tcp:", &p))
J
Juan Quintela 已提交
48
        ret = tcp_start_incoming_migration(p);
49 50
#if !defined(WIN32)
    else if (strstart(uri, "exec:", &p))
J
Juan Quintela 已提交
51
        ret =  exec_start_incoming_migration(p);
C
Chris Lalancette 已提交
52
    else if (strstart(uri, "unix:", &p))
J
Juan Quintela 已提交
53
        ret = unix_start_incoming_migration(p);
P
Paolo Bonzini 已提交
54
    else if (strstart(uri, "fd:", &p))
J
Juan Quintela 已提交
55
        ret = fd_start_incoming_migration(p);
56
#endif
J
Juan Quintela 已提交
57
    else {
A
aliguori 已提交
58
        fprintf(stderr, "unknown migration protocol: %s\n", uri);
J
Juan Quintela 已提交
59 60 61
        ret = -EPROTONOSUPPORT;
    }
    return ret;
A
aliguori 已提交
62 63
}

64 65 66 67 68 69 70 71 72
void process_incoming_migration(QEMUFile *f)
{
    if (qemu_loadvm_state(f) < 0) {
        fprintf(stderr, "load of migration failed\n");
        exit(0);
    }
    qemu_announce_self();
    DPRINTF("successfully loaded vm state\n");

73
    if (autostart) {
74
        vm_start();
75
    } else {
76
        runstate_set(RUN_STATE_PRELAUNCH);
77
    }
78 79
}

80 81 82 83 84 85 86 87 88 89 90
/* 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;
}

91 92
static void migrate_print_status(Monitor *mon, const char *name,
                                 const QDict *status_dict)
A
aliguori 已提交
93
{
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
    QDict *qdict;

    qdict = qobject_to_qdict(qdict_get(status_dict, name));

    monitor_printf(mon, "transferred %s: %" PRIu64 " kbytes\n", name,
                        qdict_get_int(qdict, "transferred") >> 10);
    monitor_printf(mon, "remaining %s: %" PRIu64 " kbytes\n", name,
                        qdict_get_int(qdict, "remaining") >> 10);
    monitor_printf(mon, "total %s: %" PRIu64 " kbytes\n", name,
                        qdict_get_int(qdict, "total") >> 10);
}

void do_info_migrate_print(Monitor *mon, const QObject *data)
{
    QDict *qdict;

    qdict = qobject_to_qdict(data);

    monitor_printf(mon, "Migration status: %s\n",
                   qdict_get_str(qdict, "status"));

    if (qdict_haskey(qdict, "ram")) {
        migrate_print_status(mon, "ram", qdict);
    }

    if (qdict_haskey(qdict, "disk")) {
        migrate_print_status(mon, "disk", qdict);
    }
}

static void migrate_put_status(QDict *qdict, const char *name,
                               uint64_t trans, uint64_t rem, uint64_t total)
{
    QObject *obj;

    obj = qobject_from_jsonf("{ 'transferred': %" PRId64 ", "
                               "'remaining': %" PRId64 ", "
                               "'total': %" PRId64 " }", trans, rem, total);
    qdict_put_obj(qdict, name, obj);
}

void do_info_migrate(Monitor *mon, QObject **ret_data)
{
    QDict *qdict;
A
aliguori 已提交
138

139
    if (current_migration) {
140
        MigrationState *s = current_migration;
141

142
        switch (s->state) {
143 144 145
        case MIG_STATE_SETUP:
            /* no migration has happened ever */
            break;
A
aliguori 已提交
146
        case MIG_STATE_ACTIVE:
147 148 149 150 151 152
            qdict = qdict_new();
            qdict_put(qdict, "status", qstring_from_str("active"));

            migrate_put_status(qdict, "ram", ram_bytes_transferred(),
                               ram_bytes_remaining(), ram_bytes_total());

153
            if (blk_mig_active()) {
154 155 156
                migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
                                   blk_mig_bytes_remaining(),
                                   blk_mig_bytes_total());
157
            }
158 159

            *ret_data = QOBJECT(qdict);
A
aliguori 已提交
160 161
            break;
        case MIG_STATE_COMPLETED:
162
            *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
A
aliguori 已提交
163 164
            break;
        case MIG_STATE_ERROR:
165
            *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
A
aliguori 已提交
166 167
            break;
        case MIG_STATE_CANCELLED:
168
            *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
A
aliguori 已提交
169 170
            break;
        }
A
aliguori 已提交
171 172 173
    }
}

174 175
/* shared migration helpers */

176
static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
177
{
178 179
    s->mon = mon;
    if (monitor_suspend(mon) == 0) {
M
malc 已提交
180
        DPRINTF("suspending monitor\n");
181 182
    } else {
        monitor_printf(mon, "terminal does not allow synchronous "
183
                       "migration, continuing detached\n");
184
    }
185 186
}

187
static int migrate_fd_cleanup(MigrationState *s)
188
{
189 190
    int ret = 0;

191 192 193
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    if (s->file) {
M
malc 已提交
194
        DPRINTF("closing file\n");
195 196 197
        if (qemu_fclose(s->file) != 0) {
            ret = -1;
        }
198
        s->file = NULL;
199 200 201 202
    } else {
        if (s->mon) {
            monitor_resume(s->mon);
        }
203 204
    }

205
    if (s->fd != -1) {
206
        close(s->fd);
207
        s->fd = -1;
208
    }
209

210
    return ret;
211 212
}

213 214 215 216 217 218 219 220
void migrate_fd_error(MigrationState *s)
{
    DPRINTF("setting error state\n");
    s->state = MIG_STATE_ERROR;
    notifier_list_notify(&migration_state_notifiers, NULL);
    migrate_fd_cleanup(s);
}

221 222 223 224 225 226 227 228 229 230 231 232
static void migrate_fd_completed(MigrationState *s)
{
    DPRINTF("setting completed state\n");
    if (migrate_fd_cleanup(s) < 0) {
        s->state = MIG_STATE_ERROR;
    } else {
        s->state = MIG_STATE_COMPLETED;
        runstate_set(RUN_STATE_POSTMIGRATE);
    }
    notifier_list_notify(&migration_state_notifiers, NULL);
}

233
static void migrate_fd_put_notify(void *opaque)
234
{
235
    MigrationState *s = opaque;
236 237 238

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
    qemu_file_put_notify(s->file);
239
    if (qemu_file_get_error(s->file)) {
240 241
        migrate_fd_error(s);
    }
242 243
}

244 245
static ssize_t migrate_fd_put_buffer(void *opaque, const void *data,
                                     size_t size)
246
{
247
    MigrationState *s = opaque;
248 249
    ssize_t ret;

250 251 252 253
    if (s->state != MIG_STATE_ACTIVE) {
        return -EIO;
    }

254 255
    do {
        ret = s->write(s, data, size);
256
    } while (ret == -1 && ((s->get_error(s)) == EINTR));
257 258 259 260

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

261
    if (ret == -EAGAIN) {
262
        qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
263
    }
264 265 266 267

    return ret;
}

268
static void migrate_fd_put_ready(void *opaque)
269
{
270
    MigrationState *s = opaque;
J
Juan Quintela 已提交
271
    int ret;
272 273

    if (s->state != MIG_STATE_ACTIVE) {
M
malc 已提交
274
        DPRINTF("put_ready returning because of non-active state\n");
275 276 277
        return;
    }

M
malc 已提交
278
    DPRINTF("iterate\n");
J
Juan Quintela 已提交
279 280 281 282
    ret = qemu_savevm_state_iterate(s->mon, s->file);
    if (ret < 0) {
        migrate_fd_error(s);
    } else if (ret == 1) {
283
        int old_vm_running = runstate_is_running();
284

M
malc 已提交
285
        DPRINTF("done iterating\n");
286
        vm_stop(RUN_STATE_FINISH_MIGRATE);
287

288 289 290
        if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
            migrate_fd_error(s);
        } else {
291
            migrate_fd_completed(s);
292
        }
293
        if (s->state != MIG_STATE_COMPLETED) {
294 295 296 297
            if (old_vm_running) {
                vm_start();
            }
        }
298 299 300
    }
}

301
static void migrate_fd_cancel(MigrationState *s)
302 303 304 305
{
    if (s->state != MIG_STATE_ACTIVE)
        return;

M
malc 已提交
306
    DPRINTF("cancelling migration\n");
307 308

    s->state = MIG_STATE_CANCELLED;
309
    notifier_list_notify(&migration_state_notifiers, NULL);
310
    qemu_savevm_state_cancel(s->mon, s->file);
311 312 313 314

    migrate_fd_cleanup(s);
}

315
static void migrate_fd_wait_for_unfreeze(void *opaque)
316
{
317
    MigrationState *s = opaque;
318 319
    int ret;

M
malc 已提交
320
    DPRINTF("wait for unfreeze\n");
321 322 323 324 325 326 327 328 329 330 331
    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);
332 333

    if (ret == -1) {
334
        qemu_file_set_error(s->file, -s->get_error(s));
335
    }
336 337
}

338
static int migrate_fd_close(void *opaque)
339
{
340
    MigrationState *s = opaque;
341

342 343 344
    if (s->mon) {
        monitor_resume(s->mon);
    }
345
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
346 347
    return s->close(s);
}
348 349 350 351 352 353 354 355 356 357 358 359 360 361

void add_migration_state_change_notifier(Notifier *notify)
{
    notifier_list_add(&migration_state_notifiers, notify);
}

void remove_migration_state_change_notifier(Notifier *notify)
{
    notifier_list_remove(&migration_state_notifiers, notify);
}

int get_migration_state(void)
{
    if (current_migration) {
362
        return current_migration->state;
363 364 365 366
    } else {
        return MIG_STATE_ERROR;
    }
}
367

368 369 370 371
void migrate_fd_connect(MigrationState *s)
{
    int ret;

372
    s->state = MIG_STATE_ACTIVE;
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
    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");
    ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared);
    if (ret < 0) {
        DPRINTF("failed, %d\n", ret);
        migrate_fd_error(s);
        return;
    }
    migrate_fd_put_ready(s);
}

390 391
static MigrationState *migrate_new(Monitor *mon, int64_t bandwidth_limit,
                                   int detach, int blk, int inc)
392 393 394 395 396 397 398
{
    MigrationState *s = g_malloc0(sizeof(*s));

    s->blk = blk;
    s->shared = inc;
    s->mon = NULL;
    s->bandwidth_limit = bandwidth_limit;
399
    s->state = MIG_STATE_SETUP;
400 401 402 403 404 405 406

    if (!detach) {
        migrate_fd_monitor_suspend(s, mon);
    }

    return s;
}
407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497

int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    MigrationState *s = NULL;
    const char *p;
    int detach = qdict_get_try_bool(qdict, "detach", 0);
    int blk = qdict_get_try_bool(qdict, "blk", 0);
    int inc = qdict_get_try_bool(qdict, "inc", 0);
    const char *uri = qdict_get_str(qdict, "uri");
    int ret;

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

    if (qemu_savevm_state_blocked(mon)) {
        return -1;
    }

    s = migrate_new(mon, max_throttle, detach, blk, inc);

    if (strstart(uri, "tcp:", &p)) {
        ret = tcp_start_outgoing_migration(s, p);
#if !defined(WIN32)
    } else if (strstart(uri, "exec:", &p)) {
        ret = exec_start_outgoing_migration(s, p);
    } else if (strstart(uri, "unix:", &p)) {
        ret = unix_start_outgoing_migration(s, p);
    } else if (strstart(uri, "fd:", &p)) {
        ret = fd_start_outgoing_migration(s, p);
#endif
    } else {
        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
        ret  = -EINVAL;
        goto free_migrate_state;
    }

    if (ret < 0) {
        monitor_printf(mon, "migration failed\n");
        goto free_migrate_state;
    }

    g_free(current_migration);
    current_migration = s;
    notifier_list_notify(&migration_state_notifiers, NULL);
    return 0;
free_migrate_state:
    g_free(s);
    return -1;
}

int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    if (current_migration) {
        migrate_fd_cancel(current_migration);
    }
    return 0;
}

int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
    int64_t d;
    MigrationState *s;

    d = qdict_get_int(qdict, "value");
    if (d < 0) {
        d = 0;
    }
    max_throttle = d;

    s = current_migration;
    if (s && s->file) {
        qemu_file_set_rate_limit(s->file, max_throttle);
    }

    return 0;
}

int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
                            QObject **ret_data)
{
    double d;

    d = qdict_get_double(qdict, "value") * 1e9;
    d = MAX(0, MIN(UINT64_MAX, d));
    max_downtime = (uint64_t)d;

    return 0;
}