]> git.proxmox.com Git - mirror_qemu.git/blame - migration/socket.c
tcg/sparc64: Disable TCG_TARGET_HAS_extr_i64_i32
[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
d99598cc 20#include "qemu/error-report.h"
d984464e 21#include "qapi/error.h"
dd4339c5 22#include "channel.h"
61e8b148 23#include "socket.h"
6666c96a 24#include "migration.h"
08a0aee1 25#include "qemu-file.h"
d984464e 26#include "io/channel-socket.h"
bdd847a0 27#include "io/net-listener.h"
d984464e 28#include "trace.h"
36f62f11 29#include "postcopy-ram.h"
1f0776f1 30#include "options.h"
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
36f62f11
PX
43QIOChannel *socket_send_channel_create_sync(Error **errp)
44{
45 QIOChannelSocket *sioc = qio_channel_socket_new();
46
47 if (!outgoing_args.saddr) {
48 object_unref(OBJECT(sioc));
49 error_setg(errp, "Initial sock address not set!");
50 return NULL;
51 }
52
53 if (qio_channel_socket_connect_sync(sioc, outgoing_args.saddr, errp) < 0) {
54 object_unref(OBJECT(sioc));
55 return NULL;
56 }
57
58 return QIO_CHANNEL(sioc);
59}
60
3854956a
JQ
61int socket_send_channel_destroy(QIOChannel *send)
62{
63 /* Remove channel */
64 object_unref(OBJECT(send));
65 if (outgoing_args.saddr) {
66 qapi_free_SocketAddress(outgoing_args.saddr);
67 outgoing_args.saddr = NULL;
68 }
69 return 0;
70}
71
e1226365
DB
72struct SocketConnectData {
73 MigrationState *s;
74 char *hostname;
75};
76
77static void socket_connect_data_free(void *opaque)
78{
79 struct SocketConnectData *data = opaque;
80 if (!data) {
81 return;
82 }
83 g_free(data->hostname);
84 g_free(data);
85}
86
60e705c5 87static void socket_outgoing_migration(QIOTask *task,
6f860ae7 88 gpointer opaque)
4951f65b 89{
e1226365 90 struct SocketConnectData *data = opaque;
60e705c5
DB
91 QIOChannel *sioc = QIO_CHANNEL(qio_task_get_source(task));
92 Error *err = NULL;
4951f65b 93
60e705c5 94 if (qio_task_propagate_error(task, &err)) {
6f860ae7 95 trace_migration_socket_outgoing_error(error_get_pretty(err));
abb6295b 96 goto out;
4951f65b 97 }
abb6295b
LB
98
99 trace_migration_socket_outgoing_connected(data->hostname);
100
b4bc342c 101 if (migrate_zero_copy_send() &&
5b1d9bab
LB
102 !qio_channel_has_feature(sioc, QIO_CHANNEL_FEATURE_WRITE_ZERO_COPY)) {
103 error_setg(&err, "Zero copy send feature not detected in host kernel");
abb6295b
LB
104 }
105
106out:
688a3dcb 107 migration_channel_connect(data->s, sioc, data->hostname, err);
60e705c5 108 object_unref(OBJECT(sioc));
4951f65b
CL
109}
110
d658f65c
LM
111static void
112socket_start_outgoing_migration_internal(MigrationState *s,
113 SocketAddress *saddr,
114 Error **errp)
4951f65b 115{
6f860ae7 116 QIOChannelSocket *sioc = qio_channel_socket_new();
e1226365 117 struct SocketConnectData *data = g_new0(struct SocketConnectData, 1);
474c624d 118
e1226365 119 data->s = s;
3854956a
JQ
120
121 /* in case previous migration leaked it */
122 qapi_free_SocketAddress(outgoing_args.saddr);
123 outgoing_args.saddr = saddr;
124
bd269ebc
MA
125 if (saddr->type == SOCKET_ADDRESS_TYPE_INET) {
126 data->hostname = g_strdup(saddr->u.inet.host);
e1226365 127 }
474c624d 128
6f01f136 129 qio_channel_set_name(QIO_CHANNEL(sioc), "migration-socket-outgoing");
d984464e
DB
130 qio_channel_socket_connect_async(sioc,
131 saddr,
6f860ae7 132 socket_outgoing_migration,
e1226365 133 data,
8005fdd8
PX
134 socket_connect_data_free,
135 NULL);
4951f65b
CL
136}
137
d658f65c
LM
138void socket_start_outgoing_migration(MigrationState *s,
139 const char *str,
140 Error **errp)
e65c67e4 141{
9308ae54 142 Error *err = NULL;
d658f65c 143 SocketAddress *saddr = socket_parse(str, &err);
9308ae54 144 if (!err) {
d658f65c 145 socket_start_outgoing_migration_internal(s, saddr, &err);
9308ae54
DDAG
146 }
147 error_propagate(errp, err);
e65c67e4
DB
148}
149
bdd847a0
DB
150static void socket_accept_incoming_migration(QIONetListener *listener,
151 QIOChannelSocket *cioc,
152 gpointer opaque)
4951f65b 153{
6f860ae7 154 trace_migration_socket_incoming_accepted();
d984464e 155
428d8908 156 if (migration_has_all_channels()) {
a59136f3
DDAG
157 error_report("%s: Extra incoming migration connection; ignoring",
158 __func__);
159 return;
428d8908 160 }
a59136f3
DDAG
161
162 qio_channel_set_name(QIO_CHANNEL(cioc), "migration-socket-incoming");
163 migration_channel_process_incoming(QIO_CHANNEL(cioc));
4951f65b
CL
164}
165
a59136f3
DDAG
166static void
167socket_incoming_migration_end(void *opaque)
168{
169 QIONetListener *listener = opaque;
170
171 qio_net_listener_disconnect(listener);
172 object_unref(OBJECT(listener));
173}
d984464e 174
d658f65c
LM
175static void
176socket_start_incoming_migration_internal(SocketAddress *saddr,
177 Error **errp)
4951f65b 178{
bdd847a0 179 QIONetListener *listener = qio_net_listener_new();
a59136f3 180 MigrationIncomingState *mis = migration_incoming_get_current();
9aca82ba 181 size_t i;
0705e564 182 int num = 1;
4951f65b 183
bdd847a0 184 qio_net_listener_set_name(listener, "migration-socket-listener");
6f01f136 185
51b07548 186 if (migrate_multifd()) {
0705e564 187 num = migrate_multifd_channels();
36f62f11
PX
188 } else if (migrate_postcopy_preempt()) {
189 num = RAM_CHANNEL_MAX;
0705e564
JQ
190 }
191
192 if (qio_net_listener_open_sync(listener, saddr, num, errp) < 0) {
bdd847a0 193 object_unref(OBJECT(listener));
43eaae28 194 return;
4951f65b
CL
195 }
196
a59136f3
DDAG
197 mis->transport_data = listener;
198 mis->transport_cleanup = socket_incoming_migration_end;
199
e89f5ff2
PX
200 qio_net_listener_set_client_func_full(listener,
201 socket_accept_incoming_migration,
202 NULL, NULL,
203 g_main_context_get_thread_default());
9aca82ba
JQ
204
205 for (i = 0; i < listener->nsioc; i++) {
206 SocketAddress *address =
207 qio_channel_socket_get_local_address(listener->sioc[i], errp);
208 if (!address) {
209 return;
210 }
211 migrate_add_address(address);
5e78bc6a 212 qapi_free_SocketAddress(address);
9aca82ba 213 }
4951f65b 214}
6f860ae7 215
d658f65c 216void socket_start_incoming_migration(const char *str, Error **errp)
e65c67e4 217{
9308ae54 218 Error *err = NULL;
d658f65c 219 SocketAddress *saddr = socket_parse(str, &err);
9308ae54 220 if (!err) {
d658f65c 221 socket_start_incoming_migration_internal(saddr, &err);
9308ae54 222 }
9102d27e 223 qapi_free_SocketAddress(saddr);
9308ae54 224 error_propagate(errp, err);
e65c67e4 225}