- int ret;
-
- s->file = qemu_fopen_ops_buffered(s,
- s->bandwidth_limit,
- fd_put_buffer,
- fd_put_ready,
- fd_wait_for_unfreeze,
- fd_close);
-
- dprintf("beginning savevm\n");
- ret = qemu_savevm_state_begin(s->file);
- if (ret < 0) {
- dprintf("failed, %d\n", ret);
- tcp_error(s);
- return;
- }
-
- fd_put_ready(s);
-}
-
-static void tcp_wait_for_connect(void *opaque)
-{
- FdMigrationState *s = opaque;
- int val, ret;
- socklen_t valsize = sizeof(val);
-
- dprintf("connect completed\n");
- do {
- ret = getsockopt(s->fd, SOL_SOCKET, SO_ERROR, &val, &valsize);
- } while (ret == -1 && socket_error() == EINTR);
-
- if (ret < 0) {
- tcp_error(s);
- return;
- }
-
- qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
-
- if (val == 0)
- tcp_connect_migrate(s);
- else {
- dprintf("error connecting %d\n", val);
- tcp_error(s);
- }
-}
-
-static FdMigrationState *to_fms(MigrationState *mig_state)
-{
- return container_of(mig_state, FdMigrationState, mig_state);
-}
-
-static int tcp_get_status(MigrationState *mig_state)
-{
- FdMigrationState *s = to_fms(mig_state);
-
- return s->state;
-}
-
-static void tcp_cancel(MigrationState *mig_state)
-{
- FdMigrationState *s = to_fms(mig_state);
-
- if (s->state != MIG_STATE_ACTIVE)
- return;
-
- dprintf("cancelling migration\n");
-
- s->state = MIG_STATE_CANCELLED;
-
- tcp_cleanup(s);
-}
-
-static void tcp_release(MigrationState *mig_state)
-{
- FdMigrationState *s = to_fms(mig_state);
-
- dprintf("releasing state\n");
-
- if (s->state == MIG_STATE_ACTIVE) {
- s->state = MIG_STATE_CANCELLED;
- tcp_cleanup(s);
- }
- free(s);
-}
-
-MigrationState *tcp_start_outgoing_migration(const char *host_port,
- int64_t bandwidth_limit,
- int async)
-{
- struct sockaddr_in addr;
- FdMigrationState *s;
- int ret;
-
- if (parse_host_port(&addr, host_port) < 0)
- return NULL;
-
- s = qemu_mallocz(sizeof(*s));
- if (s == NULL)
- return NULL;
-
- s->mig_state.cancel = tcp_cancel;
- s->mig_state.get_status = tcp_get_status;
- s->mig_state.release = tcp_release;
-
- s->state = MIG_STATE_ACTIVE;
- s->detach = !async;
- s->bandwidth_limit = bandwidth_limit;
- s->fd = socket(PF_INET, SOCK_STREAM, 0);
- if (s->fd == -1) {
- qemu_free(s);
- return NULL;
- }
-
- socket_set_nonblock(s->fd);
-
- if (s->detach == 1) {
- dprintf("detaching from monitor\n");
- monitor_suspend();
- s->detach = 2;
- }
-
- do {
- ret = connect(s->fd, (struct sockaddr *)&addr, sizeof(addr));
- if (ret == -1)
- ret = -socket_error();
-
- if (ret == -EINPROGRESS || ret == -EWOULDBLOCK)
- qemu_set_fd_handler2(s->fd, NULL, NULL, tcp_wait_for_connect, s);
- } while (ret == -EINTR);
-
- if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
- dprintf("connect failed\n");
- close(s->fd);
- qemu_free(s);
- return NULL;
- } else if (ret >= 0)
- tcp_connect_migrate(s);
-
- return &s->mig_state;