migration.c 11.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
#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 35 36 37 38

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

static MigrationState *current_migration;

J
Juan Quintela 已提交
39
int qemu_start_incoming_migration(const char *uri)
A
aliguori 已提交
40
{
A
aliguori 已提交
41
    const char *p;
J
Juan Quintela 已提交
42
    int ret;
A
aliguori 已提交
43 44

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

61 62 63 64 65 66 67 68 69 70 71 72 73
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");

    if (autostart)
        vm_start();
}

74
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
75
{
A
aliguori 已提交
76 77
    MigrationState *s = NULL;
    const char *p;
78 79
    int detach = qdict_get_int(qdict, "detach");
    const char *uri = qdict_get_str(qdict, "uri");
80 81 82 83

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

87
    if (strstart(uri, "tcp:", &p)) {
88
        s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
89 90
                                         (int)qdict_get_int(qdict, "blk"), 
                                         (int)qdict_get_int(qdict, "inc"));
91
#if !defined(WIN32)
92
    } else if (strstart(uri, "exec:", &p)) {
93
        s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
94 95
                                          (int)qdict_get_int(qdict, "blk"), 
                                          (int)qdict_get_int(qdict, "inc"));
96
    } else if (strstart(uri, "unix:", &p)) {
97
        s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
L
lirans@il.ibm.com 已提交
98 99
					  (int)qdict_get_int(qdict, "blk"), 
                                          (int)qdict_get_int(qdict, "inc"));
100
    } else if (strstart(uri, "fd:", &p)) {
L
lirans@il.ibm.com 已提交
101 102 103
        s = fd_start_outgoing_migration(mon, p, max_throttle, detach, 
                                        (int)qdict_get_int(qdict, "blk"), 
                                        (int)qdict_get_int(qdict, "inc"));
104
#endif
105
    } else {
A
aliguori 已提交
106
        monitor_printf(mon, "unknown migration protocol: %s\n", uri);
107 108
        return -1;
    }
A
aliguori 已提交
109

110
    if (s == NULL) {
A
aliguori 已提交
111
        monitor_printf(mon, "migration failed\n");
112 113
        return -1;
    }
A
aliguori 已提交
114

115 116
    if (current_migration) {
        current_migration->release(current_migration);
A
aliguori 已提交
117
    }
118 119 120

    current_migration = s;
    return 0;
A
aliguori 已提交
121 122
}

123
int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
124 125 126 127
{
    MigrationState *s = current_migration;

    if (s)
A
aliguori 已提交
128
        s->cancel(s);
129 130

    return 0;
A
aliguori 已提交
131 132
}

133
int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
134 135
{
    double d;
136
    FdMigrationState *s;
A
aliguori 已提交
137

138 139 140
    d = qdict_get_double(qdict, "value");
    d = MAX(0, MIN(UINT32_MAX, d));
    max_throttle = d;
141

142 143
    s = migrate_to_fms(current_migration);
    if (s && s->file) {
144 145
        qemu_file_set_rate_limit(s->file, max_throttle);
    }
146 147

    return 0;
A
aliguori 已提交
148 149
}

150 151 152 153 154 155 156 157 158 159 160
/* 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;
}

161 162
int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
                            QObject **ret_data)
G
Glauber Costa 已提交
163 164 165
{
    double d;

166 167
    d = qdict_get_double(qdict, "value") * 1e9;
    d = MAX(0, MIN(UINT64_MAX, d));
G
Glauber Costa 已提交
168
    max_downtime = (uint64_t)d;
169 170

    return 0;
G
Glauber Costa 已提交
171 172
}

173 174
static void migrate_print_status(Monitor *mon, const char *name,
                                 const QDict *status_dict)
A
aliguori 已提交
175
{
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    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 已提交
220
    MigrationState *s = current_migration;
A
aliguori 已提交
221

A
aliguori 已提交
222
    if (s) {
A
aliguori 已提交
223 224
        switch (s->get_status(s)) {
        case MIG_STATE_ACTIVE:
225 226 227 228 229 230
            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());

231
            if (blk_mig_active()) {
232 233 234
                migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
                                   blk_mig_bytes_remaining(),
                                   blk_mig_bytes_total());
235
            }
236 237

            *ret_data = QOBJECT(qdict);
A
aliguori 已提交
238 239
            break;
        case MIG_STATE_COMPLETED:
240
            *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
A
aliguori 已提交
241 242
            break;
        case MIG_STATE_ERROR:
243
            *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
A
aliguori 已提交
244 245
            break;
        case MIG_STATE_CANCELLED:
246
            *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
A
aliguori 已提交
247 248
            break;
        }
A
aliguori 已提交
249 250 251
    }
}

252 253
/* shared migration helpers */

