root / migration.c @ 29eee86f
History | View | Annotate | Download (15.1 kB)
1 | 5bb7910a | aliguori | /*
|
---|---|---|---|
2 | 5bb7910a | aliguori | * QEMU live migration
|
3 | 5bb7910a | aliguori | *
|
4 | 5bb7910a | aliguori | * Copyright IBM, Corp. 2008
|
5 | 5bb7910a | aliguori | *
|
6 | 5bb7910a | aliguori | * Authors:
|
7 | 5bb7910a | aliguori | * Anthony Liguori <aliguori@us.ibm.com>
|
8 | 5bb7910a | aliguori | *
|
9 | 5bb7910a | aliguori | * This work is licensed under the terms of the GNU GPL, version 2. See
|
10 | 5bb7910a | aliguori | * the COPYING file in the top-level directory.
|
11 | 5bb7910a | aliguori | *
|
12 | 6b620ca3 | Paolo Bonzini | * Contributions after 2012-01-13 are licensed under the terms of the
|
13 | 6b620ca3 | Paolo Bonzini | * GNU GPL, version 2 or (at your option) any later version.
|
14 | 5bb7910a | aliguori | */
|
15 | 5bb7910a | aliguori | |
16 | 5bb7910a | aliguori | #include "qemu-common.h" |
17 | 5bb7910a | aliguori | #include "migration.h" |
18 | 376253ec | aliguori | #include "monitor.h" |
19 | 065e2813 | aliguori | #include "buffered_file.h" |
20 | 065e2813 | aliguori | #include "sysemu.h" |
21 | 065e2813 | aliguori | #include "block.h" |
22 | 065e2813 | aliguori | #include "qemu_socket.h" |
23 | 25f23643 | Jan Kiszka | #include "block-migration.h" |
24 | 791e7c82 | Luiz Capitulino | #include "qmp-commands.h" |
25 | 065e2813 | aliguori | |
26 | 065e2813 | aliguori | //#define DEBUG_MIGRATION
|
27 | 065e2813 | aliguori | |
28 | 065e2813 | aliguori | #ifdef DEBUG_MIGRATION
|
29 | d0f2c4c6 | malc | #define DPRINTF(fmt, ...) \
|
30 | 065e2813 | aliguori | do { printf("migration: " fmt, ## __VA_ARGS__); } while (0) |
31 | 065e2813 | aliguori | #else
|
32 | d0f2c4c6 | malc | #define DPRINTF(fmt, ...) \
|
33 | 065e2813 | aliguori | do { } while (0) |
34 | 065e2813 | aliguori | #endif
|
35 | 5bb7910a | aliguori | |
36 | 7dc688ed | Juan Quintela | enum {
|
37 | 7dc688ed | Juan Quintela | MIG_STATE_ERROR, |
38 | 7dc688ed | Juan Quintela | MIG_STATE_SETUP, |
39 | 7dc688ed | Juan Quintela | MIG_STATE_CANCELLED, |
40 | 7dc688ed | Juan Quintela | MIG_STATE_ACTIVE, |
41 | 7dc688ed | Juan Quintela | MIG_STATE_COMPLETED, |
42 | 7dc688ed | Juan Quintela | }; |
43 | 5bb7910a | aliguori | |
44 | d0ae46c1 | Juan Quintela | #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ |
45 | 5bb7910a | aliguori | |
46 | 17ad9b35 | Orit Wasserman | /* Migration XBZRLE default cache size */
|
47 | 17ad9b35 | Orit Wasserman | #define DEFAULT_MIGRATE_CACHE_SIZE (64 * 1024 * 1024) |
48 | 17ad9b35 | Orit Wasserman | |
49 | 99a0db9b | Gerd Hoffmann | static NotifierList migration_state_notifiers =
|
50 | 99a0db9b | Gerd Hoffmann | NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); |
51 | 99a0db9b | Gerd Hoffmann | |
52 | 17549e84 | Juan Quintela | /* When we add fault tolerance, we could have several
|
53 | 17549e84 | Juan Quintela | migrations at once. For now we don't need to add
|
54 | 17549e84 | Juan Quintela | dynamic creation of migration */
|
55 | 17549e84 | Juan Quintela | |
56 | 859bc756 | Juan Quintela | MigrationState *migrate_get_current(void)
|
57 | 17549e84 | Juan Quintela | { |
58 | 17549e84 | Juan Quintela | static MigrationState current_migration = {
|
59 | 17549e84 | Juan Quintela | .state = MIG_STATE_SETUP, |
60 | d0ae46c1 | Juan Quintela | .bandwidth_limit = MAX_THROTTLE, |
61 | 17ad9b35 | Orit Wasserman | .xbzrle_cache_size = DEFAULT_MIGRATE_CACHE_SIZE, |
62 | 17549e84 | Juan Quintela | }; |
63 | 17549e84 | Juan Quintela | |
64 | 17549e84 | Juan Quintela | return ¤t_migration;
|
65 | 17549e84 | Juan Quintela | } |
66 | 17549e84 | Juan Quintela | |
67 | d5c5dacc | Amos Kong | int qemu_start_incoming_migration(const char *uri, Error **errp) |
68 | 5bb7910a | aliguori | { |
69 | 34c9dd8e | aliguori | const char *p; |
70 | 8ca5e801 | Juan Quintela | int ret;
|
71 | 34c9dd8e | aliguori | |
72 | 34c9dd8e | aliguori | if (strstart(uri, "tcp:", &p)) |
73 | d5c5dacc | Amos Kong | ret = tcp_start_incoming_migration(p, errp); |
74 | 065e2813 | aliguori | #if !defined(WIN32)
|
75 | 065e2813 | aliguori | else if (strstart(uri, "exec:", &p)) |
76 | 8ca5e801 | Juan Quintela | ret = exec_start_incoming_migration(p); |
77 | 4951f65b | Chris Lalancette | else if (strstart(uri, "unix:", &p)) |
78 | 8ca5e801 | Juan Quintela | ret = unix_start_incoming_migration(p); |
79 | 5ac1fad3 | Paolo Bonzini | else if (strstart(uri, "fd:", &p)) |
80 | 8ca5e801 | Juan Quintela | ret = fd_start_incoming_migration(p); |
81 | 065e2813 | aliguori | #endif
|
82 | 8ca5e801 | Juan Quintela | else {
|
83 | 34c9dd8e | aliguori | fprintf(stderr, "unknown migration protocol: %s\n", uri);
|
84 | 8ca5e801 | Juan Quintela | ret = -EPROTONOSUPPORT; |
85 | 8ca5e801 | Juan Quintela | } |
86 | 8ca5e801 | Juan Quintela | return ret;
|
87 | 5bb7910a | aliguori | } |
88 | 5bb7910a | aliguori | |
89 | 511c0231 | Juan Quintela | void process_incoming_migration(QEMUFile *f)
|
90 | 511c0231 | Juan Quintela | { |
91 | 511c0231 | Juan Quintela | if (qemu_loadvm_state(f) < 0) { |
92 | 511c0231 | Juan Quintela | fprintf(stderr, "load of migration failed\n");
|
93 | 511c0231 | Juan Quintela | exit(0);
|
94 | 511c0231 | Juan Quintela | } |
95 | 511c0231 | Juan Quintela | qemu_announce_self(); |
96 | 511c0231 | Juan Quintela | DPRINTF("successfully loaded vm state\n");
|
97 | 511c0231 | Juan Quintela | |
98 | 901862cb | Benoît Canet | bdrv_clear_incoming_migration_all(); |
99 | 0f15423c | Anthony Liguori | /* Make sure all file formats flush their mutable metadata */
|
100 | 0f15423c | Anthony Liguori | bdrv_invalidate_cache_all(); |
101 | 0f15423c | Anthony Liguori | |
102 | f5bbfba1 | Luiz Capitulino | if (autostart) {
|
103 | 511c0231 | Juan Quintela | vm_start(); |
104 | f5bbfba1 | Luiz Capitulino | } else {
|
105 | 0461d5a6 | Luiz Capitulino | runstate_set(RUN_STATE_PRELAUNCH); |
106 | f5bbfba1 | Luiz Capitulino | } |
107 | 511c0231 | Juan Quintela | } |
108 | 511c0231 | Juan Quintela | |
109 | a0a3fd60 | Glauber Costa | /* amount of nanoseconds we are willing to wait for migration to be down.
|
110 | a0a3fd60 | Glauber Costa | * the choice of nanoseconds is because it is the maximum resolution that
|
111 | a0a3fd60 | Glauber Costa | * get_clock() can achieve. It is an internal measure. All user-visible
|
112 | a0a3fd60 | Glauber Costa | * units must be in seconds */
|
113 | a0a3fd60 | Glauber Costa | static uint64_t max_downtime = 30000000; |
114 | a0a3fd60 | Glauber Costa | |
115 | a0a3fd60 | Glauber Costa | uint64_t migrate_max_downtime(void)
|
116 | a0a3fd60 | Glauber Costa | { |
117 | a0a3fd60 | Glauber Costa | return max_downtime;
|
118 | a0a3fd60 | Glauber Costa | } |
119 | a0a3fd60 | Glauber Costa | |
120 | bbf6da32 | Orit Wasserman | MigrationCapabilityStatusList *qmp_query_migrate_capabilities(Error **errp) |
121 | bbf6da32 | Orit Wasserman | { |
122 | bbf6da32 | Orit Wasserman | MigrationCapabilityStatusList *head = NULL;
|
123 | bbf6da32 | Orit Wasserman | MigrationCapabilityStatusList *caps; |
124 | bbf6da32 | Orit Wasserman | MigrationState *s = migrate_get_current(); |
125 | bbf6da32 | Orit Wasserman | int i;
|
126 | bbf6da32 | Orit Wasserman | |
127 | bbf6da32 | Orit Wasserman | for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) { |
128 | bbf6da32 | Orit Wasserman | if (head == NULL) { |
129 | bbf6da32 | Orit Wasserman | head = g_malloc0(sizeof(*caps));
|
130 | bbf6da32 | Orit Wasserman | caps = head; |
131 | bbf6da32 | Orit Wasserman | } else {
|
132 | bbf6da32 | Orit Wasserman | caps->next = g_malloc0(sizeof(*caps));
|
133 | bbf6da32 | Orit Wasserman | caps = caps->next; |
134 | bbf6da32 | Orit Wasserman | } |
135 | bbf6da32 | Orit Wasserman | caps->value = |
136 | bbf6da32 | Orit Wasserman | g_malloc(sizeof(*caps->value));
|
137 | bbf6da32 | Orit Wasserman | caps->value->capability = i; |
138 | bbf6da32 | Orit Wasserman | caps->value->state = s->enabled_capabilities[i]; |
139 | bbf6da32 | Orit Wasserman | } |
140 | bbf6da32 | Orit Wasserman | |
141 | bbf6da32 | Orit Wasserman | return head;
|
142 | bbf6da32 | Orit Wasserman | } |
143 | bbf6da32 | Orit Wasserman | |
144 | f36d55af | Orit Wasserman | static void get_xbzrle_cache_stats(MigrationInfo *info) |
145 | f36d55af | Orit Wasserman | { |
146 | f36d55af | Orit Wasserman | if (migrate_use_xbzrle()) {
|
147 | f36d55af | Orit Wasserman | info->has_xbzrle_cache = true;
|
148 | f36d55af | Orit Wasserman | info->xbzrle_cache = g_malloc0(sizeof(*info->xbzrle_cache));
|
149 | f36d55af | Orit Wasserman | info->xbzrle_cache->cache_size = migrate_xbzrle_cache_size(); |
150 | f36d55af | Orit Wasserman | info->xbzrle_cache->bytes = xbzrle_mig_bytes_transferred(); |
151 | f36d55af | Orit Wasserman | info->xbzrle_cache->pages = xbzrle_mig_pages_transferred(); |
152 | f36d55af | Orit Wasserman | info->xbzrle_cache->cache_miss = xbzrle_mig_pages_cache_miss(); |
153 | f36d55af | Orit Wasserman | info->xbzrle_cache->overflow = xbzrle_mig_pages_overflow(); |
154 | f36d55af | Orit Wasserman | } |
155 | f36d55af | Orit Wasserman | } |
156 | f36d55af | Orit Wasserman | |
157 | 791e7c82 | Luiz Capitulino | MigrationInfo *qmp_query_migrate(Error **errp) |
158 | 5bb7910a | aliguori | { |
159 | 791e7c82 | Luiz Capitulino | MigrationInfo *info = g_malloc0(sizeof(*info));
|
160 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
161 | 17549e84 | Juan Quintela | |
162 | 17549e84 | Juan Quintela | switch (s->state) {
|
163 | 17549e84 | Juan Quintela | case MIG_STATE_SETUP:
|
164 | 17549e84 | Juan Quintela | /* no migration has happened ever */
|
165 | 17549e84 | Juan Quintela | break;
|
166 | 17549e84 | Juan Quintela | case MIG_STATE_ACTIVE:
|
167 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
168 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("active");
|
169 | 7aa939af | Juan Quintela | info->has_total_time = true;
|
170 | 7aa939af | Juan Quintela | info->total_time = qemu_get_clock_ms(rt_clock) |
171 | 7aa939af | Juan Quintela | - s->total_time; |
172 | 2c52ddf1 | Juan Quintela | info->has_expected_downtime = true;
|
173 | 2c52ddf1 | Juan Quintela | info->expected_downtime = s->expected_downtime; |
174 | 17549e84 | Juan Quintela | |
175 | 791e7c82 | Luiz Capitulino | info->has_ram = true;
|
176 | 791e7c82 | Luiz Capitulino | info->ram = g_malloc0(sizeof(*info->ram));
|
177 | 791e7c82 | Luiz Capitulino | info->ram->transferred = ram_bytes_transferred(); |
178 | 791e7c82 | Luiz Capitulino | info->ram->remaining = ram_bytes_remaining(); |
179 | 791e7c82 | Luiz Capitulino | info->ram->total = ram_bytes_total(); |
180 | 004d4c10 | Orit Wasserman | info->ram->duplicate = dup_mig_pages_transferred(); |
181 | 004d4c10 | Orit Wasserman | info->ram->normal = norm_mig_pages_transferred(); |
182 | 004d4c10 | Orit Wasserman | info->ram->normal_bytes = norm_mig_bytes_transferred(); |
183 | 8d017193 | Juan Quintela | info->ram->dirty_pages_rate = s->dirty_pages_rate; |
184 | 8d017193 | Juan Quintela | |
185 | 17549e84 | Juan Quintela | |
186 | 17549e84 | Juan Quintela | if (blk_mig_active()) {
|
187 | 791e7c82 | Luiz Capitulino | info->has_disk = true;
|
188 | 791e7c82 | Luiz Capitulino | info->disk = g_malloc0(sizeof(*info->disk));
|
189 | 791e7c82 | Luiz Capitulino | info->disk->transferred = blk_mig_bytes_transferred(); |
190 | 791e7c82 | Luiz Capitulino | info->disk->remaining = blk_mig_bytes_remaining(); |
191 | 791e7c82 | Luiz Capitulino | info->disk->total = blk_mig_bytes_total(); |
192 | ff8d81d8 | aliguori | } |
193 | f36d55af | Orit Wasserman | |
194 | f36d55af | Orit Wasserman | get_xbzrle_cache_stats(info); |
195 | 17549e84 | Juan Quintela | break;
|
196 | 17549e84 | Juan Quintela | case MIG_STATE_COMPLETED:
|
197 | f36d55af | Orit Wasserman | get_xbzrle_cache_stats(info); |
198 | f36d55af | Orit Wasserman | |
199 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
200 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("completed");
|
201 | 7aa939af | Juan Quintela | info->total_time = s->total_time; |
202 | 9c5a9fcf | Juan Quintela | info->has_downtime = true;
|
203 | 9c5a9fcf | Juan Quintela | info->downtime = s->downtime; |
204 | d5f8a570 | Juan Quintela | |
205 | d5f8a570 | Juan Quintela | info->has_ram = true;
|
206 | d5f8a570 | Juan Quintela | info->ram = g_malloc0(sizeof(*info->ram));
|
207 | d5f8a570 | Juan Quintela | info->ram->transferred = ram_bytes_transferred(); |
208 | d5f8a570 | Juan Quintela | info->ram->remaining = 0;
|
209 | d5f8a570 | Juan Quintela | info->ram->total = ram_bytes_total(); |
210 | 004d4c10 | Orit Wasserman | info->ram->duplicate = dup_mig_pages_transferred(); |
211 | 004d4c10 | Orit Wasserman | info->ram->normal = norm_mig_pages_transferred(); |
212 | 004d4c10 | Orit Wasserman | info->ram->normal_bytes = norm_mig_bytes_transferred(); |
213 | 17549e84 | Juan Quintela | break;
|
214 | 17549e84 | Juan Quintela | case MIG_STATE_ERROR:
|
215 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
216 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("failed");
|
217 | 17549e84 | Juan Quintela | break;
|
218 | 17549e84 | Juan Quintela | case MIG_STATE_CANCELLED:
|
219 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
220 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("cancelled");
|
221 | 17549e84 | Juan Quintela | break;
|
222 | 5bb7910a | aliguori | } |
223 | 791e7c82 | Luiz Capitulino | |
224 | 791e7c82 | Luiz Capitulino | return info;
|
225 | 5bb7910a | aliguori | } |
226 | 5bb7910a | aliguori | |
227 | 00458433 | Orit Wasserman | void qmp_migrate_set_capabilities(MigrationCapabilityStatusList *params,
|
228 | 00458433 | Orit Wasserman | Error **errp) |
229 | 00458433 | Orit Wasserman | { |
230 | 00458433 | Orit Wasserman | MigrationState *s = migrate_get_current(); |
231 | 00458433 | Orit Wasserman | MigrationCapabilityStatusList *cap; |
232 | 00458433 | Orit Wasserman | |
233 | 00458433 | Orit Wasserman | if (s->state == MIG_STATE_ACTIVE) {
|
234 | 00458433 | Orit Wasserman | error_set(errp, QERR_MIGRATION_ACTIVE); |
235 | 00458433 | Orit Wasserman | return;
|
236 | 00458433 | Orit Wasserman | } |
237 | 00458433 | Orit Wasserman | |
238 | 00458433 | Orit Wasserman | for (cap = params; cap; cap = cap->next) {
|
239 | 00458433 | Orit Wasserman | s->enabled_capabilities[cap->value->capability] = cap->value->state; |
240 | 00458433 | Orit Wasserman | } |
241 | 00458433 | Orit Wasserman | } |
242 | 00458433 | Orit Wasserman | |
243 | 065e2813 | aliguori | /* shared migration helpers */
|
244 | 065e2813 | aliguori | |
245 | 8b6b99b3 | Juan Quintela | static int migrate_fd_cleanup(MigrationState *s) |
246 | 065e2813 | aliguori | { |
247 | 41ef56e6 | Anthony Liguori | int ret = 0; |
248 | 41ef56e6 | Anthony Liguori | |
249 | 3202beca | Orit Wasserman | if (s->fd != -1) { |
250 | 3202beca | Orit Wasserman | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
251 | 3202beca | Orit Wasserman | } |
252 | 065e2813 | aliguori | |
253 | 065e2813 | aliguori | if (s->file) {
|
254 | d0f2c4c6 | malc | DPRINTF("closing file\n");
|
255 | a6d34a94 | Eduardo Habkost | ret = qemu_fclose(s->file); |
256 | 5d39c799 | Jan Kiszka | s->file = NULL;
|
257 | 065e2813 | aliguori | } |
258 | 065e2813 | aliguori | |
259 | 84ec6552 | Jan Kiszka | if (s->fd != -1) { |
260 | 065e2813 | aliguori | close(s->fd); |
261 | 84ec6552 | Jan Kiszka | s->fd = -1;
|
262 | f327aa0c | Jan Kiszka | } |
263 | 065e2813 | aliguori | |
264 | 41ef56e6 | Anthony Liguori | return ret;
|
265 | 065e2813 | aliguori | } |
266 | 065e2813 | aliguori | |
267 | 8b6b99b3 | Juan Quintela | void migrate_fd_error(MigrationState *s)
|
268 | 065e2813 | aliguori | { |
269 | 8b6b99b3 | Juan Quintela | DPRINTF("setting error state\n");
|
270 | 8b6b99b3 | Juan Quintela | s->state = MIG_STATE_ERROR; |
271 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
272 | 8b6b99b3 | Juan Quintela | migrate_fd_cleanup(s); |
273 | 8b6b99b3 | Juan Quintela | } |
274 | 8b6b99b3 | Juan Quintela | |
275 | 458cf28e | Juan Quintela | static void migrate_fd_completed(MigrationState *s) |
276 | 458cf28e | Juan Quintela | { |
277 | 458cf28e | Juan Quintela | DPRINTF("setting completed state\n");
|
278 | 458cf28e | Juan Quintela | if (migrate_fd_cleanup(s) < 0) { |
279 | 458cf28e | Juan Quintela | s->state = MIG_STATE_ERROR; |
280 | 458cf28e | Juan Quintela | } else {
|
281 | 458cf28e | Juan Quintela | s->state = MIG_STATE_COMPLETED; |
282 | 458cf28e | Juan Quintela | runstate_set(RUN_STATE_POSTMIGRATE); |
283 | 458cf28e | Juan Quintela | } |
284 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
285 | 458cf28e | Juan Quintela | } |
286 | 458cf28e | Juan Quintela | |
287 | 8b6b99b3 | Juan Quintela | static void migrate_fd_put_notify(void *opaque) |
288 | 065e2813 | aliguori | { |
289 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
290 | 065e2813 | aliguori | |
291 | 065e2813 | aliguori | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
292 | 065e2813 | aliguori | qemu_file_put_notify(s->file); |
293 | 1fdc11c3 | Luiz Capitulino | if (s->file && qemu_file_get_error(s->file)) {
|
294 | 2350e13c | Yoshiaki Tamura | migrate_fd_error(s); |
295 | 2350e13c | Yoshiaki Tamura | } |
296 | 065e2813 | aliguori | } |
297 | 065e2813 | aliguori | |
298 | c87b015b | Juan Quintela | ssize_t migrate_fd_put_buffer(MigrationState *s, const void *data, |
299 | c87b015b | Juan Quintela | size_t size) |
300 | 065e2813 | aliguori | { |
301 | 065e2813 | aliguori | ssize_t ret; |
302 | 065e2813 | aliguori | |
303 | fdbecb5d | Juan Quintela | if (s->state != MIG_STATE_ACTIVE) {
|
304 | fdbecb5d | Juan Quintela | return -EIO;
|
305 | fdbecb5d | Juan Quintela | } |
306 | fdbecb5d | Juan Quintela | |
307 | 065e2813 | aliguori | do {
|
308 | 065e2813 | aliguori | ret = s->write(s, data, size); |
309 | 95b134ea | Uri Lublin | } while (ret == -1 && ((s->get_error(s)) == EINTR)); |
310 | 065e2813 | aliguori | |
311 | 065e2813 | aliguori | if (ret == -1) |
312 | 065e2813 | aliguori | ret = -(s->get_error(s)); |
313 | 065e2813 | aliguori | |
314 | e447b1a6 | Marcelo Tosatti | if (ret == -EAGAIN) {
|
315 | 065e2813 | aliguori | qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); |
316 | e447b1a6 | Marcelo Tosatti | } |
317 | 065e2813 | aliguori | |
318 | 065e2813 | aliguori | return ret;
|
319 | 065e2813 | aliguori | } |
320 | 065e2813 | aliguori | |
321 | 2c9adcb8 | Juan Quintela | void migrate_fd_put_ready(MigrationState *s)
|
322 | 065e2813 | aliguori | { |
323 | 065e2813 | aliguori | int ret;
|
324 | 065e2813 | aliguori | |
325 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE) {
|
326 | d0f2c4c6 | malc | DPRINTF("put_ready returning because of non-active state\n");
|
327 | 065e2813 | aliguori | return;
|
328 | 065e2813 | aliguori | } |
329 | 065e2813 | aliguori | |
330 | d0f2c4c6 | malc | DPRINTF("iterate\n");
|
331 | 539de124 | Luiz Capitulino | ret = qemu_savevm_state_iterate(s->file); |
332 | 39346385 | Juan Quintela | if (ret < 0) { |
333 | 39346385 | Juan Quintela | migrate_fd_error(s); |
334 | 39346385 | Juan Quintela | } else if (ret == 1) { |
335 | 1354869c | Luiz Capitulino | int old_vm_running = runstate_is_running();
|
336 | 9c5a9fcf | Juan Quintela | int64_t start_time, end_time; |
337 | eeb34af9 | Anthony Liguori | |
338 | d0f2c4c6 | malc | DPRINTF("done iterating\n");
|
339 | 9c5a9fcf | Juan Quintela | start_time = qemu_get_clock_ms(rt_clock); |
340 | 7b5d3aa2 | Gerd Hoffmann | qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER); |
341 | 8a9236f1 | Luiz Capitulino | vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); |
342 | 065e2813 | aliguori | |
343 | 539de124 | Luiz Capitulino | if (qemu_savevm_state_complete(s->file) < 0) { |
344 | 67afff79 | Juan Quintela | migrate_fd_error(s); |
345 | b161d123 | aliguori | } else {
|
346 | 458cf28e | Juan Quintela | migrate_fd_completed(s); |
347 | b161d123 | aliguori | } |
348 | 97d4d961 | Juan Quintela | end_time = qemu_get_clock_ms(rt_clock); |
349 | 97d4d961 | Juan Quintela | s->total_time = end_time - s->total_time; |
350 | 9c5a9fcf | Juan Quintela | s->downtime = end_time - start_time; |
351 | 48a2f4d6 | Juan Quintela | if (s->state != MIG_STATE_COMPLETED) {
|
352 | 41ef56e6 | Anthony Liguori | if (old_vm_running) {
|
353 | 41ef56e6 | Anthony Liguori | vm_start(); |
354 | 41ef56e6 | Anthony Liguori | } |
355 | f5bbfba1 | Luiz Capitulino | } |
356 | 065e2813 | aliguori | } |
357 | 065e2813 | aliguori | } |
358 | 065e2813 | aliguori | |
359 | 0edda1c4 | Juan Quintela | static void migrate_fd_cancel(MigrationState *s) |
360 | 065e2813 | aliguori | { |
361 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE)
|
362 | 065e2813 | aliguori | return;
|
363 | 065e2813 | aliguori | |
364 | d0f2c4c6 | malc | DPRINTF("cancelling migration\n");
|
365 | 065e2813 | aliguori | |
366 | 065e2813 | aliguori | s->state = MIG_STATE_CANCELLED; |
367 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
368 | 539de124 | Luiz Capitulino | qemu_savevm_state_cancel(s->file); |
369 | 065e2813 | aliguori | |
370 | 065e2813 | aliguori | migrate_fd_cleanup(s); |
371 | 065e2813 | aliguori | } |
372 | 065e2813 | aliguori | |
373 | 9499743f | Juan Quintela | int migrate_fd_wait_for_unfreeze(MigrationState *s)
|
374 | 065e2813 | aliguori | { |
375 | 065e2813 | aliguori | int ret;
|
376 | 065e2813 | aliguori | |
377 | d0f2c4c6 | malc | DPRINTF("wait for unfreeze\n");
|
378 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE)
|
379 | 9499743f | Juan Quintela | return -EINVAL;
|
380 | 065e2813 | aliguori | |
381 | 065e2813 | aliguori | do {
|
382 | 065e2813 | aliguori | fd_set wfds; |
383 | 065e2813 | aliguori | |
384 | 065e2813 | aliguori | FD_ZERO(&wfds); |
385 | 065e2813 | aliguori | FD_SET(s->fd, &wfds); |
386 | 065e2813 | aliguori | |
387 | 065e2813 | aliguori | ret = select(s->fd + 1, NULL, &wfds, NULL, NULL); |
388 | 065e2813 | aliguori | } while (ret == -1 && (s->get_error(s)) == EINTR); |
389 | af509450 | Juan Quintela | |
390 | af509450 | Juan Quintela | if (ret == -1) { |
391 | 9499743f | Juan Quintela | return -s->get_error(s);
|
392 | af509450 | Juan Quintela | } |
393 | 9499743f | Juan Quintela | return 0; |
394 | 065e2813 | aliguori | } |
395 | 065e2813 | aliguori | |
396 | 11c76741 | Juan Quintela | int migrate_fd_close(MigrationState *s)
|
397 | 065e2813 | aliguori | { |
398 | e19252d3 | Uri Lublin | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
399 | 065e2813 | aliguori | return s->close(s);
|
400 | 065e2813 | aliguori | } |
401 | 99a0db9b | Gerd Hoffmann | |
402 | 99a0db9b | Gerd Hoffmann | void add_migration_state_change_notifier(Notifier *notify)
|
403 | 99a0db9b | Gerd Hoffmann | { |
404 | 99a0db9b | Gerd Hoffmann | notifier_list_add(&migration_state_notifiers, notify); |
405 | 99a0db9b | Gerd Hoffmann | } |
406 | 99a0db9b | Gerd Hoffmann | |
407 | 99a0db9b | Gerd Hoffmann | void remove_migration_state_change_notifier(Notifier *notify)
|
408 | 99a0db9b | Gerd Hoffmann | { |
409 | 31552529 | Paolo Bonzini | notifier_remove(notify); |
410 | 99a0db9b | Gerd Hoffmann | } |
411 | 99a0db9b | Gerd Hoffmann | |
412 | afe2df69 | Gerd Hoffmann | bool migration_is_active(MigrationState *s)
|
413 | afe2df69 | Gerd Hoffmann | { |
414 | afe2df69 | Gerd Hoffmann | return s->state == MIG_STATE_ACTIVE;
|
415 | afe2df69 | Gerd Hoffmann | } |
416 | afe2df69 | Gerd Hoffmann | |
417 | 7073693b | Juan Quintela | bool migration_has_finished(MigrationState *s)
|
418 | 99a0db9b | Gerd Hoffmann | { |
419 | 7073693b | Juan Quintela | return s->state == MIG_STATE_COMPLETED;
|
420 | 99a0db9b | Gerd Hoffmann | } |
421 | 0edda1c4 | Juan Quintela | |
422 | afe2df69 | Gerd Hoffmann | bool migration_has_failed(MigrationState *s)
|
423 | afe2df69 | Gerd Hoffmann | { |
424 | afe2df69 | Gerd Hoffmann | return (s->state == MIG_STATE_CANCELLED ||
|
425 | afe2df69 | Gerd Hoffmann | s->state == MIG_STATE_ERROR); |
426 | afe2df69 | Gerd Hoffmann | } |
427 | afe2df69 | Gerd Hoffmann | |
428 | 8b6b99b3 | Juan Quintela | void migrate_fd_connect(MigrationState *s)
|
429 | 99a0db9b | Gerd Hoffmann | { |
430 | 8b6b99b3 | Juan Quintela | int ret;
|
431 | 8b6b99b3 | Juan Quintela | |
432 | d5934dde | Juan Quintela | s->state = MIG_STATE_ACTIVE; |
433 | 796b4b0f | Juan Quintela | s->file = qemu_fopen_ops_buffered(s); |
434 | 8b6b99b3 | Juan Quintela | |
435 | 8b6b99b3 | Juan Quintela | DPRINTF("beginning savevm\n");
|
436 | 6607ae23 | Isaku Yamahata | ret = qemu_savevm_state_begin(s->file, &s->params); |
437 | 8b6b99b3 | Juan Quintela | if (ret < 0) { |
438 | 8b6b99b3 | Juan Quintela | DPRINTF("failed, %d\n", ret);
|
439 | 8b6b99b3 | Juan Quintela | migrate_fd_error(s); |
440 | 8b6b99b3 | Juan Quintela | return;
|
441 | 8b6b99b3 | Juan Quintela | } |
442 | 8b6b99b3 | Juan Quintela | migrate_fd_put_ready(s); |
443 | 8b6b99b3 | Juan Quintela | } |
444 | 8b6b99b3 | Juan Quintela | |
445 | 6607ae23 | Isaku Yamahata | static MigrationState *migrate_init(const MigrationParams *params) |
446 | 0edda1c4 | Juan Quintela | { |
447 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
448 | d0ae46c1 | Juan Quintela | int64_t bandwidth_limit = s->bandwidth_limit; |
449 | bbf6da32 | Orit Wasserman | bool enabled_capabilities[MIGRATION_CAPABILITY_MAX];
|
450 | 17ad9b35 | Orit Wasserman | int64_t xbzrle_cache_size = s->xbzrle_cache_size; |
451 | bbf6da32 | Orit Wasserman | |
452 | bbf6da32 | Orit Wasserman | memcpy(enabled_capabilities, s->enabled_capabilities, |
453 | bbf6da32 | Orit Wasserman | sizeof(enabled_capabilities));
|
454 | 0edda1c4 | Juan Quintela | |
455 | 17549e84 | Juan Quintela | memset(s, 0, sizeof(*s)); |
456 | d0ae46c1 | Juan Quintela | s->bandwidth_limit = bandwidth_limit; |
457 | 6607ae23 | Isaku Yamahata | s->params = *params; |
458 | bbf6da32 | Orit Wasserman | memcpy(s->enabled_capabilities, enabled_capabilities, |
459 | bbf6da32 | Orit Wasserman | sizeof(enabled_capabilities));
|
460 | 17ad9b35 | Orit Wasserman | s->xbzrle_cache_size = xbzrle_cache_size; |
461 | 1299c631 | Juan Quintela | |
462 | 0edda1c4 | Juan Quintela | s->bandwidth_limit = bandwidth_limit; |
463 | d5934dde | Juan Quintela | s->state = MIG_STATE_SETUP; |
464 | d5f8a570 | Juan Quintela | s->total_time = qemu_get_clock_ms(rt_clock); |
465 | 0edda1c4 | Juan Quintela | |
466 | 0edda1c4 | Juan Quintela | return s;
|
467 | 0edda1c4 | Juan Quintela | } |
468 | cab30143 | Juan Quintela | |
469 | fa2756b7 | Anthony Liguori | static GSList *migration_blockers;
|
470 | fa2756b7 | Anthony Liguori | |
471 | fa2756b7 | Anthony Liguori | void migrate_add_blocker(Error *reason)
|
472 | fa2756b7 | Anthony Liguori | { |
473 | fa2756b7 | Anthony Liguori | migration_blockers = g_slist_prepend(migration_blockers, reason); |
474 | fa2756b7 | Anthony Liguori | } |
475 | fa2756b7 | Anthony Liguori | |
476 | fa2756b7 | Anthony Liguori | void migrate_del_blocker(Error *reason)
|
477 | fa2756b7 | Anthony Liguori | { |
478 | fa2756b7 | Anthony Liguori | migration_blockers = g_slist_remove(migration_blockers, reason); |
479 | fa2756b7 | Anthony Liguori | } |
480 | fa2756b7 | Anthony Liguori | |
481 | e1c37d0e | Luiz Capitulino | void qmp_migrate(const char *uri, bool has_blk, bool blk, |
482 | e1c37d0e | Luiz Capitulino | bool has_inc, bool inc, bool has_detach, bool detach, |
483 | e1c37d0e | Luiz Capitulino | Error **errp) |
484 | cab30143 | Juan Quintela | { |
485 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
486 | 6607ae23 | Isaku Yamahata | MigrationParams params; |
487 | cab30143 | Juan Quintela | const char *p; |
488 | cab30143 | Juan Quintela | int ret;
|
489 | cab30143 | Juan Quintela | |
490 | 6607ae23 | Isaku Yamahata | params.blk = blk; |
491 | 6607ae23 | Isaku Yamahata | params.shared = inc; |
492 | 6607ae23 | Isaku Yamahata | |
493 | 17549e84 | Juan Quintela | if (s->state == MIG_STATE_ACTIVE) {
|
494 | e1c37d0e | Luiz Capitulino | error_set(errp, QERR_MIGRATION_ACTIVE); |
495 | e1c37d0e | Luiz Capitulino | return;
|
496 | cab30143 | Juan Quintela | } |
497 | cab30143 | Juan Quintela | |
498 | e1c37d0e | Luiz Capitulino | if (qemu_savevm_state_blocked(errp)) {
|
499 | e1c37d0e | Luiz Capitulino | return;
|
500 | cab30143 | Juan Quintela | } |
501 | cab30143 | Juan Quintela | |
502 | fa2756b7 | Anthony Liguori | if (migration_blockers) {
|
503 | e1c37d0e | Luiz Capitulino | *errp = error_copy(migration_blockers->data); |
504 | e1c37d0e | Luiz Capitulino | return;
|
505 | fa2756b7 | Anthony Liguori | } |
506 | fa2756b7 | Anthony Liguori | |
507 | 6607ae23 | Isaku Yamahata | s = migrate_init(¶ms); |
508 | cab30143 | Juan Quintela | |
509 | cab30143 | Juan Quintela | if (strstart(uri, "tcp:", &p)) { |
510 | d5c5dacc | Amos Kong | ret = tcp_start_outgoing_migration(s, p, errp); |
511 | cab30143 | Juan Quintela | #if !defined(WIN32)
|
512 | cab30143 | Juan Quintela | } else if (strstart(uri, "exec:", &p)) { |
513 | cab30143 | Juan Quintela | ret = exec_start_outgoing_migration(s, p); |
514 | cab30143 | Juan Quintela | } else if (strstart(uri, "unix:", &p)) { |
515 | cab30143 | Juan Quintela | ret = unix_start_outgoing_migration(s, p); |
516 | cab30143 | Juan Quintela | } else if (strstart(uri, "fd:", &p)) { |
517 | cab30143 | Juan Quintela | ret = fd_start_outgoing_migration(s, p); |
518 | cab30143 | Juan Quintela | #endif
|
519 | 99a0db9b | Gerd Hoffmann | } else {
|
520 | e1c37d0e | Luiz Capitulino | error_set(errp, QERR_INVALID_PARAMETER_VALUE, "uri", "a valid migration protocol"); |
521 | e1c37d0e | Luiz Capitulino | return;
|
522 | cab30143 | Juan Quintela | } |
523 | cab30143 | Juan Quintela | |
524 | cab30143 | Juan Quintela | if (ret < 0) { |
525 | d5c5dacc | Amos Kong | if (!error_is_set(errp)) {
|
526 | d5c5dacc | Amos Kong | DPRINTF("migration failed: %s\n", strerror(-ret));
|
527 | d5c5dacc | Amos Kong | /* FIXME: we should return meaningful errors */
|
528 | d5c5dacc | Amos Kong | error_set(errp, QERR_UNDEFINED_ERROR); |
529 | d5c5dacc | Amos Kong | } |
530 | e1c37d0e | Luiz Capitulino | return;
|
531 | 1299c631 | Juan Quintela | } |
532 | 1299c631 | Juan Quintela | |
533 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
534 | cab30143 | Juan Quintela | } |
535 | cab30143 | Juan Quintela | |
536 | 6cdedb07 | Luiz Capitulino | void qmp_migrate_cancel(Error **errp)
|
537 | cab30143 | Juan Quintela | { |
538 | 17549e84 | Juan Quintela | migrate_fd_cancel(migrate_get_current()); |
539 | cab30143 | Juan Quintela | } |
540 | cab30143 | Juan Quintela | |
541 | 9e1ba4cc | Orit Wasserman | void qmp_migrate_set_cache_size(int64_t value, Error **errp)
|
542 | 9e1ba4cc | Orit Wasserman | { |
543 | 9e1ba4cc | Orit Wasserman | MigrationState *s = migrate_get_current(); |
544 | 9e1ba4cc | Orit Wasserman | |
545 | 9e1ba4cc | Orit Wasserman | /* Check for truncation */
|
546 | 9e1ba4cc | Orit Wasserman | if (value != (size_t)value) {
|
547 | 9e1ba4cc | Orit Wasserman | error_set(errp, QERR_INVALID_PARAMETER_VALUE, "cache size",
|
548 | 9e1ba4cc | Orit Wasserman | "exceeding address space");
|
549 | 9e1ba4cc | Orit Wasserman | return;
|
550 | 9e1ba4cc | Orit Wasserman | } |
551 | 9e1ba4cc | Orit Wasserman | |
552 | 9e1ba4cc | Orit Wasserman | s->xbzrle_cache_size = xbzrle_cache_resize(value); |
553 | 9e1ba4cc | Orit Wasserman | } |
554 | 9e1ba4cc | Orit Wasserman | |
555 | 9e1ba4cc | Orit Wasserman | int64_t qmp_query_migrate_cache_size(Error **errp) |
556 | 9e1ba4cc | Orit Wasserman | { |
557 | 9e1ba4cc | Orit Wasserman | return migrate_xbzrle_cache_size();
|
558 | 9e1ba4cc | Orit Wasserman | } |
559 | 9e1ba4cc | Orit Wasserman | |
560 | 3dc85383 | Luiz Capitulino | void qmp_migrate_set_speed(int64_t value, Error **errp)
|
561 | cab30143 | Juan Quintela | { |
562 | cab30143 | Juan Quintela | MigrationState *s; |
563 | cab30143 | Juan Quintela | |
564 | 3dc85383 | Luiz Capitulino | if (value < 0) { |
565 | 3dc85383 | Luiz Capitulino | value = 0;
|
566 | 99a0db9b | Gerd Hoffmann | } |
567 | cab30143 | Juan Quintela | |
568 | 17549e84 | Juan Quintela | s = migrate_get_current(); |
569 | 3dc85383 | Luiz Capitulino | s->bandwidth_limit = value; |
570 | d0ae46c1 | Juan Quintela | qemu_file_set_rate_limit(s->file, s->bandwidth_limit); |
571 | cab30143 | Juan Quintela | } |
572 | cab30143 | Juan Quintela | |
573 | 4f0a993b | Luiz Capitulino | void qmp_migrate_set_downtime(double value, Error **errp) |
574 | cab30143 | Juan Quintela | { |
575 | 4f0a993b | Luiz Capitulino | value *= 1e9;
|
576 | 4f0a993b | Luiz Capitulino | value = MAX(0, MIN(UINT64_MAX, value));
|
577 | 4f0a993b | Luiz Capitulino | max_downtime = (uint64_t)value; |
578 | 99a0db9b | Gerd Hoffmann | } |
579 | 17ad9b35 | Orit Wasserman | |
580 | 17ad9b35 | Orit Wasserman | int migrate_use_xbzrle(void) |
581 | 17ad9b35 | Orit Wasserman | { |
582 | 17ad9b35 | Orit Wasserman | MigrationState *s; |
583 | 17ad9b35 | Orit Wasserman | |
584 | 17ad9b35 | Orit Wasserman | s = migrate_get_current(); |
585 | 17ad9b35 | Orit Wasserman | |
586 | 17ad9b35 | Orit Wasserman | return s->enabled_capabilities[MIGRATION_CAPABILITY_XBZRLE];
|
587 | 17ad9b35 | Orit Wasserman | } |
588 | 17ad9b35 | Orit Wasserman | |
589 | 17ad9b35 | Orit Wasserman | int64_t migrate_xbzrle_cache_size(void)
|
590 | 17ad9b35 | Orit Wasserman | { |
591 | 17ad9b35 | Orit Wasserman | MigrationState *s; |
592 | 17ad9b35 | Orit Wasserman | |
593 | 17ad9b35 | Orit Wasserman | s = migrate_get_current(); |
594 | 17ad9b35 | Orit Wasserman | |
595 | 17ad9b35 | Orit Wasserman | return s->xbzrle_cache_size;
|
596 | 17ad9b35 | Orit Wasserman | } |