migration.c 11.0 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 39 40

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

static MigrationState *current_migration;

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

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

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

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

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

93
    if (s == NULL) {
A
aliguori 已提交
94
        monitor_printf(mon, "migration failed\n");
95 96
        return -1;
    }
A
aliguori 已提交
97

98 99
    if (current_migration) {
        current_migration->release(current_migration);
A
aliguori 已提交
100
    }
101 102 103

    current_migration = s;
    return 0;
A
aliguori 已提交
104 105
}

106
int do_migrate_cancel(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
107 108 109 110
{
    MigrationState *s = current_migration;

    if (s)
A
aliguori 已提交
111
        s->cancel(s);
112 113

    return 0;
A
aliguori 已提交
114 115
}

116
int do_migrate_set_speed(Monitor *mon, const QDict *qdict, QObject **ret_data)
A
aliguori 已提交
117 118
{
    double d;
119
    FdMigrationState *s;
A
aliguori 已提交
120

121 122 123
    d = qdict_get_double(qdict, "value");
    d = MAX(0, MIN(UINT32_MAX, d));
    max_throttle = d;
124

125 126
    s = migrate_to_fms(current_migration);
    if (s && s->file) {
127 128
        qemu_file_set_rate_limit(s->file, max_throttle);
    }
129 130

    return 0;
A
aliguori 已提交
131 132
}

133 134 135 136 137 138 139 140 141 142 143
/* 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;
}

144 145
int do_migrate_set_downtime(Monitor *mon, const QDict *qdict,
                            QObject **ret_data)
G
Glauber Costa 已提交
146 147 148
{
    double d;

149 150
    d = qdict_get_double(qdict, "value") * 1e9;
    d = MAX(0, MIN(UINT64_MAX, d));
G
Glauber Costa 已提交
151
    max_downtime = (uint64_t)d;
152 153

    return 0;
G
Glauber Costa 已提交
154 155
}

156 157
static void migrate_print_status(Monitor *mon, const char *name,
                                 const QDict *status_dict)
A
aliguori 已提交
158
{
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 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
    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 已提交
203
    MigrationState *s = current_migration;
A
aliguori 已提交
204

A
aliguori 已提交
205
    if (s) {
A
aliguori 已提交
206 207
        switch (s->get_status(s)) {
        case MIG_STATE_ACTIVE:
208 209 210 211 212 213
            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());

214
            if (blk_mig_active()) {
215 216 217
                migrate_put_status(qdict, "disk", blk_mig_bytes_transferred(),
                                   blk_mig_bytes_remaining(),
                                   blk_mig_bytes_total());
218
            }
219 220

            *ret_data = QOBJECT(qdict);
A
aliguori 已提交
221 222
            break;
        case MIG_STATE_COMPLETED:
223
            *ret_data = qobject_from_jsonf("{ 'status': 'completed' }");
A
aliguori 已提交
224 225
            break;
        case MIG_STATE_ERROR:
226
            *ret_data = qobject_from_jsonf("{ 'status': 'failed' }");
A
aliguori 已提交
227 228
            break;
        case MIG_STATE_CANCELLED:
229
            *ret_data = qobject_from_jsonf("{ 'status': 'cancelled' }");
A
aliguori 已提交
230 231
            break;
        }
A
aliguori 已提交
232 233 234
    }
}

235 236
/* shared migration helpers */

237
void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
238
{
239 240
    s->mon = mon;
    if (monitor_suspend(mon) == 0) {
M
malc 已提交
241
        DPRINTF("suspending monitor\n");
242 243
    } else {
        monitor_printf(mon, "terminal does not allow synchronous "
244
                       "migration, continuing detached\n");
245
    }
246 247
}

248 249
void migrate_fd_error(FdMigrationState *s)
{
M
malc 已提交
250
    DPRINTF("setting error state\n");
251 252 253 254
    s->state = MIG_STATE_ERROR;
    migrate_fd_cleanup(s);
}

255
int migrate_fd_cleanup(FdMigrationState *s)
256
{
257 258
    int ret = 0;

259 260 261
    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);

    if (s->file) {
M
malc 已提交
262
        DPRINTF("closing file\n");
263 264 265
        if (qemu_fclose(s->file) != 0) {
            ret = -1;
        }
266
        s->file = NULL;
267 268 269 270 271 272
    }

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

    /* Don't resume monitor until we've flushed all of the buffers */
273 274 275
    if (s->mon) {
        monitor_resume(s->mon);
    }
276 277

    s->fd = -1;
278 279

    return ret;
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
}

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);
297
    } while (ret == -1 && ((s->get_error(s)) == EINTR));
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318

    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 已提交
319
    DPRINTF("beginning savevm\n");
320
    ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
L
lirans@il.ibm.com 已提交
321
                                  s->mig_state.shared);
322
    if (ret < 0) {
M
malc 已提交
323
        DPRINTF("failed, %d\n", ret);
324 325 326
        migrate_fd_error(s);
        return;
    }
L
lirans@il.ibm.com 已提交
327
    
328 329 330 331 332 333 334 335
    migrate_fd_put_ready(s);
}

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

    if (s->state != MIG_STATE_ACTIVE) {
M
malc 已提交
336
        DPRINTF("put_ready returning because of non-active state\n");
337 338 339
        return;
    }

M
malc 已提交
340
    DPRINTF("iterate\n");
341
    if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
342
        int state;
343 344
        int old_vm_running = vm_running;

M
malc 已提交
345
        DPRINTF("done iterating\n");
346 347
        vm_stop(0);

G
Glauber Costa 已提交
348
        qemu_aio_flush();
349
        bdrv_flush_all();
350
        if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
351 352 353
            if (old_vm_running) {
                vm_start();
            }
354 355 356 357
            state = MIG_STATE_ERROR;
        } else {
            state = MIG_STATE_COMPLETED;
        }
358 359 360 361 362 363
        if (migrate_fd_cleanup(s) < 0) {
            if (old_vm_running) {
                vm_start();
            }
            state = MIG_STATE_ERROR;
        }
364
        s->state = state;
365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    }
}

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 已提交
381
    DPRINTF("cancelling migration\n");
382 383

    s->state = MIG_STATE_CANCELLED;
384
    qemu_savevm_state_cancel(s->mon, s->file);
385 386 387 388 389 390 391 392

    migrate_fd_cleanup(s);
}

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

M
malc 已提交
393
    DPRINTF("releasing state\n");
394 395 396 397 398
   
    if (s->state == MIG_STATE_ACTIVE) {
        s->state = MIG_STATE_CANCELLED;
        migrate_fd_cleanup(s);
    }
399
    qemu_free(s);
400 401 402 403 404 405 406
}

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

M
malc 已提交
407
    DPRINTF("wait for unfreeze\n");
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
    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;
424 425

    qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
426 427
    return s->close(s);
}