root / migration.c @ 19bf7c87
History | View | Annotate | Download (11.8 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 | 5bb7910a | aliguori | */
|
13 | 5bb7910a | aliguori | |
14 | 5bb7910a | aliguori | #include "qemu-common.h" |
15 | 5bb7910a | aliguori | #include "migration.h" |
16 | 376253ec | aliguori | #include "monitor.h" |
17 | 065e2813 | aliguori | #include "buffered_file.h" |
18 | 065e2813 | aliguori | #include "sysemu.h" |
19 | 065e2813 | aliguori | #include "block.h" |
20 | 065e2813 | aliguori | #include "qemu_socket.h" |
21 | 25f23643 | Jan Kiszka | #include "block-migration.h" |
22 | 791e7c82 | Luiz Capitulino | #include "qmp-commands.h" |
23 | 065e2813 | aliguori | |
24 | 065e2813 | aliguori | //#define DEBUG_MIGRATION
|
25 | 065e2813 | aliguori | |
26 | 065e2813 | aliguori | #ifdef DEBUG_MIGRATION
|
27 | d0f2c4c6 | malc | #define DPRINTF(fmt, ...) \
|
28 | 065e2813 | aliguori | do { printf("migration: " fmt, ## __VA_ARGS__); } while (0) |
29 | 065e2813 | aliguori | #else
|
30 | d0f2c4c6 | malc | #define DPRINTF(fmt, ...) \
|
31 | 065e2813 | aliguori | do { } while (0) |
32 | 065e2813 | aliguori | #endif
|
33 | 5bb7910a | aliguori | |
34 | 7dc688ed | Juan Quintela | enum {
|
35 | 7dc688ed | Juan Quintela | MIG_STATE_ERROR, |
36 | 7dc688ed | Juan Quintela | MIG_STATE_SETUP, |
37 | 7dc688ed | Juan Quintela | MIG_STATE_CANCELLED, |
38 | 7dc688ed | Juan Quintela | MIG_STATE_ACTIVE, |
39 | 7dc688ed | Juan Quintela | MIG_STATE_COMPLETED, |
40 | 7dc688ed | Juan Quintela | }; |
41 | 5bb7910a | aliguori | |
42 | d0ae46c1 | Juan Quintela | #define MAX_THROTTLE (32 << 20) /* Migration speed throttling */ |
43 | 5bb7910a | aliguori | |
44 | 99a0db9b | Gerd Hoffmann | static NotifierList migration_state_notifiers =
|
45 | 99a0db9b | Gerd Hoffmann | NOTIFIER_LIST_INITIALIZER(migration_state_notifiers); |
46 | 99a0db9b | Gerd Hoffmann | |
47 | 17549e84 | Juan Quintela | /* When we add fault tolerance, we could have several
|
48 | 17549e84 | Juan Quintela | migrations at once. For now we don't need to add
|
49 | 17549e84 | Juan Quintela | dynamic creation of migration */
|
50 | 17549e84 | Juan Quintela | |
51 | 17549e84 | Juan Quintela | static MigrationState *migrate_get_current(void) |
52 | 17549e84 | Juan Quintela | { |
53 | 17549e84 | Juan Quintela | static MigrationState current_migration = {
|
54 | 17549e84 | Juan Quintela | .state = MIG_STATE_SETUP, |
55 | d0ae46c1 | Juan Quintela | .bandwidth_limit = MAX_THROTTLE, |
56 | 17549e84 | Juan Quintela | }; |
57 | 17549e84 | Juan Quintela | |
58 | 17549e84 | Juan Quintela | return ¤t_migration;
|
59 | 17549e84 | Juan Quintela | } |
60 | 17549e84 | Juan Quintela | |
61 | 8ca5e801 | Juan Quintela | int qemu_start_incoming_migration(const char *uri) |
62 | 5bb7910a | aliguori | { |
63 | 34c9dd8e | aliguori | const char *p; |
64 | 8ca5e801 | Juan Quintela | int ret;
|
65 | 34c9dd8e | aliguori | |
66 | 34c9dd8e | aliguori | if (strstart(uri, "tcp:", &p)) |
67 | 8ca5e801 | Juan Quintela | ret = tcp_start_incoming_migration(p); |
68 | 065e2813 | aliguori | #if !defined(WIN32)
|
69 | 065e2813 | aliguori | else if (strstart(uri, "exec:", &p)) |
70 | 8ca5e801 | Juan Quintela | ret = exec_start_incoming_migration(p); |
71 | 4951f65b | Chris Lalancette | else if (strstart(uri, "unix:", &p)) |
72 | 8ca5e801 | Juan Quintela | ret = unix_start_incoming_migration(p); |
73 | 5ac1fad3 | Paolo Bonzini | else if (strstart(uri, "fd:", &p)) |
74 | 8ca5e801 | Juan Quintela | ret = fd_start_incoming_migration(p); |
75 | 065e2813 | aliguori | #endif
|
76 | 8ca5e801 | Juan Quintela | else {
|
77 | 34c9dd8e | aliguori | fprintf(stderr, "unknown migration protocol: %s\n", uri);
|
78 | 8ca5e801 | Juan Quintela | ret = -EPROTONOSUPPORT; |
79 | 8ca5e801 | Juan Quintela | } |
80 | 8ca5e801 | Juan Quintela | return ret;
|
81 | 5bb7910a | aliguori | } |
82 | 5bb7910a | aliguori | |
83 | 511c0231 | Juan Quintela | void process_incoming_migration(QEMUFile *f)
|
84 | 511c0231 | Juan Quintela | { |
85 | 511c0231 | Juan Quintela | if (qemu_loadvm_state(f) < 0) { |
86 | 511c0231 | Juan Quintela | fprintf(stderr, "load of migration failed\n");
|
87 | 511c0231 | Juan Quintela | exit(0);
|
88 | 511c0231 | Juan Quintela | } |
89 | 511c0231 | Juan Quintela | qemu_announce_self(); |
90 | 511c0231 | Juan Quintela | DPRINTF("successfully loaded vm state\n");
|
91 | 511c0231 | Juan Quintela | |
92 | 0f15423c | Anthony Liguori | /* Make sure all file formats flush their mutable metadata */
|
93 | 0f15423c | Anthony Liguori | bdrv_invalidate_cache_all(); |
94 | 0f15423c | Anthony Liguori | |
95 | f5bbfba1 | Luiz Capitulino | if (autostart) {
|
96 | 511c0231 | Juan Quintela | vm_start(); |
97 | f5bbfba1 | Luiz Capitulino | } else {
|
98 | 0461d5a6 | Luiz Capitulino | runstate_set(RUN_STATE_PRELAUNCH); |
99 | f5bbfba1 | Luiz Capitulino | } |
100 | 511c0231 | Juan Quintela | } |
101 | 511c0231 | Juan Quintela | |
102 | a0a3fd60 | Glauber Costa | /* amount of nanoseconds we are willing to wait for migration to be down.
|
103 | a0a3fd60 | Glauber Costa | * the choice of nanoseconds is because it is the maximum resolution that
|
104 | a0a3fd60 | Glauber Costa | * get_clock() can achieve. It is an internal measure. All user-visible
|
105 | a0a3fd60 | Glauber Costa | * units must be in seconds */
|
106 | a0a3fd60 | Glauber Costa | static uint64_t max_downtime = 30000000; |
107 | a0a3fd60 | Glauber Costa | |
108 | a0a3fd60 | Glauber Costa | uint64_t migrate_max_downtime(void)
|
109 | a0a3fd60 | Glauber Costa | { |
110 | a0a3fd60 | Glauber Costa | return max_downtime;
|
111 | a0a3fd60 | Glauber Costa | } |
112 | a0a3fd60 | Glauber Costa | |
113 | 791e7c82 | Luiz Capitulino | MigrationInfo *qmp_query_migrate(Error **errp) |
114 | 5bb7910a | aliguori | { |
115 | 791e7c82 | Luiz Capitulino | MigrationInfo *info = g_malloc0(sizeof(*info));
|
116 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
117 | 17549e84 | Juan Quintela | |
118 | 17549e84 | Juan Quintela | switch (s->state) {
|
119 | 17549e84 | Juan Quintela | case MIG_STATE_SETUP:
|
120 | 17549e84 | Juan Quintela | /* no migration has happened ever */
|
121 | 17549e84 | Juan Quintela | break;
|
122 | 17549e84 | Juan Quintela | case MIG_STATE_ACTIVE:
|
123 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
124 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("active");
|
125 | 17549e84 | Juan Quintela | |
126 | 791e7c82 | Luiz Capitulino | info->has_ram = true;
|
127 | 791e7c82 | Luiz Capitulino | info->ram = g_malloc0(sizeof(*info->ram));
|
128 | 791e7c82 | Luiz Capitulino | info->ram->transferred = ram_bytes_transferred(); |
129 | 791e7c82 | Luiz Capitulino | info->ram->remaining = ram_bytes_remaining(); |
130 | 791e7c82 | Luiz Capitulino | info->ram->total = ram_bytes_total(); |
131 | 17549e84 | Juan Quintela | |
132 | 17549e84 | Juan Quintela | if (blk_mig_active()) {
|
133 | 791e7c82 | Luiz Capitulino | info->has_disk = true;
|
134 | 791e7c82 | Luiz Capitulino | info->disk = g_malloc0(sizeof(*info->disk));
|
135 | 791e7c82 | Luiz Capitulino | info->disk->transferred = blk_mig_bytes_transferred(); |
136 | 791e7c82 | Luiz Capitulino | info->disk->remaining = blk_mig_bytes_remaining(); |
137 | 791e7c82 | Luiz Capitulino | info->disk->total = blk_mig_bytes_total(); |
138 | ff8d81d8 | aliguori | } |
139 | 17549e84 | Juan Quintela | break;
|
140 | 17549e84 | Juan Quintela | case MIG_STATE_COMPLETED:
|
141 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
142 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("completed");
|
143 | 17549e84 | Juan Quintela | break;
|
144 | 17549e84 | Juan Quintela | case MIG_STATE_ERROR:
|
145 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
146 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("failed");
|
147 | 17549e84 | Juan Quintela | break;
|
148 | 17549e84 | Juan Quintela | case MIG_STATE_CANCELLED:
|
149 | 791e7c82 | Luiz Capitulino | info->has_status = true;
|
150 | 791e7c82 | Luiz Capitulino | info->status = g_strdup("cancelled");
|
151 | 17549e84 | Juan Quintela | break;
|
152 | 5bb7910a | aliguori | } |
153 | 791e7c82 | Luiz Capitulino | |
154 | 791e7c82 | Luiz Capitulino | return info;
|
155 | 5bb7910a | aliguori | } |
156 | 5bb7910a | aliguori | |
157 | 065e2813 | aliguori | /* shared migration helpers */
|
158 | 065e2813 | aliguori | |
159 | 0edda1c4 | Juan Quintela | static void migrate_fd_monitor_suspend(MigrationState *s, Monitor *mon) |
160 | 731b0364 | aliguori | { |
161 | f327aa0c | Jan Kiszka | if (monitor_suspend(mon) == 0) { |
162 | d0f2c4c6 | malc | DPRINTF("suspending monitor\n");
|
163 | f327aa0c | Jan Kiszka | } else {
|
164 | f327aa0c | Jan Kiszka | monitor_printf(mon, "terminal does not allow synchronous "
|
165 | cde76ee1 | aliguori | "migration, continuing detached\n");
|
166 | f327aa0c | Jan Kiszka | } |
167 | 731b0364 | aliguori | } |
168 | 731b0364 | aliguori | |
169 | 8b6b99b3 | Juan Quintela | static int migrate_fd_cleanup(MigrationState *s) |
170 | 065e2813 | aliguori | { |
171 | 41ef56e6 | Anthony Liguori | int ret = 0; |
172 | 41ef56e6 | Anthony Liguori | |
173 | 065e2813 | aliguori | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
174 | 065e2813 | aliguori | |
175 | 065e2813 | aliguori | if (s->file) {
|
176 | d0f2c4c6 | malc | DPRINTF("closing file\n");
|
177 | a6d34a94 | Eduardo Habkost | ret = qemu_fclose(s->file); |
178 | 5d39c799 | Jan Kiszka | s->file = NULL;
|
179 | 84ec6552 | Jan Kiszka | } else {
|
180 | 84ec6552 | Jan Kiszka | if (s->mon) {
|
181 | 84ec6552 | Jan Kiszka | monitor_resume(s->mon); |
182 | 84ec6552 | Jan Kiszka | } |
183 | 065e2813 | aliguori | } |
184 | 065e2813 | aliguori | |
185 | 84ec6552 | Jan Kiszka | if (s->fd != -1) { |
186 | 065e2813 | aliguori | close(s->fd); |
187 | 84ec6552 | Jan Kiszka | s->fd = -1;
|
188 | f327aa0c | Jan Kiszka | } |
189 | 065e2813 | aliguori | |
190 | 41ef56e6 | Anthony Liguori | return ret;
|
191 | 065e2813 | aliguori | } |
192 | 065e2813 | aliguori | |
193 | 8b6b99b3 | Juan Quintela | void migrate_fd_error(MigrationState *s)
|
194 | 065e2813 | aliguori | { |
195 | 8b6b99b3 | Juan Quintela | DPRINTF("setting error state\n");
|
196 | 8b6b99b3 | Juan Quintela | s->state = MIG_STATE_ERROR; |
197 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
198 | 8b6b99b3 | Juan Quintela | migrate_fd_cleanup(s); |
199 | 8b6b99b3 | Juan Quintela | } |
200 | 8b6b99b3 | Juan Quintela | |
201 | 458cf28e | Juan Quintela | static void migrate_fd_completed(MigrationState *s) |
202 | 458cf28e | Juan Quintela | { |
203 | 458cf28e | Juan Quintela | DPRINTF("setting completed state\n");
|
204 | 458cf28e | Juan Quintela | if (migrate_fd_cleanup(s) < 0) { |
205 | 458cf28e | Juan Quintela | s->state = MIG_STATE_ERROR; |
206 | 458cf28e | Juan Quintela | } else {
|
207 | 458cf28e | Juan Quintela | s->state = MIG_STATE_COMPLETED; |
208 | 458cf28e | Juan Quintela | runstate_set(RUN_STATE_POSTMIGRATE); |
209 | 458cf28e | Juan Quintela | } |
210 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
211 | 458cf28e | Juan Quintela | } |
212 | 458cf28e | Juan Quintela | |
213 | 8b6b99b3 | Juan Quintela | static void migrate_fd_put_notify(void *opaque) |
214 | 065e2813 | aliguori | { |
215 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
216 | 065e2813 | aliguori | |
217 | 065e2813 | aliguori | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
218 | 065e2813 | aliguori | qemu_file_put_notify(s->file); |
219 | 1fdc11c3 | Luiz Capitulino | if (s->file && qemu_file_get_error(s->file)) {
|
220 | 2350e13c | Yoshiaki Tamura | migrate_fd_error(s); |
221 | 2350e13c | Yoshiaki Tamura | } |
222 | 065e2813 | aliguori | } |
223 | 065e2813 | aliguori | |
224 | 8b6b99b3 | Juan Quintela | static ssize_t migrate_fd_put_buffer(void *opaque, const void *data, |
225 | 8b6b99b3 | Juan Quintela | size_t size) |
226 | 065e2813 | aliguori | { |
227 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
228 | 065e2813 | aliguori | ssize_t ret; |
229 | 065e2813 | aliguori | |
230 | fdbecb5d | Juan Quintela | if (s->state != MIG_STATE_ACTIVE) {
|
231 | fdbecb5d | Juan Quintela | return -EIO;
|
232 | fdbecb5d | Juan Quintela | } |
233 | fdbecb5d | Juan Quintela | |
234 | 065e2813 | aliguori | do {
|
235 | 065e2813 | aliguori | ret = s->write(s, data, size); |
236 | 95b134ea | Uri Lublin | } while (ret == -1 && ((s->get_error(s)) == EINTR)); |
237 | 065e2813 | aliguori | |
238 | 065e2813 | aliguori | if (ret == -1) |
239 | 065e2813 | aliguori | ret = -(s->get_error(s)); |
240 | 065e2813 | aliguori | |
241 | e447b1a6 | Marcelo Tosatti | if (ret == -EAGAIN) {
|
242 | 065e2813 | aliguori | qemu_set_fd_handler2(s->fd, NULL, NULL, migrate_fd_put_notify, s); |
243 | e447b1a6 | Marcelo Tosatti | } |
244 | 065e2813 | aliguori | |
245 | 065e2813 | aliguori | return ret;
|
246 | 065e2813 | aliguori | } |
247 | 065e2813 | aliguori | |
248 | 8b6b99b3 | Juan Quintela | static void migrate_fd_put_ready(void *opaque) |
249 | 065e2813 | aliguori | { |
250 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
251 | 065e2813 | aliguori | int ret;
|
252 | 065e2813 | aliguori | |
253 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE) {
|
254 | d0f2c4c6 | malc | DPRINTF("put_ready returning because of non-active state\n");
|
255 | 065e2813 | aliguori | return;
|
256 | 065e2813 | aliguori | } |
257 | 065e2813 | aliguori | |
258 | d0f2c4c6 | malc | DPRINTF("iterate\n");
|
259 | 39346385 | Juan Quintela | ret = qemu_savevm_state_iterate(s->mon, s->file); |
260 | 39346385 | Juan Quintela | if (ret < 0) { |
261 | 39346385 | Juan Quintela | migrate_fd_error(s); |
262 | 39346385 | Juan Quintela | } else if (ret == 1) { |
263 | 1354869c | Luiz Capitulino | int old_vm_running = runstate_is_running();
|
264 | eeb34af9 | Anthony Liguori | |
265 | d0f2c4c6 | malc | DPRINTF("done iterating\n");
|
266 | 8a9236f1 | Luiz Capitulino | vm_stop_force_state(RUN_STATE_FINISH_MIGRATE); |
267 | 065e2813 | aliguori | |
268 | 67afff79 | Juan Quintela | if (qemu_savevm_state_complete(s->mon, s->file) < 0) { |
269 | 67afff79 | Juan Quintela | migrate_fd_error(s); |
270 | b161d123 | aliguori | } else {
|
271 | 458cf28e | Juan Quintela | migrate_fd_completed(s); |
272 | b161d123 | aliguori | } |
273 | 48a2f4d6 | Juan Quintela | if (s->state != MIG_STATE_COMPLETED) {
|
274 | 41ef56e6 | Anthony Liguori | if (old_vm_running) {
|
275 | 41ef56e6 | Anthony Liguori | vm_start(); |
276 | 41ef56e6 | Anthony Liguori | } |
277 | f5bbfba1 | Luiz Capitulino | } |
278 | 065e2813 | aliguori | } |
279 | 065e2813 | aliguori | } |
280 | 065e2813 | aliguori | |
281 | 0edda1c4 | Juan Quintela | static void migrate_fd_cancel(MigrationState *s) |
282 | 065e2813 | aliguori | { |
283 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE)
|
284 | 065e2813 | aliguori | return;
|
285 | 065e2813 | aliguori | |
286 | d0f2c4c6 | malc | DPRINTF("cancelling migration\n");
|
287 | 065e2813 | aliguori | |
288 | 065e2813 | aliguori | s->state = MIG_STATE_CANCELLED; |
289 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
290 | f327aa0c | Jan Kiszka | qemu_savevm_state_cancel(s->mon, s->file); |
291 | 065e2813 | aliguori | |
292 | 065e2813 | aliguori | migrate_fd_cleanup(s); |
293 | 065e2813 | aliguori | } |
294 | 065e2813 | aliguori | |
295 | 8b6b99b3 | Juan Quintela | static void migrate_fd_wait_for_unfreeze(void *opaque) |
296 | 065e2813 | aliguori | { |
297 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
298 | 065e2813 | aliguori | int ret;
|
299 | 065e2813 | aliguori | |
300 | d0f2c4c6 | malc | DPRINTF("wait for unfreeze\n");
|
301 | 065e2813 | aliguori | if (s->state != MIG_STATE_ACTIVE)
|
302 | 065e2813 | aliguori | return;
|
303 | 065e2813 | aliguori | |
304 | 065e2813 | aliguori | do {
|
305 | 065e2813 | aliguori | fd_set wfds; |
306 | 065e2813 | aliguori | |
307 | 065e2813 | aliguori | FD_ZERO(&wfds); |
308 | 065e2813 | aliguori | FD_SET(s->fd, &wfds); |
309 | 065e2813 | aliguori | |
310 | 065e2813 | aliguori | ret = select(s->fd + 1, NULL, &wfds, NULL, NULL); |
311 | 065e2813 | aliguori | } while (ret == -1 && (s->get_error(s)) == EINTR); |
312 | af509450 | Juan Quintela | |
313 | af509450 | Juan Quintela | if (ret == -1) { |
314 | dcd1d224 | Juan Quintela | qemu_file_set_error(s->file, -s->get_error(s)); |
315 | af509450 | Juan Quintela | } |
316 | 065e2813 | aliguori | } |
317 | 065e2813 | aliguori | |
318 | 8b6b99b3 | Juan Quintela | static int migrate_fd_close(void *opaque) |
319 | 065e2813 | aliguori | { |
320 | 22f00a44 | Juan Quintela | MigrationState *s = opaque; |
321 | e19252d3 | Uri Lublin | |
322 | 84ec6552 | Jan Kiszka | if (s->mon) {
|
323 | 84ec6552 | Jan Kiszka | monitor_resume(s->mon); |
324 | 84ec6552 | Jan Kiszka | } |
325 | e19252d3 | Uri Lublin | qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); |
326 | 065e2813 | aliguori | return s->close(s);
|
327 | 065e2813 | aliguori | } |
328 | 99a0db9b | Gerd Hoffmann | |
329 | 99a0db9b | Gerd Hoffmann | void add_migration_state_change_notifier(Notifier *notify)
|
330 | 99a0db9b | Gerd Hoffmann | { |
331 | 99a0db9b | Gerd Hoffmann | notifier_list_add(&migration_state_notifiers, notify); |
332 | 99a0db9b | Gerd Hoffmann | } |
333 | 99a0db9b | Gerd Hoffmann | |
334 | 99a0db9b | Gerd Hoffmann | void remove_migration_state_change_notifier(Notifier *notify)
|
335 | 99a0db9b | Gerd Hoffmann | { |
336 | 99a0db9b | Gerd Hoffmann | notifier_list_remove(&migration_state_notifiers, notify); |
337 | 99a0db9b | Gerd Hoffmann | } |
338 | 99a0db9b | Gerd Hoffmann | |
339 | afe2df69 | Gerd Hoffmann | bool migration_is_active(MigrationState *s)
|
340 | afe2df69 | Gerd Hoffmann | { |
341 | afe2df69 | Gerd Hoffmann | return s->state == MIG_STATE_ACTIVE;
|
342 | afe2df69 | Gerd Hoffmann | } |
343 | afe2df69 | Gerd Hoffmann | |
344 | 7073693b | Juan Quintela | bool migration_has_finished(MigrationState *s)
|
345 | 99a0db9b | Gerd Hoffmann | { |
346 | 7073693b | Juan Quintela | return s->state == MIG_STATE_COMPLETED;
|
347 | 99a0db9b | Gerd Hoffmann | } |
348 | 0edda1c4 | Juan Quintela | |
349 | afe2df69 | Gerd Hoffmann | bool migration_has_failed(MigrationState *s)
|
350 | afe2df69 | Gerd Hoffmann | { |
351 | afe2df69 | Gerd Hoffmann | return (s->state == MIG_STATE_CANCELLED ||
|
352 | afe2df69 | Gerd Hoffmann | s->state == MIG_STATE_ERROR); |
353 | afe2df69 | Gerd Hoffmann | } |
354 | afe2df69 | Gerd Hoffmann | |
355 | 8b6b99b3 | Juan Quintela | void migrate_fd_connect(MigrationState *s)
|
356 | 99a0db9b | Gerd Hoffmann | { |
357 | 8b6b99b3 | Juan Quintela | int ret;
|
358 | 8b6b99b3 | Juan Quintela | |
359 | d5934dde | Juan Quintela | s->state = MIG_STATE_ACTIVE; |
360 | 8b6b99b3 | Juan Quintela | s->file = qemu_fopen_ops_buffered(s, |
361 | 8b6b99b3 | Juan Quintela | s->bandwidth_limit, |
362 | 8b6b99b3 | Juan Quintela | migrate_fd_put_buffer, |
363 | 8b6b99b3 | Juan Quintela | migrate_fd_put_ready, |
364 | 8b6b99b3 | Juan Quintela | migrate_fd_wait_for_unfreeze, |
365 | 8b6b99b3 | Juan Quintela | migrate_fd_close); |
366 | 8b6b99b3 | Juan Quintela | |
367 | 8b6b99b3 | Juan Quintela | DPRINTF("beginning savevm\n");
|
368 | 8b6b99b3 | Juan Quintela | ret = qemu_savevm_state_begin(s->mon, s->file, s->blk, s->shared); |
369 | 8b6b99b3 | Juan Quintela | if (ret < 0) { |
370 | 8b6b99b3 | Juan Quintela | DPRINTF("failed, %d\n", ret);
|
371 | 8b6b99b3 | Juan Quintela | migrate_fd_error(s); |
372 | 8b6b99b3 | Juan Quintela | return;
|
373 | 8b6b99b3 | Juan Quintela | } |
374 | 8b6b99b3 | Juan Quintela | migrate_fd_put_ready(s); |
375 | 8b6b99b3 | Juan Quintela | } |
376 | 8b6b99b3 | Juan Quintela | |
377 | d0ae46c1 | Juan Quintela | static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc) |
378 | 0edda1c4 | Juan Quintela | { |
379 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
380 | d0ae46c1 | Juan Quintela | int64_t bandwidth_limit = s->bandwidth_limit; |
381 | 0edda1c4 | Juan Quintela | |
382 | 17549e84 | Juan Quintela | memset(s, 0, sizeof(*s)); |
383 | d0ae46c1 | Juan Quintela | s->bandwidth_limit = bandwidth_limit; |
384 | 0edda1c4 | Juan Quintela | s->blk = blk; |
385 | 0edda1c4 | Juan Quintela | s->shared = inc; |
386 | 1299c631 | Juan Quintela | |
387 | 1299c631 | Juan Quintela | /* s->mon is used for two things:
|
388 | 1299c631 | Juan Quintela | - pass fd in fd migration
|
389 | 1299c631 | Juan Quintela | - suspend/resume monitor for not detached migration
|
390 | 1299c631 | Juan Quintela | */
|
391 | 1299c631 | Juan Quintela | s->mon = mon; |
392 | 0edda1c4 | Juan Quintela | s->bandwidth_limit = bandwidth_limit; |
393 | d5934dde | Juan Quintela | s->state = MIG_STATE_SETUP; |
394 | 0edda1c4 | Juan Quintela | |
395 | 0edda1c4 | Juan Quintela | if (!detach) {
|
396 | 0edda1c4 | Juan Quintela | migrate_fd_monitor_suspend(s, mon); |
397 | 0edda1c4 | Juan Quintela | } |
398 | 0edda1c4 | Juan Quintela | |
399 | 0edda1c4 | Juan Quintela | return s;
|
400 | 0edda1c4 | Juan Quintela | } |
401 | cab30143 | Juan Quintela | |
402 | fa2756b7 | Anthony Liguori | static GSList *migration_blockers;
|
403 | fa2756b7 | Anthony Liguori | |
404 | fa2756b7 | Anthony Liguori | void migrate_add_blocker(Error *reason)
|
405 | fa2756b7 | Anthony Liguori | { |
406 | fa2756b7 | Anthony Liguori | migration_blockers = g_slist_prepend(migration_blockers, reason); |
407 | fa2756b7 | Anthony Liguori | } |
408 | fa2756b7 | Anthony Liguori | |
409 | fa2756b7 | Anthony Liguori | void migrate_del_blocker(Error *reason)
|
410 | fa2756b7 | Anthony Liguori | { |
411 | fa2756b7 | Anthony Liguori | migration_blockers = g_slist_remove(migration_blockers, reason); |
412 | fa2756b7 | Anthony Liguori | } |
413 | fa2756b7 | Anthony Liguori | |
414 | cab30143 | Juan Quintela | int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data) |
415 | cab30143 | Juan Quintela | { |
416 | 17549e84 | Juan Quintela | MigrationState *s = migrate_get_current(); |
417 | cab30143 | Juan Quintela | const char *p; |
418 | cab30143 | Juan Quintela | int detach = qdict_get_try_bool(qdict, "detach", 0); |
419 | cab30143 | Juan Quintela | int blk = qdict_get_try_bool(qdict, "blk", 0); |
420 | cab30143 | Juan Quintela | int inc = qdict_get_try_bool(qdict, "inc", 0); |
421 | cab30143 | Juan Quintela | const char *uri = qdict_get_str(qdict, "uri"); |
422 | cab30143 | Juan Quintela | int ret;
|
423 | cab30143 | Juan Quintela | |
424 | 17549e84 | Juan Quintela | if (s->state == MIG_STATE_ACTIVE) {
|
425 | cab30143 | Juan Quintela | monitor_printf(mon, "migration already in progress\n");
|
426 | cab30143 | Juan Quintela | return -1; |
427 | cab30143 | Juan Quintela | } |
428 | cab30143 | Juan Quintela | |
429 | cab30143 | Juan Quintela | if (qemu_savevm_state_blocked(mon)) {
|
430 | cab30143 | Juan Quintela | return -1; |
431 | cab30143 | Juan Quintela | } |
432 | cab30143 | Juan Quintela | |
433 | fa2756b7 | Anthony Liguori | if (migration_blockers) {
|
434 | fa2756b7 | Anthony Liguori | Error *err = migration_blockers->data; |
435 | fa2756b7 | Anthony Liguori | qerror_report_err(err); |
436 | fa2756b7 | Anthony Liguori | return -1; |
437 | fa2756b7 | Anthony Liguori | } |
438 | fa2756b7 | Anthony Liguori | |
439 | d0ae46c1 | Juan Quintela | s = migrate_init(mon, detach, blk, inc); |
440 | cab30143 | Juan Quintela | |
441 | cab30143 | Juan Quintela | if (strstart(uri, "tcp:", &p)) { |
442 | cab30143 | Juan Quintela | ret = tcp_start_outgoing_migration(s, p); |
443 | cab30143 | Juan Quintela | #if !defined(WIN32)
|
444 | cab30143 | Juan Quintela | } else if (strstart(uri, "exec:", &p)) { |
445 | cab30143 | Juan Quintela | ret = exec_start_outgoing_migration(s, p); |
446 | cab30143 | Juan Quintela | } else if (strstart(uri, "unix:", &p)) { |
447 | cab30143 | Juan Quintela | ret = unix_start_outgoing_migration(s, p); |
448 | cab30143 | Juan Quintela | } else if (strstart(uri, "fd:", &p)) { |
449 | cab30143 | Juan Quintela | ret = fd_start_outgoing_migration(s, p); |
450 | cab30143 | Juan Quintela | #endif
|
451 | 99a0db9b | Gerd Hoffmann | } else {
|
452 | cab30143 | Juan Quintela | monitor_printf(mon, "unknown migration protocol: %s\n", uri);
|
453 | cab30143 | Juan Quintela | ret = -EINVAL; |
454 | cab30143 | Juan Quintela | } |
455 | cab30143 | Juan Quintela | |
456 | cab30143 | Juan Quintela | if (ret < 0) { |
457 | 17549e84 | Juan Quintela | monitor_printf(mon, "migration failed: %s\n", strerror(-ret));
|
458 | 17549e84 | Juan Quintela | return ret;
|
459 | cab30143 | Juan Quintela | } |
460 | cab30143 | Juan Quintela | |
461 | 1299c631 | Juan Quintela | if (detach) {
|
462 | 1299c631 | Juan Quintela | s->mon = NULL;
|
463 | 1299c631 | Juan Quintela | } |
464 | 1299c631 | Juan Quintela | |
465 | e0eb7390 | Juan Quintela | notifier_list_notify(&migration_state_notifiers, s); |
466 | cab30143 | Juan Quintela | return 0; |
467 | cab30143 | Juan Quintela | } |
468 | cab30143 | Juan Quintela | |
469 | 6cdedb07 | Luiz Capitulino | void qmp_migrate_cancel(Error **errp)
|
470 | cab30143 | Juan Quintela | { |
471 | 17549e84 | Juan Quintela | migrate_fd_cancel(migrate_get_current()); |
472 | cab30143 | Juan Quintela | } |
473 | cab30143 | Juan Quintela | |
474 | 3dc85383 | Luiz Capitulino | void qmp_migrate_set_speed(int64_t value, Error **errp)
|
475 | cab30143 | Juan Quintela | { |
476 | cab30143 | Juan Quintela | MigrationState *s; |
477 | cab30143 | Juan Quintela | |
478 | 3dc85383 | Luiz Capitulino | if (value < 0) { |
479 | 3dc85383 | Luiz Capitulino | value = 0;
|
480 | 99a0db9b | Gerd Hoffmann | } |
481 | cab30143 | Juan Quintela | |
482 | 17549e84 | Juan Quintela | s = migrate_get_current(); |
483 | 3dc85383 | Luiz Capitulino | s->bandwidth_limit = value; |
484 | d0ae46c1 | Juan Quintela | qemu_file_set_rate_limit(s->file, s->bandwidth_limit); |
485 | cab30143 | Juan Quintela | } |
486 | cab30143 | Juan Quintela | |
487 | 4f0a993b | Luiz Capitulino | void qmp_migrate_set_downtime(double value, Error **errp) |
488 | cab30143 | Juan Quintela | { |
489 | 4f0a993b | Luiz Capitulino | value *= 1e9;
|
490 | 4f0a993b | Luiz Capitulino | value = MAX(0, MIN(UINT64_MAX, value));
|
491 | 4f0a993b | Luiz Capitulino | max_downtime = (uint64_t)value; |
492 | 99a0db9b | Gerd Hoffmann | } |