Introduce tcp_incoming_migration_async(), and register it handle incoming migration asynchronously. MigrateInocming is used to pass argument to tcp_incoming_migration_async(). tcp_start_incoming_migration() allocates FdMigrationState, and returns MigrationState to print incoming migration info.
Signed-off-by: Yoshiaki Tamura <tamura.yoshi...@lab.ntt.co.jp> --- migration-tcp.c | 109 ++++++++++++++++++++++++++++++++++++++++--------------- migration.h | 2 +- 2 files changed, 80 insertions(+), 31 deletions(-) diff --git a/migration-tcp.c b/migration-tcp.c index 95ce722..b55e891 100644 --- a/migration-tcp.c +++ b/migration-tcp.c @@ -137,16 +137,54 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon, return &s->mig_state; } +typedef struct MigrateIncoming { + FdMigrationState *s; + int c; +} MigrateIncoming; + +static void tcp_incoming_migration_async(void *opaque) +{ + MigrateIncoming *p = opaque; + FdMigrationState *s = p->s; + QEMUFile *f = s->file; + int ret; + + ret = qemu_loadvm_state_async(f); + if (ret < 0) { + s->state = MIG_STATE_ERROR; + fprintf(stderr, "load of migration failed\n"); + goto out; + } else if (ret == 0) { + qemu_announce_self(); + s->state = MIG_STATE_COMPLETED; + DPRINTF("successfully loaded vm state\n"); + + if (autostart) { + vm_start(); + } + + goto out; + } + + return; + +out: + qemu_set_fd_handler2(p->c, NULL, NULL, NULL, NULL); + close(p->c); + migrate_fd_cleanup(s); + qemu_free(p); +} + static void tcp_accept_incoming_migration(void *opaque) { struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); - int s = (unsigned long)opaque; - QEMUFile *f; + FdMigrationState *s = opaque; + MigrateIncoming *p; int c, ret; do { - c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen); + c = qemu_accept(s->fd, (struct sockaddr *)&addr, &addrlen); } while (c == -1 && socket_error() == EINTR); DPRINTF("accepted migration\n"); @@ -156,61 +194,72 @@ static void tcp_accept_incoming_migration(void *opaque) return; } - f = qemu_fopen_socket(c); - if (f == NULL) { + p = qemu_mallocz(sizeof(MigrateIncoming)); + p->s = s; + p->c = c; + + s->file = qemu_fopen_socket(c); + if (s->file == NULL) { fprintf(stderr, "could not qemu_fopen socket\n"); goto out; } - ret = qemu_loadvm_state(f); + ret = qemu_loadvm_state_begin(s->file); if (ret < 0) { - fprintf(stderr, "load of migration failed\n"); - goto out_fopen; + goto out; } - qemu_announce_self(); - DPRINTF("successfully loaded vm state\n"); - if (autostart) - vm_start(); + qemu_set_fd_handler2(c, NULL, tcp_incoming_migration_async, NULL, p); + + return; -out_fopen: - qemu_fclose(f); out: - qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL); - close(s); close(c); + migrate_fd_release(&s->mig_state); + qemu_free(p); } -int tcp_start_incoming_migration(const char *host_port) +MigrationState *tcp_start_incoming_migration(const char *host_port) { struct sockaddr_in addr; + FdMigrationState *s; int val; - int s; if (parse_host_port(&addr, host_port) < 0) { fprintf(stderr, "invalid host/port combination: %s\n", host_port); - return -EINVAL; + return NULL; } - s = qemu_socket(PF_INET, SOCK_STREAM, 0); - if (s == -1) - return -socket_error(); + s = qemu_mallocz(sizeof(*s)); + + s->get_error = socket_errno; + s->close = tcp_close; + s->mig_state.cancel = migrate_fd_cancel; + s->mig_state.get_status = migrate_fd_get_status; + s->mig_state.release = migrate_fd_release; + s->state = MIG_STATE_ACTIVE; + + s->fd = qemu_socket(PF_INET, SOCK_STREAM, 0); + if (s->fd == -1) { + qemu_free(s); + return NULL; + } val = 1; - setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); + setsockopt(s->fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, + sizeof(val)); - if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) + if (bind(s->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) goto err; - if (listen(s, 1) == -1) + if (listen(s->fd, 1) == -1) goto err; - qemu_set_fd_handler2(s, NULL, tcp_accept_incoming_migration, NULL, - (void *)(unsigned long)s); + qemu_set_fd_handler2(s->fd, NULL, tcp_accept_incoming_migration, NULL, s); - return 0; + return &s->mig_state; err: - close(s); - return -socket_error(); + migrate_fd_release(&s->mig_state); + return NULL; } diff --git a/migration.h b/migration.h index 385423f..c11e6db 100644 --- a/migration.h +++ b/migration.h @@ -76,7 +76,7 @@ MigrationState *exec_start_outgoing_migration(Monitor *mon, int blk, int inc); -int tcp_start_incoming_migration(const char *host_port); +MigrationState *tcp_start_incoming_migration(const char *host_port); MigrationState *tcp_start_outgoing_migration(Monitor *mon, const char *host_port, -- 1.7.0.31.g1df487