254
void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
255
{
256 257
    s->mon = mon;
    if (monitor_suspend(mon) == 0) {
M
malc 已提交
258
        DPRINTF("suspending monitor\n");
259 260
    } else {
        monitor_printf(mon, "terminal does not allow synchronous "
261
                       "migration, continuing detached\n");
262
    }
263 264
}

265 266
void migrate_fd_error(FdMigrationState *s)
{
M
malc 已提交
267
    DPRINTF("setting error state\n");
268 269 270 271
    s->state = MIG_STATE_ERROR;
    migrate_fd_cleanup(s);
}

272
int migrate_fd_cleanup(FdMigrationState *s)
273
{
274 275
    int ret = 0;

276 277 278
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    if (s->file) {
M
malc 已提交
279
        DPRINTF("closing file\n");
280 281 282
        if (qemu_fclose(s->file) != 0) {
            ret = -1;
        }
283
        s->file = NULL;
284 285 286 287 288 289
    }

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

    /* Don't resume monitor until we've flushed all of the buffers */
290 291 292
    if (s->mon) {
        monitor_resume(s->mon);
    }
293 294

    s->fd = -1;
295 296

    return ret;
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
}

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);
314
    } while (ret == -1 && ((s->get_error(s)) == EINTR));
315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335

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

M
malc 已提交
336
    DPRINTF("beginning savevm\n");
337
    ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
L
lirans@il.ibm.com 已提交
338
                                  s->mig_state.shared);
339
    if (ret < 0) {
M
malc 已提交
340
        DPRINTF("failed, %d\n", ret);
341 342 343
        migrate_fd_error(s);
        return;
    }
L
lirans@il.ibm.com 已提交
344
    
345 346 347 348 349 350 351 352
    migrate_fd_put_ready(s);
}

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

    if (s->state != MIG_STATE_ACTIVE) {
M
malc 已提交
353
        DPRINTF("put_ready returning because of non-active state\n");
354 355 356
        return;
    }

M
malc 已提交
357
    DPRINTF("iterate\n");
358
    if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
359
        int state;
360 361
        int old_vm_running = vm_running;

M
malc 已提交
362
        DPRINTF("done iterating\n");
363 364
        vm_stop(0);

G
Glauber Costa 已提交
365
        qemu_aio_flush();
366
        bdrv_flush_all();
367
        if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
368 369 370
            if (old_vm_running) {
                vm_start();
            }
371 372 373 374
            state = MIG_STATE_ERROR;
        } else {
            state = MIG_STATE_COMPLETED;
        }
375 376 377 378 379 380
        if (migrate_fd_cleanup(s) < 0) {
            if (old_vm_running) {
                vm_start();
            }
            state = MIG_STATE_ERROR;
        }
381
        s->state = state;
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
    }
}

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;

M
malc 已提交
398
    DPRINTF("cancelling migration\n");
399 400

    s->state = MIG_STATE_CANCELLED;
401
    qemu_savevm_state_cancel(s->mon, s->file);
402 403 404 405 406 407 408 409

    migrate_fd_cleanup(s);
}

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

M
malc 已提交
410
    DPRINTF("releasing state\n");
411 412 413 414 415
   
    if (s->state == MIG_STATE_ACTIVE) {
        s->state = MIG_STATE_CANCELLED;
        migrate_fd_cleanup(s);
    }
416
    qemu_free(s);
417 418 419 420 421 422 423
}

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

M
malc 已提交
424
    DPRINTF("wait for unfreeze\n");
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    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;
441 442

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
443 444
    return s->close(s);
}