mirror of
https://github.com/qemu/qemu.git
synced 2024-11-23 19:03:38 +08:00
live migration: Propagate output monitor to callback handler
In order to allow proper progress reporting to the monitor that initiated the migration, forward the monitor reference through the migration layer down to SaveLiveStateHandler. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
This commit is contained in:
parent
82801d8f4f
commit
f327aa0c60
@ -352,7 +352,7 @@ static void blk_mig_cleanup(void)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int block_save_live(QEMUFile *f, int stage, void *opaque)
|
||||
static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
|
||||
{
|
||||
dprintf("Enter save live stage %d submitted %d transferred %d\n",
|
||||
stage, block_mig_state.submitted, block_mig_state.transferred);
|
||||
|
3
hw/hw.h
3
hw/hw.h
@ -244,7 +244,8 @@ int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
|
||||
|
||||
typedef void SaveSetParamsHandler(int blk_enable, int shared, void * opaque);
|
||||
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
|
||||
typedef int SaveLiveStateHandler(QEMUFile *f, int stage, void *opaque);
|
||||
typedef int SaveLiveStateHandler(Monitor *mon, QEMUFile *f, int stage,
|
||||
void *opaque);
|
||||
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
|
||||
|
||||
int register_savevm(const char *idstr,
|
||||
|
@ -52,7 +52,8 @@ static int exec_close(FdMigrationState *s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
MigrationState *exec_start_outgoing_migration(const char *command,
|
||||
MigrationState *exec_start_outgoing_migration(Monitor *mon,
|
||||
const char *command,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -88,13 +89,14 @@ MigrationState *exec_start_outgoing_migration(const char *command,
|
||||
|
||||
s->mig_state.blk = blk;
|
||||
s->mig_state.shared = inc;
|
||||
|
||||
|
||||
s->state = MIG_STATE_ACTIVE;
|
||||
s->mon_resume = NULL;
|
||||
s->mon = NULL;
|
||||
s->bandwidth_limit = bandwidth_limit;
|
||||
|
||||
if (!detach)
|
||||
migrate_fd_monitor_suspend(s);
|
||||
if (!detach) {
|
||||
migrate_fd_monitor_suspend(s, mon);
|
||||
}
|
||||
|
||||
migrate_fd_connect(s);
|
||||
return &s->mig_state;
|
||||
|
@ -82,13 +82,14 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
|
||||
|
||||
s->mig_state.blk = blk;
|
||||
s->mig_state.shared = inc;
|
||||
|
||||
|
||||
s->state = MIG_STATE_ACTIVE;
|
||||
s->mon_resume = NULL;
|
||||
s->mon = NULL;
|
||||
s->bandwidth_limit = bandwidth_limit;
|
||||
|
||||
if (!detach)
|
||||
migrate_fd_monitor_suspend(s);
|
||||
if (!detach) {
|
||||
migrate_fd_monitor_suspend(s, mon);
|
||||
}
|
||||
|
||||
migrate_fd_connect(s);
|
||||
return &s->mig_state;
|
||||
|
@ -76,7 +76,8 @@ static void tcp_wait_for_connect(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
MigrationState *tcp_start_outgoing_migration(const char *host_port,
|
||||
MigrationState *tcp_start_outgoing_migration(Monitor *mon,
|
||||
const char *host_port,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -102,7 +103,7 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
|
||||
s->mig_state.shared = inc;
|
||||
|
||||
s->state = MIG_STATE_ACTIVE;
|
||||
s->mon_resume = NULL;
|
||||
s->mon = NULL;
|
||||
s->bandwidth_limit = bandwidth_limit;
|
||||
s->fd = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (s->fd == -1) {
|
||||
@ -112,8 +113,9 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
|
||||
|
||||
socket_set_nonblock(s->fd);
|
||||
|
||||
if (!detach)
|
||||
migrate_fd_monitor_suspend(s);
|
||||
if (!detach) {
|
||||
migrate_fd_monitor_suspend(s, mon);
|
||||
}
|
||||
|
||||
do {
|
||||
ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
@ -75,7 +75,8 @@ static void unix_wait_for_connect(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
MigrationState *unix_start_outgoing_migration(const char *path,
|
||||
MigrationState *unix_start_outgoing_migration(Monitor *mon,
|
||||
const char *path,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -101,7 +102,7 @@ MigrationState *unix_start_outgoing_migration(const char *path,
|
||||
s->mig_state.shared = inc;
|
||||
|
||||
s->state = MIG_STATE_ACTIVE;
|
||||
s->mon_resume = NULL;
|
||||
s->mon = NULL;
|
||||
s->bandwidth_limit = bandwidth_limit;
|
||||
s->fd = socket(PF_UNIX, SOCK_STREAM, 0);
|
||||
if (s->fd < 0) {
|
||||
@ -111,8 +112,9 @@ MigrationState *unix_start_outgoing_migration(const char *path,
|
||||
|
||||
socket_set_nonblock(s->fd);
|
||||
|
||||
if (!detach)
|
||||
migrate_fd_monitor_suspend(s);
|
||||
if (!detach) {
|
||||
migrate_fd_monitor_suspend(s, mon);
|
||||
}
|
||||
|
||||
do {
|
||||
ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||
|
30
migration.c
30
migration.c
@ -66,16 +66,16 @@ void do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
}
|
||||
|
||||
if (strstart(uri, "tcp:", &p))
|
||||
s = tcp_start_outgoing_migration(p, max_throttle, detach,
|
||||
s = tcp_start_outgoing_migration(mon, p, max_throttle, detach,
|
||||
(int)qdict_get_int(qdict, "blk"),
|
||||
(int)qdict_get_int(qdict, "inc"));
|
||||
#if !defined(WIN32)
|
||||
else if (strstart(uri, "exec:", &p))
|
||||
s = exec_start_outgoing_migration(p, max_throttle, detach,
|
||||
s = exec_start_outgoing_migration(mon, p, max_throttle, detach,
|
||||
(int)qdict_get_int(qdict, "blk"),
|
||||
(int)qdict_get_int(qdict, "inc"));
|
||||
else if (strstart(uri, "unix:", &p))
|
||||
s = unix_start_outgoing_migration(p, max_throttle, detach,
|
||||
s = unix_start_outgoing_migration(mon, p, max_throttle, detach,
|
||||
(int)qdict_get_int(qdict, "blk"),
|
||||
(int)qdict_get_int(qdict, "inc"));
|
||||
else if (strstart(uri, "fd:", &p))
|
||||
@ -190,14 +190,15 @@ void do_info_migrate(Monitor *mon)
|
||||
|
||||
/* shared migration helpers */
|
||||
|
||||
void migrate_fd_monitor_suspend(FdMigrationState *s)
|
||||
void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon)
|
||||
{
|
||||
s->mon_resume = cur_mon;
|
||||
if (monitor_suspend(cur_mon) == 0)
|
||||
s->mon = mon;
|
||||
if (monitor_suspend(mon) == 0) {
|
||||
dprintf("suspending monitor\n");
|
||||
else
|
||||
monitor_printf(cur_mon, "terminal does not allow synchronous "
|
||||
} else {
|
||||
monitor_printf(mon, "terminal does not allow synchronous "
|
||||
"migration, continuing detached\n");
|
||||
}
|
||||
}
|
||||
|
||||
void migrate_fd_error(FdMigrationState *s)
|
||||
@ -221,8 +222,9 @@ void migrate_fd_cleanup(FdMigrationState *s)
|
||||
close(s->fd);
|
||||
|
||||
/* Don't resume monitor until we've flushed all of the buffers */
|
||||
if (s->mon_resume)
|
||||
monitor_resume(s->mon_resume);
|
||||
if (s->mon) {
|
||||
monitor_resume(s->mon);
|
||||
}
|
||||
|
||||
s->fd = -1;
|
||||
}
|
||||
@ -265,7 +267,7 @@ void migrate_fd_connect(FdMigrationState *s)
|
||||
migrate_fd_close);
|
||||
|
||||
dprintf("beginning savevm\n");
|
||||
ret = qemu_savevm_state_begin(s->file, s->mig_state.blk,
|
||||
ret = qemu_savevm_state_begin(s->mon, s->file, s->mig_state.blk,
|
||||
s->mig_state.shared);
|
||||
if (ret < 0) {
|
||||
dprintf("failed, %d\n", ret);
|
||||
@ -286,7 +288,7 @@ void migrate_fd_put_ready(void *opaque)
|
||||
}
|
||||
|
||||
dprintf("iterate\n");
|
||||
if (qemu_savevm_state_iterate(s->file) == 1) {
|
||||
if (qemu_savevm_state_iterate(s->mon, s->file) == 1) {
|
||||
int state;
|
||||
int old_vm_running = vm_running;
|
||||
|
||||
@ -295,7 +297,7 @@ void migrate_fd_put_ready(void *opaque)
|
||||
|
||||
qemu_aio_flush();
|
||||
bdrv_flush_all();
|
||||
if ((qemu_savevm_state_complete(s->file)) < 0) {
|
||||
if ((qemu_savevm_state_complete(s->mon, s->file)) < 0) {
|
||||
if (old_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
@ -324,7 +326,7 @@ void migrate_fd_cancel(MigrationState *mig_state)
|
||||
dprintf("cancelling migration\n");
|
||||
|
||||
s->state = MIG_STATE_CANCELLED;
|
||||
qemu_savevm_state_cancel(s->file);
|
||||
qemu_savevm_state_cancel(s->mon, s->file);
|
||||
|
||||
migrate_fd_cleanup(s);
|
||||
}
|
||||
|
13
migration.h
13
migration.h
@ -42,7 +42,7 @@ struct FdMigrationState
|
||||
int64_t bandwidth_limit;
|
||||
QEMUFile *file;
|
||||
int fd;
|
||||
Monitor *mon_resume;
|
||||
Monitor *mon;
|
||||
int state;
|
||||
int (*get_error)(struct FdMigrationState*);
|
||||
int (*close)(struct FdMigrationState*);
|
||||
@ -66,7 +66,8 @@ void do_info_migrate(Monitor *mon);
|
||||
|
||||
int exec_start_incoming_migration(const char *host_port);
|
||||
|
||||
MigrationState *exec_start_outgoing_migration(const char *host_port,
|
||||
MigrationState *exec_start_outgoing_migration(Monitor *mon,
|
||||
const char *host_port,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -74,7 +75,8 @@ MigrationState *exec_start_outgoing_migration(const char *host_port,
|
||||
|
||||
int tcp_start_incoming_migration(const char *host_port);
|
||||
|
||||
MigrationState *tcp_start_outgoing_migration(const char *host_port,
|
||||
MigrationState *tcp_start_outgoing_migration(Monitor *mon,
|
||||
const char *host_port,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -82,7 +84,8 @@ MigrationState *tcp_start_outgoing_migration(const char *host_port,
|
||||
|
||||
int unix_start_incoming_migration(const char *path);
|
||||
|
||||
MigrationState *unix_start_outgoing_migration(const char *path,
|
||||
MigrationState *unix_start_outgoing_migration(Monitor *mon,
|
||||
const char *path,
|
||||
int64_t bandwidth_limit,
|
||||
int detach,
|
||||
int blk,
|
||||
@ -97,7 +100,7 @@ MigrationState *fd_start_outgoing_migration(Monitor *mon,
|
||||
int blk,
|
||||
int inc);
|
||||
|
||||
void migrate_fd_monitor_suspend(FdMigrationState *s);
|
||||
void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon);
|
||||
|
||||
void migrate_fd_error(FdMigrationState *s);
|
||||
|
||||
|
31
savevm.c
31
savevm.c
@ -1264,7 +1264,8 @@ static void vmstate_save(QEMUFile *f, SaveStateEntry *se)
|
||||
#define QEMU_VM_SECTION_END 0x03
|
||||
#define QEMU_VM_SECTION_FULL 0x04
|
||||
|
||||
int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
|
||||
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
|
||||
int shared)
|
||||
{
|
||||
SaveStateEntry *se;
|
||||
|
||||
@ -1296,18 +1297,18 @@ int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared)
|
||||
qemu_put_be32(f, se->instance_id);
|
||||
qemu_put_be32(f, se->version_id);
|
||||
|
||||
se->save_live_state(f, QEMU_VM_SECTION_START, se->opaque);
|
||||
se->save_live_state(mon, f, QEMU_VM_SECTION_START, se->opaque);
|
||||
}
|
||||
|
||||
if (qemu_file_has_error(f)) {
|
||||
qemu_savevm_state_cancel(f);
|
||||
qemu_savevm_state_cancel(mon, f);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qemu_savevm_state_iterate(QEMUFile *f)
|
||||
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f)
|
||||
{
|
||||
SaveStateEntry *se;
|
||||
int ret = 1;
|
||||
@ -1320,21 +1321,21 @@ int qemu_savevm_state_iterate(QEMUFile *f)
|
||||
qemu_put_byte(f, QEMU_VM_SECTION_PART);
|
||||
qemu_put_be32(f, se->section_id);
|
||||
|
||||
ret &= !!se->save_live_state(f, QEMU_VM_SECTION_PART, se->opaque);
|
||||
ret &= !!se->save_live_state(mon, f, QEMU_VM_SECTION_PART, se->opaque);
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return 1;
|
||||
|
||||
if (qemu_file_has_error(f)) {
|
||||
qemu_savevm_state_cancel(f);
|
||||
qemu_savevm_state_cancel(mon, f);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int qemu_savevm_state_complete(QEMUFile *f)
|
||||
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f)
|
||||
{
|
||||
SaveStateEntry *se;
|
||||
|
||||
@ -1346,7 +1347,7 @@ int qemu_savevm_state_complete(QEMUFile *f)
|
||||
qemu_put_byte(f, QEMU_VM_SECTION_END);
|
||||
qemu_put_be32(f, se->section_id);
|
||||
|
||||
se->save_live_state(f, QEMU_VM_SECTION_END, se->opaque);
|
||||
se->save_live_state(mon, f, QEMU_VM_SECTION_END, se->opaque);
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||
@ -1378,18 +1379,18 @@ int qemu_savevm_state_complete(QEMUFile *f)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void qemu_savevm_state_cancel(QEMUFile *f)
|
||||
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f)
|
||||
{
|
||||
SaveStateEntry *se;
|
||||
|
||||
QTAILQ_FOREACH(se, &savevm_handlers, entry) {
|
||||
if (se->save_live_state) {
|
||||
se->save_live_state(f, -1, se->opaque);
|
||||
se->save_live_state(mon, f, -1, se->opaque);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int qemu_savevm_state(QEMUFile *f)
|
||||
static int qemu_savevm_state(Monitor *mon, QEMUFile *f)
|
||||
{
|
||||
int saved_vm_running;
|
||||
int ret;
|
||||
@ -1399,17 +1400,17 @@ int qemu_savevm_state(QEMUFile *f)
|
||||
|
||||
bdrv_flush_all();
|
||||
|
||||
ret = qemu_savevm_state_begin(f, 0, 0);
|
||||
ret = qemu_savevm_state_begin(mon, f, 0, 0);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
do {
|
||||
ret = qemu_savevm_state_iterate(f);
|
||||
ret = qemu_savevm_state_iterate(mon, f);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
} while (ret == 0);
|
||||
|
||||
ret = qemu_savevm_state_complete(f);
|
||||
ret = qemu_savevm_state_complete(mon, f);
|
||||
|
||||
out:
|
||||
if (qemu_file_has_error(f))
|
||||
@ -1698,7 +1699,7 @@ void do_savevm(Monitor *mon, const QDict *qdict)
|
||||
monitor_printf(mon, "Could not open VM state file\n");
|
||||
goto the_end;
|
||||
}
|
||||
ret = qemu_savevm_state(f);
|
||||
ret = qemu_savevm_state(mon, f);
|
||||
vm_state_size = qemu_ftell(f);
|
||||
qemu_fclose(f);
|
||||
if (ret < 0) {
|
||||
|
10
sysemu.h
10
sysemu.h
@ -62,11 +62,11 @@ void qemu_announce_self(void);
|
||||
|
||||
void main_loop_wait(int timeout);
|
||||
|
||||
int qemu_savevm_state_begin(QEMUFile *f, int blk_enable, int shared);
|
||||
int qemu_savevm_state_iterate(QEMUFile *f);
|
||||
int qemu_savevm_state_complete(QEMUFile *f);
|
||||
void qemu_savevm_state_cancel(QEMUFile *f);
|
||||
int qemu_savevm_state(QEMUFile *f);
|
||||
int qemu_savevm_state_begin(Monitor *mon, QEMUFile *f, int blk_enable,
|
||||
int shared);
|
||||
int qemu_savevm_state_iterate(Monitor *mon, QEMUFile *f);
|
||||
int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
|
||||
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
|
||||
int qemu_loadvm_state(QEMUFile *f);
|
||||
|
||||
void qemu_errors_to_file(FILE *fp);
|
||||
|
Loading…
Reference in New Issue
Block a user