migration.c 12.2 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
#define MAX_THROTTLE  (32 << 20)      /* Migration speed throttling */
A
aliguori 已提交
35

36 37 38
static NotifierList migration_state_notifiers =
    NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);

39 40 41 42 43 44 45 46
/* When we add fault tolerance, we could have several
   migrations at once.  For now we don't need to add
   dynamic creation of migration */

static MigrationState *migrate_get_current(void)
{
    static MigrationState current_migration = {
        .state = MIG_STATE_SETUP,
47
        .bandwidth_limit = MAX_THROTTLE,
48 49 50 51 52
    };

    return &current_migration;
}

J
Juan Quintela 已提交
53
int qemu_start_incoming_migration(const char *uri)
A
aliguori 已提交
54
{
A
aliguori 已提交
55
    const char *p;
J
Juan Quintela 已提交
56
    int ret;
A
aliguori 已提交
57 58

    if (strstart(uri, "tcp:", &p))
J
Juan Quintela 已提交
59
        ret = tcp_start_incoming_migration(p);
60 61
#if !defined(WIN32)
    else if (strstart(uri, "exec:", &p))
J
Juan Quintela 已提交
62
        ret =  exec_start_incoming_migration(p);
C
Chris Lalancette 已提交
63
    else if (strstart(uri, "unix:", &p))
J
Juan Quintela 已提交
64
        ret = unix_start_incoming_migration(p);
P
Paolo Bonzini 已提交
65
    else if (strstart(uri, "fd:", &p))
J
Juan Quintela 已提交
66
        ret = fd_start_incoming_migration(p);
67
#endif
J
Juan Quintela 已提交
68
    else {
A
aliguori 已提交
69
        fprintf(stderr, "unknown migration protocol: %s\n", uri);
J
Juan Quintela 已提交
70 71 72
        ret = -EPROTONOSUPPORT;
    }
    return ret;
A
aliguori 已提交
73 74
}

75 76 77 78 79 80 81 82 83
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");

84
    if (autostart) {
85
        vm_start();
86
    } else {
87
        runstate_set(RUN_STATE_PRELAUNCH);
88
    }
89 90
}

91 92 93 94 95 96 97 98 99 100 101
/* 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;
}

102 103
static void migrate_print_status(Monitor *mon, const char *name,
                                 const QDict *status_dict)
A
aliguori 已提交
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 138 139 140 141 142 143 144 145 146 147 148
    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;
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    MigrationState *s = migrate_get_current();

    switch (s->state) {
    case MIG_STATE_SETUP:
        /* no migration has happened ever */
        break;
    case MIG_STATE_ACTIVE:
        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());

        if (blk_mig_active()) {
            migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
                               blk_mig_bytes_remaining(),
                               blk_mig_bytes_total());
A
aliguori 已提交
166
        }
167 168 169 170 171 172 173 174 175 176 177 178

        *ret_data = QOBJECT(qdict);
        break;
    case MIG_STATE_COMPLETED:
        *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
        break;
    case MIG_STATE_ERROR:
        *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
        break;
    case MIG_STATE_CANCELLED:
        *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
        break;
A
aliguori 已提交
179 180 181
    }
}

182 183
/* shared migration helpers */

184
static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon)
185
{
186 187
    s->mon = mon;
    if (monitor_suspend(mon) == 0) {
M
malc 已提交
188
        DPRINTF("suspending monitor\n");
189 190
    } else {
        monitor_printf(mon, "terminal does not allow synchronous "
191
                       "migration, continuing detached\n");
192
    }
193 194
}

195
static int migrate_fd_cleanup(MigrationState *s)
196
{
197 198
    int ret = 0;

199 200 201
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    if (s->file) {
M
malc 已提交
202
        DPRINTF("closing file\n");
203 204 205
        if (qemu_fclose(s->file) != 0) {
            ret = -1;
        }
206
        s->file = NULL;
207 208 209 210
    } else {
        if (s->mon) {
            monitor_resume(s->mon);
        }
211 212
    }

213
    if (s->fd != -1) {
214
        close(s->fd);
215
        s->fd = -1;
216
    }
217

218
    return ret;
219 220
}

221 222 223 224
void migrate_fd_error(MigrationState *s)
{
    DPRINTF("setting error state\n");
    s->state = MIG_STATE_ERROR;
225
    notifier_list_notify(&migration_state_notifiers, s);
226 227 228
    migrate_fd_cleanup(s);
}

229 230 231 232 233 234 235 236 237
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);
    }
238
    notifier_list_notify(&migration_state_notifiers, s);
239 240
}

241
static void migrate_fd_put_notify(void *opaque)
242
{
243
    MigrationState *s = opaque;
244 245 246

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
    qemu_file_put_notify(s->file);
247
    if (qemu_file_get_error(s->file)) {
248 249
        migrate_fd_error(s);
    }
250 251
}

