Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 644 lines (520 sloc) 17.186 kb
c163b5c Block live migration
lirans@il.ibm.com authored
1 /*
2 * QEMU live block migration
3 *
4 * Copyright IBM, Corp. 2009
5 *
6 * Authors:
7 * Liran Schour <lirans@il.ibm.com>
8 *
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
11 *
12 */
13
14 #include "qemu-common.h"
15 #include "block_int.h"
16 #include "hw/hw.h"
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
17 #include "qemu-queue.h"
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
18 #include "qemu-timer.h"
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
19 #include "monitor.h"
c163b5c Block live migration
lirans@il.ibm.com authored
20 #include "block-migration.h"
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
21 #include "migration.h"
c163b5c Block live migration
lirans@il.ibm.com authored
22 #include <assert.h>
23
6ea4430 @jan-kiszka block migration: Rework constants API
jan-kiszka authored
24 #define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
c163b5c Block live migration
lirans@il.ibm.com authored
25
26 #define BLK_MIG_FLAG_DEVICE_BLOCK 0x01
27 #define BLK_MIG_FLAG_EOS 0x02
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
28 #define BLK_MIG_FLAG_PROGRESS 0x04
c163b5c Block live migration
lirans@il.ibm.com authored
29
30 #define MAX_IS_ALLOCATED_SEARCH 65536
31
32 //#define DEBUG_BLK_MIGRATION
33
34 #ifdef DEBUG_BLK_MIGRATION
d0f2c4c @moosotc Do not use dprintf
moosotc authored
35 #define DPRINTF(fmt, ...) \
c163b5c Block live migration
lirans@il.ibm.com authored
36 do { printf("blk_migration: " fmt, ## __VA_ARGS__); } while (0)
37 #else
d0f2c4c @moosotc Do not use dprintf
moosotc authored
38 #define DPRINTF(fmt, ...) \
c163b5c Block live migration
lirans@il.ibm.com authored
39 do { } while (0)
40 #endif
41
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
42 typedef struct BlkMigDevState {
43 BlockDriverState *bs;
44 int bulk_completed;
45 int shared_base;
46 int64_t cur_sector;
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
47 int64_t cur_dirty;
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
48 int64_t completed_sectors;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
49 int64_t total_sectors;
50 int64_t dirty;
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
51 QSIMPLEQ_ENTRY(BlkMigDevState) entry;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
52 } BlkMigDevState;
53
c163b5c Block live migration
lirans@il.ibm.com authored
54 typedef struct BlkMigBlock {
55 uint8_t *buf;
56 BlkMigDevState *bmds;
57 int64_t sector;
58 struct iovec iov;
59 QEMUIOVector qiov;
60 BlockDriverAIOCB *aiocb;
61 int ret;
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
62 int64_t time;
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
63 QSIMPLEQ_ENTRY(BlkMigBlock) entry;
c163b5c Block live migration
lirans@il.ibm.com authored
64 } BlkMigBlock;
65
66 typedef struct BlkMigState {
67 int blk_enable;
68 int shared_base;
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
69 QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
70 QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
c163b5c Block live migration
lirans@il.ibm.com authored
71 int submitted;
72 int read_done;
73 int transferred;
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
74 int64_t total_sector_sum;
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
75 int prev_progress;
e970ec0 Remove unused code
Liran Schour authored
76 int bulk_completed;
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
77 long double total_time;
78 int reads;
c163b5c Block live migration
lirans@il.ibm.com authored
79 } BlkMigState;
80
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
81 static BlkMigState block_mig_state;
c163b5c Block live migration
lirans@il.ibm.com authored
82
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
83 static void blk_send(QEMUFile *f, BlkMigBlock * blk)
84 {
85 int len;
86
87 /* sector number and flags */
88 qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
89 | BLK_MIG_FLAG_DEVICE_BLOCK);
90
91 /* device name */
92 len = strlen(blk->bmds->bs->device_name);
93 qemu_put_byte(f, len);
94 qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
95
96 qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
97 }
98
25f2364 @jan-kiszka block migration: Report progress also via info migration
jan-kiszka authored
99 int blk_mig_active(void)
100 {
101 return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
102 }
103
104 uint64_t blk_mig_bytes_transferred(void)
105 {
106 BlkMigDevState *bmds;
107 uint64_t sum = 0;
108
109 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
110 sum += bmds->completed_sectors;
111 }
112 return sum << BDRV_SECTOR_BITS;
113 }
114
115 uint64_t blk_mig_bytes_remaining(void)
116 {
117 return blk_mig_bytes_total() - blk_mig_bytes_transferred();
118 }
119
120 uint64_t blk_mig_bytes_total(void)
121 {
122 BlkMigDevState *bmds;
123 uint64_t sum = 0;
124
125 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
126 sum += bmds->total_sectors;
127 }
128 return sum << BDRV_SECTOR_BITS;
129 }
130
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
131 static inline void add_avg_read_time(int64_t time)
132 {
133 block_mig_state.reads++;
134 block_mig_state.total_time += time;
135 }
136
137 static inline long double compute_read_bwidth(void)
138 {
139 assert(block_mig_state.total_time != 0);
140 return (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time;
141 }
142
c163b5c Block live migration
lirans@il.ibm.com authored
143 static void blk_mig_read_cb(void *opaque, int ret)
144 {
145 BlkMigBlock *blk = opaque;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
146
c163b5c Block live migration
lirans@il.ibm.com authored
147 blk->ret = ret;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
148
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
149 blk->time = qemu_get_clock_ns(rt_clock) - blk->time;
150
151 add_avg_read_time(blk->time);
152
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
153 QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
154
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
155 block_mig_state.submitted--;
156 block_mig_state.read_done++;
157 assert(block_mig_state.submitted >= 0);
c163b5c Block live migration
lirans@il.ibm.com authored
158 }
159
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
160 static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
e970ec0 Remove unused code
Liran Schour authored
161 BlkMigDevState *bmds)
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
162 {
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
163 int64_t total_sectors = bmds->total_sectors;
164 int64_t cur_sector = bmds->cur_sector;
165 BlockDriverState *bs = bmds->bs;
c163b5c Block live migration
lirans@il.ibm.com authored
166 BlkMigBlock *blk;
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
167 int nr_sectors;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
168
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
169 if (bmds->shared_base) {
b1d1085 @jan-kiszka block migration: Clean up use of total_sectors
jan-kiszka authored
170 while (cur_sector < total_sectors &&
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
171 !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
172 &nr_sectors)) {
c163b5c Block live migration
lirans@il.ibm.com authored
173 cur_sector += nr_sectors;
174 }
175 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
176
177 if (cur_sector >= total_sectors) {
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
178 bmds->cur_sector = bmds->completed_sectors = total_sectors;
c163b5c Block live migration
lirans@il.ibm.com authored
179 return 1;
180 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
181
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
182 bmds->completed_sectors = cur_sector;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
183
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
184 cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
185
6ea4430 @jan-kiszka block migration: Rework constants API
jan-kiszka authored
186 /* we are going to transfer a full block even if it is not allocated */
187 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
c163b5c Block live migration
lirans@il.ibm.com authored
188
6ea4430 @jan-kiszka block migration: Rework constants API
jan-kiszka authored
189 if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
190 nr_sectors = total_sectors - cur_sector;
c163b5c Block live migration
lirans@il.ibm.com authored
191 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
192
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
193 blk = qemu_malloc(sizeof(BlkMigBlock));
194 blk->buf = qemu_malloc(BLOCK_SIZE);
195 blk->bmds = bmds;
196 blk->sector = cur_sector;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
197
e970ec0 Remove unused code
Liran Schour authored
198 blk->iov.iov_base = blk->buf;
199 blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
200 qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
201
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
202 blk->time = qemu_get_clock_ns(rt_clock);
203
e970ec0 Remove unused code
Liran Schour authored
204 blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
205 nr_sectors, blk_mig_read_cb, blk);
206 if (!blk->aiocb) {
207 goto error;
c163b5c Block live migration
lirans@il.ibm.com authored
208 }
e970ec0 Remove unused code
Liran Schour authored
209 block_mig_state.submitted++;
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
210
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
211 bdrv_reset_dirty(bs, cur_sector, nr_sectors);
212 bmds->cur_sector = cur_sector + nr_sectors;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
213
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
214 return (bmds->cur_sector >= total_sectors);
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
215
216 error:
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
217 monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
218 qemu_file_set_error(f);
219 qemu_free(blk->buf);
220 qemu_free(blk);
221 return 0;
c163b5c Block live migration
lirans@il.ibm.com authored
222 }
223
224 static void set_dirty_tracking(int enable)
225 {
226 BlkMigDevState *bmds;
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
227
228 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
229 bdrv_set_dirty_tracking(bmds->bs, enable);
c163b5c Block live migration
lirans@il.ibm.com authored
230 }
231 }
232
b66460e block: Do not export bdrv_first
Stefan Hajnoczi authored
233 static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
c163b5c Block live migration
lirans@il.ibm.com authored
234 {
b66460e block: Do not export bdrv_first
Stefan Hajnoczi authored
235 Monitor *mon = opaque;
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
236 BlkMigDevState *bmds;
792773b @jan-kiszka block migration: Skip zero-sized disks
jan-kiszka authored
237 int64_t sectors;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
238
b66460e block: Do not export bdrv_first
Stefan Hajnoczi authored
239 if (bs->type == BDRV_TYPE_HD) {
240 sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
241 if (sectors == 0) {
242 return;
243 }
244
245 bmds = qemu_mallocz(sizeof(BlkMigDevState));
246 bmds->bs = bs;
247 bmds->bulk_completed = 0;
248 bmds->total_sectors = sectors;
249 bmds->completed_sectors = 0;
250 bmds->shared_base = block_mig_state.shared_base;
251
252 block_mig_state.total_sector_sum += sectors;
253
254 if (bmds->shared_base) {
255 monitor_printf(mon, "Start migration for %s with shared base "
256 "image\n",
257 bs->device_name);
258 } else {
259 monitor_printf(mon, "Start full migration for %s\n",
260 bs->device_name);
261 }
262
263 QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
264 }
265 }
266
267 static void init_blk_migration(Monitor *mon, QEMUFile *f)
268 {
69d63a9 @jan-kiszka block migration: Initialize remaining BlkMigState fields
jan-kiszka authored
269 block_mig_state.submitted = 0;
270 block_mig_state.read_done = 0;
271 block_mig_state.transferred = 0;
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
272 block_mig_state.total_sector_sum = 0;
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
273 block_mig_state.prev_progress = -1;
e970ec0 Remove unused code
Liran Schour authored
274 block_mig_state.bulk_completed = 0;
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
275 block_mig_state.total_time = 0;
276 block_mig_state.reads = 0;
69d63a9 @jan-kiszka block migration: Initialize remaining BlkMigState fields
jan-kiszka authored
277
b66460e block: Do not export bdrv_first
Stefan Hajnoczi authored
278 bdrv_iterate(init_blk_migration_it, mon);
c163b5c Block live migration
lirans@il.ibm.com authored
279 }
280
e970ec0 Remove unused code
Liran Schour authored
281 static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
c163b5c Block live migration
lirans@il.ibm.com authored
282 {
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
283 int64_t completed_sector_sum = 0;
c163b5c Block live migration
lirans@il.ibm.com authored
284 BlkMigDevState *bmds;
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
285 int progress;
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
286 int ret = 0;
c163b5c Block live migration
lirans@il.ibm.com authored
287
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
288 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
289 if (bmds->bulk_completed == 0) {
e970ec0 Remove unused code
Liran Schour authored
290 if (mig_save_device_bulk(mon, f, bmds) == 1) {
57cce12 @jan-kiszka block migration: Consolidate mig_read_device_bulk into mig_save_device_b...
jan-kiszka authored
291 /* completed bulk section for this device */
292 bmds->bulk_completed = 1;
c163b5c Block live migration
lirans@il.ibm.com authored
293 }
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
294 completed_sector_sum += bmds->completed_sectors;
295 ret = 1;
296 break;
297 } else {
298 completed_sector_sum += bmds->completed_sectors;
c163b5c Block live migration
lirans@il.ibm.com authored
299 }
300 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
301
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
302 progress = completed_sector_sum * 100 / block_mig_state.total_sector_sum;
303 if (progress != block_mig_state.prev_progress) {
304 block_mig_state.prev_progress = progress;
305 qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
306 | BLK_MIG_FLAG_PROGRESS);
307 monitor_printf(mon, "Completed %d %%\r", progress);
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
308 monitor_flush(mon);
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
309 }
310
311 return ret;
c163b5c Block live migration
lirans@il.ibm.com authored
312 }
313
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
314 static void blk_mig_reset_dirty_cursor(void)
c163b5c Block live migration
lirans@il.ibm.com authored
315 {
316 BlkMigDevState *bmds;
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
317
318 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
319 bmds->cur_dirty = 0;
320 }
321 }
322
323 static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
324 BlkMigDevState *bmds, int is_async)
325 {
326 BlkMigBlock *blk;
327 int64_t total_sectors = bmds->total_sectors;
c163b5c Block live migration
lirans@il.ibm.com authored
328 int64_t sector;
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
329 int nr_sectors;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
330
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
331 for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
332 if (bdrv_get_dirty(bmds->bs, sector)) {
575a58d @jan-kiszka block migration: Avoid large stack buffer
jan-kiszka authored
333
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
334 if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
335 nr_sectors = total_sectors - sector;
336 } else {
337 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
338 }
339 blk = qemu_malloc(sizeof(BlkMigBlock));
340 blk->buf = qemu_malloc(BLOCK_SIZE);
341 blk->bmds = bmds;
342 blk->sector = sector;
343
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
344 if (is_async) {
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
345 blk->iov.iov_base = blk->buf;
346 blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
347 qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
348
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
349 blk->time = qemu_get_clock_ns(rt_clock);
350
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
351 blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
352 nr_sectors, blk_mig_read_cb, blk);
353 if (!blk->aiocb) {
354 goto error;
355 }
356 block_mig_state.submitted++;
357 } else {
358 if (bdrv_read(bmds->bs, sector, blk->buf,
359 nr_sectors) < 0) {
360 goto error;
c163b5c Block live migration
lirans@il.ibm.com authored
361 }
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
362 blk_send(f, blk);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
363
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
364 qemu_free(blk->buf);
365 qemu_free(blk);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
366 }
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
367
368 bdrv_reset_dirty(bmds->bs, sector, nr_sectors);
369 break;
c163b5c Block live migration
lirans@il.ibm.com authored
370 }
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
371 sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
372 bmds->cur_dirty = sector;
c163b5c Block live migration
lirans@il.ibm.com authored
373 }
575a58d @jan-kiszka block migration: Avoid large stack buffer
jan-kiszka authored
374
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
375 return (bmds->cur_dirty >= bmds->total_sectors);
376
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
377 error:
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
378 monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
379 qemu_file_set_error(f);
380 qemu_free(blk->buf);
381 qemu_free(blk);
382 return 0;
383 }
384
385 static int blk_mig_save_dirty_block(Monitor *mon, QEMUFile *f, int is_async)
386 {
387 BlkMigDevState *bmds;
388 int ret = 0;
389
390 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
391 if (mig_save_device_dirty(mon, f, bmds, is_async) == 0) {
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
392 ret = 1;
393 break;
394 }
395 }
396
397 return ret;
c163b5c Block live migration
lirans@il.ibm.com authored
398 }
399
400 static void flush_blks(QEMUFile* f)
401 {
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
402 BlkMigBlock *blk;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
403
d0f2c4c @moosotc Do not use dprintf
moosotc authored
404 DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
405 __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
406 block_mig_state.transferred);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
407
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
408 while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
409 if (qemu_file_rate_limit(f)) {
410 break;
411 }
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
412 if (blk->ret < 0) {
413 qemu_file_set_error(f);
414 break;
415 }
13f0b67 @jan-kiszka block migration: Consolidate block transmission
jan-kiszka authored
416 blk_send(f, blk);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
417
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
418 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
c163b5c Block live migration
lirans@il.ibm.com authored
419 qemu_free(blk->buf);
420 qemu_free(blk);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
421
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
422 block_mig_state.read_done--;
423 block_mig_state.transferred++;
424 assert(block_mig_state.read_done >= 0);
c163b5c Block live migration
lirans@il.ibm.com authored
425 }
426
d0f2c4c @moosotc Do not use dprintf
moosotc authored
427 DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
428 block_mig_state.submitted, block_mig_state.read_done,
429 block_mig_state.transferred);
c163b5c Block live migration
lirans@il.ibm.com authored
430 }
431
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
432 static int64_t get_remaining_dirty(void)
433 {
434 BlkMigDevState *bmds;
435 int64_t dirty = 0;
436
437 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
438 dirty += bdrv_get_dirty_count(bmds->bs);
439 }
440
441 return dirty * BLOCK_SIZE;
442 }
443
c163b5c Block live migration
lirans@il.ibm.com authored
444 static int is_stage2_completed(void)
445 {
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
446 int64_t remaining_dirty;
447 long double bwidth;
448
449 if (block_mig_state.bulk_completed == 1) {
450
451 remaining_dirty = get_remaining_dirty();
452 if (remaining_dirty == 0) {
453 return 1;
454 }
455
456 bwidth = compute_read_bwidth();
457
458 if ((remaining_dirty / bwidth) <=
459 migrate_max_downtime()) {
460 /* finish stage2 because we think that we can finish remaing work
461 below max_downtime */
462
463 return 1;
464 }
465 }
466
467 return 0;
c163b5c Block live migration
lirans@il.ibm.com authored
468 }
469
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
470 static void blk_mig_cleanup(Monitor *mon)
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
471 {
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
472 BlkMigDevState *bmds;
473 BlkMigBlock *blk;
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
474
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
475 while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
476 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
477 qemu_free(bmds);
478 }
479
82801d8 @jan-kiszka block migration: Report overall migration progress
jan-kiszka authored
480 while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
481 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
482 qemu_free(blk->buf);
483 qemu_free(blk);
484 }
485
486 set_dirty_tracking(0);
487
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
488 monitor_printf(mon, "\n");
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
489 }
490
f327aa0 @jan-kiszka live migration: Propagate output monitor to callback handler
jan-kiszka authored
491 static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
c163b5c Block live migration
lirans@il.ibm.com authored
492 {
d0f2c4c @moosotc Do not use dprintf
moosotc authored
493 DPRINTF("Enter save live stage %d submitted %d transferred %d\n",
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
494 stage, block_mig_state.submitted, block_mig_state.transferred);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
495
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
496 if (stage < 0) {
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
497 blk_mig_cleanup(mon);
4ec7fcc @jan-kiszka live migration: Allow cleanup after cancellation or error
jan-kiszka authored
498 return 0;
499 }
500
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
501 if (block_mig_state.blk_enable != 1) {
c163b5c Block live migration
lirans@il.ibm.com authored
502 /* no need to migrate storage */
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
503 qemu_put_be64(f, BLK_MIG_FLAG_EOS);
c163b5c Block live migration
lirans@il.ibm.com authored
504 return 1;
505 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
506
507 if (stage == 1) {
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
508 init_blk_migration(mon, f);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
509
c163b5c Block live migration
lirans@il.ibm.com authored
510 /* start track dirty blocks */
511 set_dirty_tracking(1);
512 }
513
514 flush_blks(f);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
515
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
516 if (qemu_file_has_error(f)) {
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
517 blk_mig_cleanup(mon);
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
518 return 0;
519 }
520
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
521 blk_mig_reset_dirty_cursor();
522
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
523 if (stage == 2) {
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
524 /* control the rate of transfer */
525 while ((block_mig_state.submitted +
526 block_mig_state.read_done) * BLOCK_SIZE <
527 qemu_file_get_rate_limit(f)) {
528 if (block_mig_state.bulk_completed == 0) {
529 /* first finish the bulk phase */
530 if (blk_mig_save_bulked_block(mon, f) == 0) {
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
531 /* finished saving bulk on all devices */
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
532 block_mig_state.bulk_completed = 1;
533 }
534 } else {
535 if (blk_mig_save_dirty_block(mon, f, 1) == 0) {
536 /* no more dirty blocks */
537 break;
538 }
539 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
540 }
541
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
542 flush_blks(f);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
543
d76cac7 Tranfer dirty blocks during iterative phase
Liran Schour authored
544 if (qemu_file_has_error(f)) {
545 blk_mig_cleanup(mon);
546 return 0;
547 }
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
548 }
549
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
550 if (stage == 3) {
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
551 /* we know for sure that save bulk is completed and
552 all async read completed */
553 assert(block_mig_state.submitted == 0);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
554
889ae39 Try not to exceed max downtime on stage3
Liran Schour authored
555 while (blk_mig_save_dirty_block(mon, f, 0) != 0);
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
556 blk_mig_cleanup(mon);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
557
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
558 /* report completion */
559 qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
560
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
561 if (qemu_file_has_error(f)) {
562 return 0;
563 }
564
7184049 @jan-kiszka block migration: Fix outgoing progress output
jan-kiszka authored
565 monitor_printf(mon, "Block migration completed\n");
c163b5c Block live migration
lirans@il.ibm.com authored
566 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
567
568 qemu_put_be64(f, BLK_MIG_FLAG_EOS);
569
c163b5c Block live migration
lirans@il.ibm.com authored
570 return ((stage == 2) && is_stage2_completed());
571 }
572
573 static int block_load(QEMUFile *f, void *opaque, int version_id)
574 {
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
575 static int banner_printed;
c163b5c Block live migration
lirans@il.ibm.com authored
576 int len, flags;
577 char device_name[256];
578 int64_t addr;
579 BlockDriverState *bs;
580 uint8_t *buf;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
581
c163b5c Block live migration
lirans@il.ibm.com authored
582 do {
583 addr = qemu_get_be64(f);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
584
6ea4430 @jan-kiszka block migration: Rework constants API
jan-kiszka authored
585 flags = addr & ~BDRV_SECTOR_MASK;
586 addr >>= BDRV_SECTOR_BITS;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
587
588 if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
c163b5c Block live migration
lirans@il.ibm.com authored
589 /* get device name */
590 len = qemu_get_byte(f);
591 qemu_get_buffer(f, (uint8_t *)device_name, len);
592 device_name[len] = '\0';
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
593
c163b5c Block live migration
lirans@il.ibm.com authored
594 bs = bdrv_find(device_name);
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
595 if (!bs) {
596 fprintf(stderr, "Error unknown block device %s\n",
597 device_name);
598 return -EINVAL;
599 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
600
575a58d @jan-kiszka block migration: Avoid large stack buffer
jan-kiszka authored
601 buf = qemu_malloc(BLOCK_SIZE);
602
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
603 qemu_get_buffer(f, buf, BLOCK_SIZE);
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
604 bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
575a58d @jan-kiszka block migration: Avoid large stack buffer
jan-kiszka authored
605
606 qemu_free(buf);
01e61e2 @jan-kiszka block migration: Add support for restore progress reporting
jan-kiszka authored
607 } else if (flags & BLK_MIG_FLAG_PROGRESS) {
608 if (!banner_printed) {
609 printf("Receiving block device images\n");
610 banner_printed = 1;
611 }
612 printf("Completed %d %%%c", (int)addr,
613 (addr == 100) ? '\n' : '\r');
614 fflush(stdout);
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
615 } else if (!(flags & BLK_MIG_FLAG_EOS)) {
4b64036 @jan-kiszka block migration: Add error handling/propagation
jan-kiszka authored
616 fprintf(stderr, "Unknown flags\n");
617 return -EINVAL;
618 }
619 if (qemu_file_has_error(f)) {
620 return -EIO;
c163b5c Block live migration
lirans@il.ibm.com authored
621 }
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
622 } while (!(flags & BLK_MIG_FLAG_EOS));
623
c163b5c Block live migration
lirans@il.ibm.com authored
624 return 0;
625 }
626
627 static void block_set_params(int blk_enable, int shared_base, void *opaque)
628 {
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
629 block_mig_state.blk_enable = blk_enable;
630 block_mig_state.shared_base = shared_base;
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
631
c163b5c Block live migration
lirans@il.ibm.com authored
632 /* shared base means that blk_enable = 1 */
d11ecd3 @jan-kiszka block migration: Avoid indirection of block_mig_state
jan-kiszka authored
633 block_mig_state.blk_enable |= shared_base;
c163b5c Block live migration
lirans@il.ibm.com authored
634 }
635
636 void blk_mig_init(void)
a55eb92 @jan-kiszka block migration: Fix coding style and whitespaces
jan-kiszka authored
637 {
5e5328b @jan-kiszka block migration: Switch device and block lists to QSIMPLEQ
jan-kiszka authored
638 QSIMPLEQ_INIT(&block_mig_state.bmds_list);
639 QSIMPLEQ_INIT(&block_mig_state.blk_list);
640
0be71e3 @awilliam savevm: Add DeviceState param
awilliam authored
641 register_savevm_live(NULL, "block", 0, 1, block_set_params,
642 block_save_live, NULL, block_load, &block_mig_state);
c163b5c Block live migration
lirans@il.ibm.com authored
643 }
Something went wrong with that request. Please try again.