]> git.proxmox.com Git - mirror_qemu.git/blame - migration/socket.c
Revert "vl: Fix to create migration object before block backends again"
[mirror_qemu.git] / migration / socket.c
CommitLineData
4951f65b 1/*
474c624d 2 * QEMU live migration via socket
4951f65b 3 *
d984464e 4 * Copyright Red Hat, Inc. 2009-2016
4951f65b
CL
5 *
6 * Authors:
7 * Chris Lalancette <clalance@redhat.com>
d984464e 8 * Daniel P. Berrange <berrange@redhat.com>
4951f65b
CL
9 *
10 * This work is licensed under the terms of the GNU GPL, version 2. See
11 * the COPYING file in the top-level directory.
12 *
6b620ca3
PB
13 * Contributions after 2012-01-13 are licensed under the terms of the
14 * GNU GPL, version 2 or (at your option) any later version.
4951f65b
CL
15 */
16
1393a485 17#include "qemu/osdep.h"
9aca82ba 18#include "qemu/cutils.h"
d99598cc 19
4951f65b 20#include "qemu-common.h"
d99598cc 21#include "qemu/error-report.h"
d984464e 22#include "qapi/error.h"
dd4339c5 23#include "channel.h"
61e8b148 24#include "socket.h"
6666c96a 25#include "migration.h"
08a0aee1 26#include "qemu-file.h"
d984464e 27#include "io/channel-socket.h"
bdd847a0 28#include "io/net-listener.h"
d984464e 29#include "trace.h"
4951f65b 30
4951f65b 31
3854956a
JQ
32struct SocketOutgoingArgs {
33 SocketAddress *saddr;
34} outgoing_args;
35
36void socket_send_channel_create(QIOTaskFunc f, void *data)
37{
38 QIOChannelSocket *sioc = qio_channel_socket_new();
39 qio_channel_socket_connect_async(sioc, outgoing_args.saddr,
40 f, data, NULL, NULL);
41}
42
43int socket_send_channel_destroy(QIOChannel *send)
44{
45 /* Remove channel */
46 object_unref(OBJECT(send));
47 if (outgoing_args.saddr) {
48 qapi_free_SocketAddress(outgoing_args.saddr);
49 outgoing_args.saddr = NULL;
50 }
51 return 0;
52}
53
bd269ebc 54static SocketAddress *tcp_build_address(const char *host_port, Error **errp)
e65c67e4 55{
bd269ebc 56 SocketAddress *saddr;
e65c67e4 57
bd269ebc
MA
58 saddr = g_new0(SocketAddress, 1);
59 saddr->type = SOCKET_ADDRESS_TYPE_INET;
60
61 if (inet_parse(&saddr->u.inet, host_port, errp)) {
62 qapi_free_SocketAddress(saddr);
e65c67e4
DB
63 return NULL;
64 }
65
e65c67e4
DB
66 return saddr;
67}
68
69
bd269ebc 70static SocketAddress *unix_build_address(const char *path)
d984464e 71{
bd269ebc 72 SocketAddress *saddr;
d984464e 73
bd269ebc
MA
74 saddr = g_new0(SocketAddress, 1);
75 saddr->type = SOCKET_ADDRESS_TYPE_UNIX;
76 saddr->u.q_unix.path = g_strdup(path);
d984464e
DB
77
78 return saddr;
79}
4951f65b 80
d984464e 81
e1226365
DB
82struct SocketConnectData {
83 MigrationState *s;
84 char *hostname;
85};
86
87static void socket_connect_data_free(void *opaque)
88{
89 struct SocketConnectData *data = opaque;
90 if (!data) {
91 return;
92 }
93 g_free(data->hostname);
94 g_free(data);
95}
96
60e705c5 97static void socket_outgoing_migration(QIOTask *task,
6f860ae7 98 gpointer opaque)
4951f65b 99{
e1226365 100 struct SocketConnectData *data = opaque;
60e705c5
DB
101 QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
102 Error *err = NULL;
4951f65b 103
60e705c5 104 if (qio_task_propagate_error(task, &err)) {
6f860ae7 105 trace_migration_socket_outgoing_error(error_get_pretty(err));
e08c95ce 106 } else {
e1226365 107 trace_migration_socket_outgoing_connected(data->hostname);
4951f65b 108 }
688a3dcb 109 migration_channel_connect(data->s, sioc, data->hostname, err);
60e705c5 110 object_unref(OBJECT(sioc));
4951f65b
CL
111}
112
6f860ae7 113static void socket_start_outgoing_migration(MigrationState *s,
bd269ebc 114 SocketAddress *saddr,
6f860ae7 115 Error **errp)
4951f65b 116{
6f860ae7 117 QIOChannelSocket *sioc = qio_channel_socket_new();
e1226365 118 struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
474c624d 119
e1226365 120 data->s = s;
3854956a
JQ
121
122 /* in case previous migration leaked it */
123 qapi_free_SocketAddress(outgoing_args.saddr);
124 outgoing_args.saddr = saddr;
125
bd269ebc
MA
126 if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
127 data->hostname = g_strdup(saddr->u.inet.host);
e1226365 128 }
474c624d 129
6f01f136 130 qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-outgoing");
d984464e
DB
131 qio_channel_socket_connect_async(sioc,
132 saddr,
6f860ae7 133 socket_outgoing_migration,
e1226365 134 data,
8005fdd8
PX
135 socket_connect_data_free,
136 NULL);
4951f65b
CL
137}
138
e65c67e4
DB
139void tcp_start_outgoing_migration(MigrationState *s,
140 const char *host_port,
141 Error **errp)
142{
9308ae54 143 Error *err = NULL;
bd269ebc 144 SocketAddress *saddr = tcp_build_address(host_port, &err);
9308ae54
DDAG
145 if (!err) {
146 socket_start_outgoing_migration(s, saddr, &err);
147 }
148 error_propagate(errp, err);
e65c67e4
DB
149}
150
6f860ae7
DB
151void unix_start_outgoing_migration(MigrationState *s,
152 const char *path,
153 Error **errp)
154{
bd269ebc 155 SocketAddress *saddr = unix_build_address(path);
6f860ae7
DB
156 socket_start_outgoing_migration(s, saddr, errp);
157}
158
d984464e 159
bdd847a0
DB
160static void socket_accept_incoming_migration(QIONetListener *listener,
161 QIOChannelSocket *cioc,
162 gpointer opaque)
4951f65b 163{
6f860ae7 164 trace_migration_socket_incoming_accepted();
d984464e 165
bdd847a0
DB
166 qio_channel_set_name(QIO_CHANNEL(cioc), "migration-socket-incoming");
167 migration_channel_process_incoming(QIO_CHANNEL(cioc));
ab52a824 168
428d8908
JQ
169 if (migration_has_all_channels()) {
170 /* Close listening socket as its no longer needed */
bdd847a0 171 qio_net_listener_disconnect(listener);
bdd847a0 172 object_unref(OBJECT(listener));
428d8908 173 }
4951f65b
CL
174}
175
d984464e 176
bd269ebc 177static void socket_start_incoming_migration(SocketAddress *saddr,
6f860ae7 178 Error **errp)
4951f65b 179{
bdd847a0 180 QIONetListener *listener = qio_net_listener_new();
9aca82ba 181 size_t i;
4951f65b 182
bdd847a0 183 qio_net_listener_set_name(listener, "migration-socket-listener");
6f01f136 184
bdd847a0
DB
185 if (qio_net_listener_open_sync(listener, saddr, errp) < 0) {
186 object_unref(OBJECT(listener));
43eaae28 187 return;
4951f65b
CL
188 }
189
e89f5ff2
PX
190 qio_net_listener_set_client_func_full(listener,
191 socket_accept_incoming_migration,
192 NULL, NULL,
193 g_main_context_get_thread_default());
9aca82ba
JQ
194
195 for (i = 0; i < listener->nsioc; i++) {
196 SocketAddress *address =
197 qio_channel_socket_get_local_address(listener->sioc[i], errp);
198 if (!address) {
199 return;
200 }
201 migrate_add_address(address);
5e78bc6a 202 qapi_free_SocketAddress(address);
9aca82ba 203 }
4951f65b 204}
6f860ae7 205
e65c67e4
DB
206void tcp_start_incoming_migration(const char *host_port, Error **errp)
207{
9308ae54 208 Error *err = NULL;
bd269ebc 209 SocketAddress *saddr = tcp_build_address(host_port, &err);
9308ae54
DDAG
210 if (!err) {
211 socket_start_incoming_migration(saddr, &err);
212 }
9102d27e 213 qapi_free_SocketAddress(saddr);
9308ae54 214 error_propagate(errp, err);
e65c67e4
DB
215}
216
6f860ae7
DB
217void unix_start_incoming_migration(const char *path, Error **errp)
218{
bd269ebc 219 SocketAddress *saddr = unix_build_address(path);
6f860ae7 220 socket_start_incoming_migration(saddr, errp);
9102d27e 221 qapi_free_SocketAddress(saddr);
6f860ae7 222}