252 253
static ssize_t migrate_fd_put_buffer(void *opaque, const void *data,
                                     size_t size)
254
{
255
    MigrationState *s = opaque;
256 257
    ssize_t ret;

258 259 260 261
    if (s->state != MIG_STATE_ACTIVE) {
        return -EIO;
    }

262 263
    do {
        ret = s->write(s, data, size);
264
    } while (ret == -1 && ((s->get_error(s)) == EINTR));
265 266 267 268

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

269
    if (ret == -EAGAIN) {
270
        qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s);
271
    }
272 273 274 275

    return ret;
}

276
static void migrate_fd_put_ready(void *opaque)
277
{
278
    MigrationState *s = opaque;
J
Juan Quintela 已提交
279
    int ret;
280 281

    if (s->state != MIG_STATE_ACTIVE) {
M
malc 已提交
282
        DPRINTF("put_ready returning because of non-active state\n");
283 284 285
        return;
    }

M
malc 已提交
286
    DPRINTF("iterate\n");
J
Juan Quintela 已提交
287 288 289 290
    ret = qemu_savevm_state_iterate(s->mon, s->file);
    if (ret < 0) {
        migrate_fd_error(s);
    } else if (ret == 1) {
291
        int old_vm_running = runstate_is_running();
292

M
malc 已提交
293
        DPRINTF("done iterating\n");
294
        vm_stop(RUN_STATE_FINISH_MIGRATE);
295

296 297 298
        if (qemu_savevm_state_complete(s->mon, s->file) < 0) {
            migrate_fd_error(s);
        } else {
299
            migrate_fd_completed(s);
300
        }
301
        if (s->state != MIG_STATE_COMPLETED) {
302 303 304 305
            if (old_vm_running) {
                vm_start();
            }
        }
306 307 308
    }
}

309
static void migrate_fd_cancel(MigrationState *s)
310 311 312 313
{
    if (s->state != MIG_STATE_ACTIVE)
        return;

M
malc 已提交
314
    DPRINTF("cancelling migration\n");
315 316

    s->state = MIG_STATE_CANCELLED;
317
    notifier_list_notify(&migration_state_notifiers, s);
318
    qemu_savevm_state_cancel(s->mon, s->file);
319 320 321 322

    migrate_fd_cleanup(s);
}

323
static void migrate_fd_wait_for_unfreeze(void *opaque)
324
{
325
    MigrationState *s = opaque;
326 327
    int ret;

M
malc 已提交
328
    DPRINTF("wait for unfreeze\n");
329 330 331 332 333 334 335 336 337 338 339
    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);
340 341

    if (ret == -1) {
342
        qemu_file_set_error(s->file, -s->get_error(s));
343
    }
344 345
}

346
static int migrate_fd_close(void *opaque)
347
{
348
    MigrationState *s = opaque;
349

350 351 352
    if (s->mon) {
        monitor_resume(s->mon);
    }
353
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
354 355
    return s->close(s);
}
356 357 358 359 360 361 362 363 364 365 366

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);
}

367
bool migration_has_finished(MigrationState *s)
368
{
369
    return s->state == MIG_STATE_COMPLETED;
370
}
371

372 373 374 375
void migrate_fd_connect(MigrationState *s)
{
    int ret;

376
    s->state = MIG_STATE_ACTIVE;
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393
    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);
}

394
static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
395
{
396
    MigrationState *s = migrate_get_current();
397
    int64_t bandwidth_limit = s->bandwidth_limit;
398

399
    memset(s, 0, sizeof(*s));
400
    s->bandwidth_limit = bandwidth_limit;
401 402 403 404
    s->blk = blk;
    s->shared = inc;
    s->mon = NULL;
    s->bandwidth_limit = bandwidth_limit;
405
    s->state = MIG_STATE_SETUP;
406 407 408 409 410 411 412

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

    return s;
}
413 414 415

int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
416
    MigrationState *s = migrate_get_current();
417 418 419 420 421 422 423
    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;

424
    if (s->state == MIG_STATE_ACTIVE) {
425 426 427 428 429 430 431 432
        monitor_printf(mon, "migration already in progress\n");
        return -1;
    }

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

433
    s = migrate_init(mon, detach, blk, inc);
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450

    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;
    }

    if (ret < 0) {
451 452
        monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
        return ret;
453 454
    }

455
    notifier_list_notify(&migration_state_notifiers, s);
456 457 458 459 460
    return 0;
}

int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
461
    migrate_fd_cancel(migrate_get_current());
462 463 464 465 466 467 468 469 470 471 472 473 474
    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;
    }

475
    s = migrate_get_current();
476 477
    s->bandwidth_limit = d;
    qemu_file_set_rate_limit(s->file, s->bandwidth_limit);
478 479 480 481 482 483 484 485 486 487 488 489 490 491 492

    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;
}