Statistics
| Branch: | Revision:

root / block-migration.c @ 1d2699ae

History | View | Annotate | Download (14.1 kB)

1 c163b5ca lirans@il.ibm.com
/*
2 c163b5ca lirans@il.ibm.com
 * QEMU live block migration
3 c163b5ca lirans@il.ibm.com
 *
4 c163b5ca lirans@il.ibm.com
 * Copyright IBM, Corp. 2009
5 c163b5ca lirans@il.ibm.com
 *
6 c163b5ca lirans@il.ibm.com
 * Authors:
7 c163b5ca lirans@il.ibm.com
 *  Liran Schour   <lirans@il.ibm.com>
8 c163b5ca lirans@il.ibm.com
 *
9 c163b5ca lirans@il.ibm.com
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 c163b5ca lirans@il.ibm.com
 * the COPYING file in the top-level directory.
11 c163b5ca lirans@il.ibm.com
 *
12 c163b5ca lirans@il.ibm.com
 */
13 c163b5ca lirans@il.ibm.com
14 c163b5ca lirans@il.ibm.com
#include "qemu-common.h"
15 c163b5ca lirans@il.ibm.com
#include "block_int.h"
16 c163b5ca lirans@il.ibm.com
#include "hw/hw.h"
17 5e5328be Jan Kiszka
#include "qemu-queue.h"
18 7184049e Jan Kiszka
#include "monitor.h"
19 c163b5ca lirans@il.ibm.com
#include "block-migration.h"
20 c163b5ca lirans@il.ibm.com
#include <assert.h>
21 c163b5ca lirans@il.ibm.com
22 6ea44308 Jan Kiszka
#define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
23 c163b5ca lirans@il.ibm.com
24 c163b5ca lirans@il.ibm.com
#define BLK_MIG_FLAG_DEVICE_BLOCK       0x01
25 c163b5ca lirans@il.ibm.com
#define BLK_MIG_FLAG_EOS                0x02
26 01e61e2d Jan Kiszka
#define BLK_MIG_FLAG_PROGRESS           0x04
27 c163b5ca lirans@il.ibm.com
28 c163b5ca lirans@il.ibm.com
#define MAX_IS_ALLOCATED_SEARCH 65536
29 c163b5ca lirans@il.ibm.com
#define MAX_BLOCKS_READ 10000
30 c163b5ca lirans@il.ibm.com
#define BLOCKS_READ_CHANGE 100
31 c163b5ca lirans@il.ibm.com
#define INITIAL_BLOCKS_READ 100
32 c163b5ca lirans@il.ibm.com
33 c163b5ca lirans@il.ibm.com
//#define DEBUG_BLK_MIGRATION
34 c163b5ca lirans@il.ibm.com
35 c163b5ca lirans@il.ibm.com
#ifdef DEBUG_BLK_MIGRATION
36 a55eb92c Jan Kiszka
#define dprintf(fmt, ...) \
37 c163b5ca lirans@il.ibm.com
    do { printf("blk_migration: " fmt, ## __VA_ARGS__); } while (0)
38 c163b5ca lirans@il.ibm.com
#else
39 a55eb92c Jan Kiszka
#define dprintf(fmt, ...) \
40 c163b5ca lirans@il.ibm.com
    do { } while (0)
41 c163b5ca lirans@il.ibm.com
#endif
42 c163b5ca lirans@il.ibm.com
43 a55eb92c Jan Kiszka
typedef struct BlkMigDevState {
44 a55eb92c Jan Kiszka
    BlockDriverState *bs;
45 a55eb92c Jan Kiszka
    int bulk_completed;
46 a55eb92c Jan Kiszka
    int shared_base;
47 a55eb92c Jan Kiszka
    int64_t cur_sector;
48 82801d8f Jan Kiszka
    int64_t completed_sectors;
49 a55eb92c Jan Kiszka
    int64_t total_sectors;
50 a55eb92c Jan Kiszka
    int64_t dirty;
51 5e5328be Jan Kiszka
    QSIMPLEQ_ENTRY(BlkMigDevState) entry;
52 a55eb92c Jan Kiszka
} BlkMigDevState;
53 a55eb92c Jan Kiszka
54 c163b5ca lirans@il.ibm.com
typedef struct BlkMigBlock {
55 c163b5ca lirans@il.ibm.com
    uint8_t *buf;
56 c163b5ca lirans@il.ibm.com
    BlkMigDevState *bmds;
57 c163b5ca lirans@il.ibm.com
    int64_t sector;
58 c163b5ca lirans@il.ibm.com
    struct iovec iov;
59 c163b5ca lirans@il.ibm.com
    QEMUIOVector qiov;
60 c163b5ca lirans@il.ibm.com
    BlockDriverAIOCB *aiocb;
61 c163b5ca lirans@il.ibm.com
    int ret;
62 5e5328be Jan Kiszka
    QSIMPLEQ_ENTRY(BlkMigBlock) entry;
63 c163b5ca lirans@il.ibm.com
} BlkMigBlock;
64 c163b5ca lirans@il.ibm.com
65 c163b5ca lirans@il.ibm.com
typedef struct BlkMigState {
66 c163b5ca lirans@il.ibm.com
    int blk_enable;
67 c163b5ca lirans@il.ibm.com
    int shared_base;
68 5e5328be Jan Kiszka
    QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
69 5e5328be Jan Kiszka
    QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
70 c163b5ca lirans@il.ibm.com
    int submitted;
71 c163b5ca lirans@il.ibm.com
    int read_done;
72 c163b5ca lirans@il.ibm.com
    int transferred;
73 82801d8f Jan Kiszka
    int64_t total_sector_sum;
74 01e61e2d Jan Kiszka
    int prev_progress;
75 c163b5ca lirans@il.ibm.com
} BlkMigState;
76 c163b5ca lirans@il.ibm.com
77 d11ecd3d Jan Kiszka
static BlkMigState block_mig_state;
78 c163b5ca lirans@il.ibm.com
79 13f0b67f Jan Kiszka
static void blk_send(QEMUFile *f, BlkMigBlock * blk)
80 13f0b67f Jan Kiszka
{
81 13f0b67f Jan Kiszka
    int len;
82 13f0b67f Jan Kiszka
83 13f0b67f Jan Kiszka
    /* sector number and flags */
84 13f0b67f Jan Kiszka
    qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
85 13f0b67f Jan Kiszka
                     | BLK_MIG_FLAG_DEVICE_BLOCK);
86 13f0b67f Jan Kiszka
87 13f0b67f Jan Kiszka
    /* device name */
88 13f0b67f Jan Kiszka
    len = strlen(blk->bmds->bs->device_name);
89 13f0b67f Jan Kiszka
    qemu_put_byte(f, len);
90 13f0b67f Jan Kiszka
    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
91 13f0b67f Jan Kiszka
92 13f0b67f Jan Kiszka
    qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
93 13f0b67f Jan Kiszka
}
94 13f0b67f Jan Kiszka
95 25f23643 Jan Kiszka
int blk_mig_active(void)
96 25f23643 Jan Kiszka
{
97 25f23643 Jan Kiszka
    return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
98 25f23643 Jan Kiszka
}
99 25f23643 Jan Kiszka
100 25f23643 Jan Kiszka
uint64_t blk_mig_bytes_transferred(void)
101 25f23643 Jan Kiszka
{
102 25f23643 Jan Kiszka
    BlkMigDevState *bmds;
103 25f23643 Jan Kiszka
    uint64_t sum = 0;
104 25f23643 Jan Kiszka
105 25f23643 Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
106 25f23643 Jan Kiszka
        sum += bmds->completed_sectors;
107 25f23643 Jan Kiszka
    }
108 25f23643 Jan Kiszka
    return sum << BDRV_SECTOR_BITS;
109 25f23643 Jan Kiszka
}
110 25f23643 Jan Kiszka
111 25f23643 Jan Kiszka
uint64_t blk_mig_bytes_remaining(void)
112 25f23643 Jan Kiszka
{
113 25f23643 Jan Kiszka
    return blk_mig_bytes_total() - blk_mig_bytes_transferred();
114 25f23643 Jan Kiszka
}
115 25f23643 Jan Kiszka
116 25f23643 Jan Kiszka
uint64_t blk_mig_bytes_total(void)
117 25f23643 Jan Kiszka
{
118 25f23643 Jan Kiszka
    BlkMigDevState *bmds;
119 25f23643 Jan Kiszka
    uint64_t sum = 0;
120 25f23643 Jan Kiszka
121 25f23643 Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
122 25f23643 Jan Kiszka
        sum += bmds->total_sectors;
123 25f23643 Jan Kiszka
    }
124 25f23643 Jan Kiszka
    return sum << BDRV_SECTOR_BITS;
125 25f23643 Jan Kiszka
}
126 25f23643 Jan Kiszka
127 c163b5ca lirans@il.ibm.com
static void blk_mig_read_cb(void *opaque, int ret)
128 c163b5ca lirans@il.ibm.com
{
129 c163b5ca lirans@il.ibm.com
    BlkMigBlock *blk = opaque;
130 a55eb92c Jan Kiszka
131 c163b5ca lirans@il.ibm.com
    blk->ret = ret;
132 a55eb92c Jan Kiszka
133 5e5328be Jan Kiszka
    QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
134 a55eb92c Jan Kiszka
135 d11ecd3d Jan Kiszka
    block_mig_state.submitted--;
136 d11ecd3d Jan Kiszka
    block_mig_state.read_done++;
137 d11ecd3d Jan Kiszka
    assert(block_mig_state.submitted >= 0);
138 c163b5ca lirans@il.ibm.com
}
139 c163b5ca lirans@il.ibm.com
140 7184049e Jan Kiszka
static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
141 7184049e Jan Kiszka
                                BlkMigDevState *bmds, int is_async)
142 a55eb92c Jan Kiszka
{
143 57cce12d Jan Kiszka
    int64_t total_sectors = bmds->total_sectors;
144 57cce12d Jan Kiszka
    int64_t cur_sector = bmds->cur_sector;
145 57cce12d Jan Kiszka
    BlockDriverState *bs = bmds->bs;
146 c163b5ca lirans@il.ibm.com
    BlkMigBlock *blk;
147 13f0b67f Jan Kiszka
    int nr_sectors;
148 a55eb92c Jan Kiszka
149 57cce12d Jan Kiszka
    if (bmds->shared_base) {
150 b1d10856 Jan Kiszka
        while (cur_sector < total_sectors &&
151 57cce12d Jan Kiszka
               !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
152 57cce12d Jan Kiszka
                                  &nr_sectors)) {
153 c163b5ca lirans@il.ibm.com
            cur_sector += nr_sectors;
154 c163b5ca lirans@il.ibm.com
        }
155 c163b5ca lirans@il.ibm.com
    }
156 a55eb92c Jan Kiszka
157 a55eb92c Jan Kiszka
    if (cur_sector >= total_sectors) {
158 82801d8f Jan Kiszka
        bmds->cur_sector = bmds->completed_sectors = total_sectors;
159 c163b5ca lirans@il.ibm.com
        return 1;
160 c163b5ca lirans@il.ibm.com
    }
161 a55eb92c Jan Kiszka
162 82801d8f Jan Kiszka
    bmds->completed_sectors = cur_sector;
163 a55eb92c Jan Kiszka
164 57cce12d Jan Kiszka
    cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
165 57cce12d Jan Kiszka
166 6ea44308 Jan Kiszka
    /* we are going to transfer a full block even if it is not allocated */
167 6ea44308 Jan Kiszka
    nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
168 c163b5ca lirans@il.ibm.com
169 6ea44308 Jan Kiszka
    if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
170 57cce12d Jan Kiszka
        nr_sectors = total_sectors - cur_sector;
171 c163b5ca lirans@il.ibm.com
    }
172 a55eb92c Jan Kiszka
173 13f0b67f Jan Kiszka
    blk = qemu_malloc(sizeof(BlkMigBlock));
174 13f0b67f Jan Kiszka
    blk->buf = qemu_malloc(BLOCK_SIZE);
175 13f0b67f Jan Kiszka
    blk->bmds = bmds;
176 13f0b67f Jan Kiszka
    blk->sector = cur_sector;
177 a55eb92c Jan Kiszka
178 13f0b67f Jan Kiszka
    if (is_async) {
179 57cce12d Jan Kiszka
        blk->iov.iov_base = blk->buf;
180 57cce12d Jan Kiszka
        blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
181 57cce12d Jan Kiszka
        qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
182 a55eb92c Jan Kiszka
183 57cce12d Jan Kiszka
        blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
184 57cce12d Jan Kiszka
                                    nr_sectors, blk_mig_read_cb, blk);
185 57cce12d Jan Kiszka
        if (!blk->aiocb) {
186 4b640365 Jan Kiszka
            goto error;
187 57cce12d Jan Kiszka
        }
188 57cce12d Jan Kiszka
        block_mig_state.submitted++;
189 57cce12d Jan Kiszka
    } else {
190 13f0b67f Jan Kiszka
        if (bdrv_read(bs, cur_sector, blk->buf, nr_sectors) < 0) {
191 4b640365 Jan Kiszka
            goto error;
192 c163b5ca lirans@il.ibm.com
        }
193 13f0b67f Jan Kiszka
        blk_send(f, blk);
194 a55eb92c Jan Kiszka
195 13f0b67f Jan Kiszka
        qemu_free(blk->buf);
196 13f0b67f Jan Kiszka
        qemu_free(blk);
197 c163b5ca lirans@il.ibm.com
    }
198 c163b5ca lirans@il.ibm.com
199 13f0b67f Jan Kiszka
    bdrv_reset_dirty(bs, cur_sector, nr_sectors);
200 13f0b67f Jan Kiszka
    bmds->cur_sector = cur_sector + nr_sectors;
201 a55eb92c Jan Kiszka
202 13f0b67f Jan Kiszka
    return (bmds->cur_sector >= total_sectors);
203 4b640365 Jan Kiszka
204 4b640365 Jan Kiszka
error:
205 7184049e Jan Kiszka
    monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
206 4b640365 Jan Kiszka
    qemu_file_set_error(f);
207 4b640365 Jan Kiszka
    qemu_free(blk->buf);
208 4b640365 Jan Kiszka
    qemu_free(blk);
209 4b640365 Jan Kiszka
    return 0;
210 c163b5ca lirans@il.ibm.com
}
211 c163b5ca lirans@il.ibm.com
212 c163b5ca lirans@il.ibm.com
static void set_dirty_tracking(int enable)
213 c163b5ca lirans@il.ibm.com
{
214 c163b5ca lirans@il.ibm.com
    BlkMigDevState *bmds;
215 5e5328be Jan Kiszka
216 5e5328be Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
217 a55eb92c Jan Kiszka
        bdrv_set_dirty_tracking(bmds->bs, enable);
218 c163b5ca lirans@il.ibm.com
    }
219 c163b5ca lirans@il.ibm.com
}
220 c163b5ca lirans@il.ibm.com
221 7184049e Jan Kiszka
static void init_blk_migration(Monitor *mon, QEMUFile *f)
222 c163b5ca lirans@il.ibm.com
{
223 5e5328be Jan Kiszka
    BlkMigDevState *bmds;
224 c163b5ca lirans@il.ibm.com
    BlockDriverState *bs;
225 792773b2 Jan Kiszka
    int64_t sectors;
226 a55eb92c Jan Kiszka
227 69d63a97 Jan Kiszka
    block_mig_state.submitted = 0;
228 69d63a97 Jan Kiszka
    block_mig_state.read_done = 0;
229 69d63a97 Jan Kiszka
    block_mig_state.transferred = 0;
230 82801d8f Jan Kiszka
    block_mig_state.total_sector_sum = 0;
231 01e61e2d Jan Kiszka
    block_mig_state.prev_progress = -1;
232 69d63a97 Jan Kiszka
233 c163b5ca lirans@il.ibm.com
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
234 a55eb92c Jan Kiszka
        if (bs->type == BDRV_TYPE_HD) {
235 792773b2 Jan Kiszka
            sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
236 792773b2 Jan Kiszka
            if (sectors == 0) {
237 792773b2 Jan Kiszka
                continue;
238 792773b2 Jan Kiszka
            }
239 792773b2 Jan Kiszka
240 c163b5ca lirans@il.ibm.com
            bmds = qemu_mallocz(sizeof(BlkMigDevState));
241 c163b5ca lirans@il.ibm.com
            bmds->bs = bs;
242 c163b5ca lirans@il.ibm.com
            bmds->bulk_completed = 0;
243 792773b2 Jan Kiszka
            bmds->total_sectors = sectors;
244 82801d8f Jan Kiszka
            bmds->completed_sectors = 0;
245 d11ecd3d Jan Kiszka
            bmds->shared_base = block_mig_state.shared_base;
246 a55eb92c Jan Kiszka
247 792773b2 Jan Kiszka
            block_mig_state.total_sector_sum += sectors;
248 82801d8f Jan Kiszka
249 a55eb92c Jan Kiszka
            if (bmds->shared_base) {
250 7184049e Jan Kiszka
                monitor_printf(mon, "Start migration for %s with shared base "
251 7184049e Jan Kiszka
                                    "image\n",
252 7184049e Jan Kiszka
                               bs->device_name);
253 c163b5ca lirans@il.ibm.com
            } else {
254 7184049e Jan Kiszka
                monitor_printf(mon, "Start full migration for %s\n",
255 7184049e Jan Kiszka
                               bs->device_name);
256 c163b5ca lirans@il.ibm.com
            }
257 a55eb92c Jan Kiszka
258 5e5328be Jan Kiszka
            QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
259 c163b5ca lirans@il.ibm.com
        }
260 a55eb92c Jan Kiszka
    }
261 c163b5ca lirans@il.ibm.com
}
262 c163b5ca lirans@il.ibm.com
263 7184049e Jan Kiszka
static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f, int is_async)
264 c163b5ca lirans@il.ibm.com
{
265 82801d8f Jan Kiszka
    int64_t completed_sector_sum = 0;
266 c163b5ca lirans@il.ibm.com
    BlkMigDevState *bmds;
267 01e61e2d Jan Kiszka
    int progress;
268 82801d8f Jan Kiszka
    int ret = 0;
269 c163b5ca lirans@il.ibm.com
270 5e5328be Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
271 a55eb92c Jan Kiszka
        if (bmds->bulk_completed == 0) {
272 7184049e Jan Kiszka
            if (mig_save_device_bulk(mon, f, bmds, is_async) == 1) {
273 57cce12d Jan Kiszka
                /* completed bulk section for this device */
274 57cce12d Jan Kiszka
                bmds->bulk_completed = 1;
275 c163b5ca lirans@il.ibm.com
            }
276 82801d8f Jan Kiszka
            completed_sector_sum += bmds->completed_sectors;
277 82801d8f Jan Kiszka
            ret = 1;
278 82801d8f Jan Kiszka
            break;
279 82801d8f Jan Kiszka
        } else {
280 82801d8f Jan Kiszka
            completed_sector_sum += bmds->completed_sectors;
281 c163b5ca lirans@il.ibm.com
        }
282 c163b5ca lirans@il.ibm.com
    }
283 a55eb92c Jan Kiszka
284 01e61e2d Jan Kiszka
    progress = completed_sector_sum * 100 / block_mig_state.total_sector_sum;
285 01e61e2d Jan Kiszka
    if (progress != block_mig_state.prev_progress) {
286 01e61e2d Jan Kiszka
        block_mig_state.prev_progress = progress;
287 01e61e2d Jan Kiszka
        qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
288 01e61e2d Jan Kiszka
                         | BLK_MIG_FLAG_PROGRESS);
289 01e61e2d Jan Kiszka
        monitor_printf(mon, "Completed %d %%\r", progress);
290 7184049e Jan Kiszka
        monitor_flush(mon);
291 82801d8f Jan Kiszka
    }
292 82801d8f Jan Kiszka
293 82801d8f Jan Kiszka
    return ret;
294 c163b5ca lirans@il.ibm.com
}
295 c163b5ca lirans@il.ibm.com
296 c163b5ca lirans@il.ibm.com
#define MAX_NUM_BLOCKS 4
297 c163b5ca lirans@il.ibm.com
298 7184049e Jan Kiszka
static void blk_mig_save_dirty_blocks(Monitor *mon, QEMUFile *f)
299 c163b5ca lirans@il.ibm.com
{
300 c163b5ca lirans@il.ibm.com
    BlkMigDevState *bmds;
301 13f0b67f Jan Kiszka
    BlkMigBlock blk;
302 c163b5ca lirans@il.ibm.com
    int64_t sector;
303 a55eb92c Jan Kiszka
304 13f0b67f Jan Kiszka
    blk.buf = qemu_malloc(BLOCK_SIZE);
305 575a58d7 Jan Kiszka
306 5e5328be Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
307 a55eb92c Jan Kiszka
        for (sector = 0; sector < bmds->cur_sector;) {
308 a55eb92c Jan Kiszka
            if (bdrv_get_dirty(bmds->bs, sector)) {
309 13f0b67f Jan Kiszka
                if (bdrv_read(bmds->bs, sector, blk.buf,
310 6ea44308 Jan Kiszka
                              BDRV_SECTORS_PER_DIRTY_CHUNK) < 0) {
311 7184049e Jan Kiszka
                    monitor_printf(mon, "Error reading sector %" PRId64 "\n",
312 7184049e Jan Kiszka
                                   sector);
313 4b640365 Jan Kiszka
                    qemu_file_set_error(f);
314 4b640365 Jan Kiszka
                    qemu_free(blk.buf);
315 4b640365 Jan Kiszka
                    return;
316 c163b5ca lirans@il.ibm.com
                }
317 13f0b67f Jan Kiszka
                blk.bmds = bmds;
318 13f0b67f Jan Kiszka
                blk.sector = sector;
319 13f0b67f Jan Kiszka
                blk_send(f, &blk);
320 a55eb92c Jan Kiszka
321 a55eb92c Jan Kiszka
                bdrv_reset_dirty(bmds->bs, sector,
322 6ea44308 Jan Kiszka
                                 BDRV_SECTORS_PER_DIRTY_CHUNK);
323 a55eb92c Jan Kiszka
            }
324 6ea44308 Jan Kiszka
            sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
325 c163b5ca lirans@il.ibm.com
        }
326 c163b5ca lirans@il.ibm.com
    }
327 575a58d7 Jan Kiszka
328 13f0b67f Jan Kiszka
    qemu_free(blk.buf);
329 c163b5ca lirans@il.ibm.com
}
330 c163b5ca lirans@il.ibm.com
331 c163b5ca lirans@il.ibm.com
static void flush_blks(QEMUFile* f)
332 c163b5ca lirans@il.ibm.com
{
333 5e5328be Jan Kiszka
    BlkMigBlock *blk;
334 a55eb92c Jan Kiszka
335 d11ecd3d Jan Kiszka
    dprintf("%s Enter submitted %d read_done %d transferred %d\n",
336 d11ecd3d Jan Kiszka
            __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
337 d11ecd3d Jan Kiszka
            block_mig_state.transferred);
338 a55eb92c Jan Kiszka
339 5e5328be Jan Kiszka
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
340 5e5328be Jan Kiszka
        if (qemu_file_rate_limit(f)) {
341 5e5328be Jan Kiszka
            break;
342 5e5328be Jan Kiszka
        }
343 4b640365 Jan Kiszka
        if (blk->ret < 0) {
344 4b640365 Jan Kiszka
            qemu_file_set_error(f);
345 4b640365 Jan Kiszka
            break;
346 4b640365 Jan Kiszka
        }
347 13f0b67f Jan Kiszka
        blk_send(f, blk);
348 a55eb92c Jan Kiszka
349 5e5328be Jan Kiszka
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
350 c163b5ca lirans@il.ibm.com
        qemu_free(blk->buf);
351 c163b5ca lirans@il.ibm.com
        qemu_free(blk);
352 a55eb92c Jan Kiszka
353 d11ecd3d Jan Kiszka
        block_mig_state.read_done--;
354 d11ecd3d Jan Kiszka
        block_mig_state.transferred++;
355 d11ecd3d Jan Kiszka
        assert(block_mig_state.read_done >= 0);
356 c163b5ca lirans@il.ibm.com
    }
357 c163b5ca lirans@il.ibm.com
358 d11ecd3d Jan Kiszka
    dprintf("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
359 d11ecd3d Jan Kiszka
            block_mig_state.submitted, block_mig_state.read_done,
360 d11ecd3d Jan Kiszka
            block_mig_state.transferred);
361 c163b5ca lirans@il.ibm.com
}
362 c163b5ca lirans@il.ibm.com
363 c163b5ca lirans@il.ibm.com
static int is_stage2_completed(void)
364 c163b5ca lirans@il.ibm.com
{
365 c163b5ca lirans@il.ibm.com
    BlkMigDevState *bmds;
366 a55eb92c Jan Kiszka
367 d11ecd3d Jan Kiszka
    if (block_mig_state.submitted > 0) {
368 c163b5ca lirans@il.ibm.com
        return 0;
369 c163b5ca lirans@il.ibm.com
    }
370 a55eb92c Jan Kiszka
371 5e5328be Jan Kiszka
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
372 a55eb92c Jan Kiszka
        if (bmds->bulk_completed == 0) {
373 c163b5ca lirans@il.ibm.com
            return 0;
374 c163b5ca lirans@il.ibm.com
        }
375 c163b5ca lirans@il.ibm.com
    }
376 a55eb92c Jan Kiszka
377 c163b5ca lirans@il.ibm.com
    return 1;
378 c163b5ca lirans@il.ibm.com
}
379 c163b5ca lirans@il.ibm.com
380 7184049e Jan Kiszka
static void blk_mig_cleanup(Monitor *mon)
381 4ec7fcc7 Jan Kiszka
{
382 82801d8f Jan Kiszka
    BlkMigDevState *bmds;
383 82801d8f Jan Kiszka
    BlkMigBlock *blk;
384 4ec7fcc7 Jan Kiszka
385 82801d8f Jan Kiszka
    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
386 82801d8f Jan Kiszka
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
387 4ec7fcc7 Jan Kiszka
        qemu_free(bmds);
388 4ec7fcc7 Jan Kiszka
    }
389 4ec7fcc7 Jan Kiszka
390 82801d8f Jan Kiszka
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
391 82801d8f Jan Kiszka
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
392 4ec7fcc7 Jan Kiszka
        qemu_free(blk->buf);
393 4ec7fcc7 Jan Kiszka
        qemu_free(blk);
394 4ec7fcc7 Jan Kiszka
    }
395 4ec7fcc7 Jan Kiszka
396 4ec7fcc7 Jan Kiszka
    set_dirty_tracking(0);
397 4ec7fcc7 Jan Kiszka
398 7184049e Jan Kiszka
    monitor_printf(mon, "\n");
399 4ec7fcc7 Jan Kiszka
}
400 4ec7fcc7 Jan Kiszka
401 f327aa0c Jan Kiszka
static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
402 c163b5ca lirans@il.ibm.com
{
403 d11ecd3d Jan Kiszka
    dprintf("Enter save live stage %d submitted %d transferred %d\n",
404 d11ecd3d Jan Kiszka
            stage, block_mig_state.submitted, block_mig_state.transferred);
405 a55eb92c Jan Kiszka
406 4ec7fcc7 Jan Kiszka
    if (stage < 0) {
407 7184049e Jan Kiszka
        blk_mig_cleanup(mon);
408 4ec7fcc7 Jan Kiszka
        return 0;
409 4ec7fcc7 Jan Kiszka
    }
410 4ec7fcc7 Jan Kiszka
411 d11ecd3d Jan Kiszka
    if (block_mig_state.blk_enable != 1) {
412 c163b5ca lirans@il.ibm.com
        /* no need to migrate storage */
413 a55eb92c Jan Kiszka
        qemu_put_be64(f, BLK_MIG_FLAG_EOS);
414 c163b5ca lirans@il.ibm.com
        return 1;
415 c163b5ca lirans@il.ibm.com
    }
416 a55eb92c Jan Kiszka
417 a55eb92c Jan Kiszka
    if (stage == 1) {
418 7184049e Jan Kiszka
        init_blk_migration(mon, f);
419 a55eb92c Jan Kiszka
420 c163b5ca lirans@il.ibm.com
        /* start track dirty blocks */
421 c163b5ca lirans@il.ibm.com
        set_dirty_tracking(1);
422 c163b5ca lirans@il.ibm.com
    }
423 c163b5ca lirans@il.ibm.com
424 c163b5ca lirans@il.ibm.com
    flush_blks(f);
425 a55eb92c Jan Kiszka
426 4b640365 Jan Kiszka
    if (qemu_file_has_error(f)) {
427 7184049e Jan Kiszka
        blk_mig_cleanup(mon);
428 4b640365 Jan Kiszka
        return 0;
429 4b640365 Jan Kiszka
    }
430 4b640365 Jan Kiszka
431 c163b5ca lirans@il.ibm.com
    /* control the rate of transfer */
432 d11ecd3d Jan Kiszka
    while ((block_mig_state.submitted +
433 d11ecd3d Jan Kiszka
            block_mig_state.read_done) * BLOCK_SIZE <
434 a55eb92c Jan Kiszka
           qemu_file_get_rate_limit(f)) {
435 7184049e Jan Kiszka
        if (blk_mig_save_bulked_block(mon, f, 1) == 0) {
436 a55eb92c Jan Kiszka
            /* no more bulk blocks for now */
437 c163b5ca lirans@il.ibm.com
            break;
438 a55eb92c Jan Kiszka
        }
439 c163b5ca lirans@il.ibm.com
    }
440 a55eb92c Jan Kiszka
441 c163b5ca lirans@il.ibm.com
    flush_blks(f);
442 a55eb92c Jan Kiszka
443 4b640365 Jan Kiszka
    if (qemu_file_has_error(f)) {
444 7184049e Jan Kiszka
        blk_mig_cleanup(mon);
445 4b640365 Jan Kiszka
        return 0;
446 4b640365 Jan Kiszka
    }
447 4b640365 Jan Kiszka
448 a55eb92c Jan Kiszka
    if (stage == 3) {
449 7184049e Jan Kiszka
        while (blk_mig_save_bulked_block(mon, f, 0) != 0) {
450 a55eb92c Jan Kiszka
            /* empty */
451 a55eb92c Jan Kiszka
        }
452 a55eb92c Jan Kiszka
453 7184049e Jan Kiszka
        blk_mig_save_dirty_blocks(mon, f);
454 7184049e Jan Kiszka
        blk_mig_cleanup(mon);
455 a55eb92c Jan Kiszka
456 01e61e2d Jan Kiszka
        /* report completion */
457 01e61e2d Jan Kiszka
        qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
458 01e61e2d Jan Kiszka
459 4b640365 Jan Kiszka
        if (qemu_file_has_error(f)) {
460 4b640365 Jan Kiszka
            return 0;
461 4b640365 Jan Kiszka
        }
462 4b640365 Jan Kiszka
463 7184049e Jan Kiszka
        monitor_printf(mon, "Block migration completed\n");
464 c163b5ca lirans@il.ibm.com
    }
465 a55eb92c Jan Kiszka
466 a55eb92c Jan Kiszka
    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
467 a55eb92c Jan Kiszka
468 c163b5ca lirans@il.ibm.com
    return ((stage == 2) && is_stage2_completed());
469 c163b5ca lirans@il.ibm.com
}
470 c163b5ca lirans@il.ibm.com
471 c163b5ca lirans@il.ibm.com
static int block_load(QEMUFile *f, void *opaque, int version_id)
472 c163b5ca lirans@il.ibm.com
{
473 01e61e2d Jan Kiszka
    static int banner_printed;
474 c163b5ca lirans@il.ibm.com
    int len, flags;
475 c163b5ca lirans@il.ibm.com
    char device_name[256];
476 c163b5ca lirans@il.ibm.com
    int64_t addr;
477 c163b5ca lirans@il.ibm.com
    BlockDriverState *bs;
478 c163b5ca lirans@il.ibm.com
    uint8_t *buf;
479 a55eb92c Jan Kiszka
480 c163b5ca lirans@il.ibm.com
    do {
481 c163b5ca lirans@il.ibm.com
        addr = qemu_get_be64(f);
482 a55eb92c Jan Kiszka
483 6ea44308 Jan Kiszka
        flags = addr & ~BDRV_SECTOR_MASK;
484 6ea44308 Jan Kiszka
        addr >>= BDRV_SECTOR_BITS;
485 a55eb92c Jan Kiszka
486 a55eb92c Jan Kiszka
        if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
487 c163b5ca lirans@il.ibm.com
            /* get device name */
488 c163b5ca lirans@il.ibm.com
            len = qemu_get_byte(f);
489 c163b5ca lirans@il.ibm.com
            qemu_get_buffer(f, (uint8_t *)device_name, len);
490 c163b5ca lirans@il.ibm.com
            device_name[len] = '\0';
491 a55eb92c Jan Kiszka
492 c163b5ca lirans@il.ibm.com
            bs = bdrv_find(device_name);
493 4b640365 Jan Kiszka
            if (!bs) {
494 4b640365 Jan Kiszka
                fprintf(stderr, "Error unknown block device %s\n",
495 4b640365 Jan Kiszka
                        device_name);
496 4b640365 Jan Kiszka
                return -EINVAL;
497 4b640365 Jan Kiszka
            }
498 a55eb92c Jan Kiszka
499 575a58d7 Jan Kiszka
            buf = qemu_malloc(BLOCK_SIZE);
500 575a58d7 Jan Kiszka
501 a55eb92c Jan Kiszka
            qemu_get_buffer(f, buf, BLOCK_SIZE);
502 4b640365 Jan Kiszka
            bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
503 575a58d7 Jan Kiszka
504 575a58d7 Jan Kiszka
            qemu_free(buf);
505 01e61e2d Jan Kiszka
        } else if (flags & BLK_MIG_FLAG_PROGRESS) {
506 01e61e2d Jan Kiszka
            if (!banner_printed) {
507 01e61e2d Jan Kiszka
                printf("Receiving block device images\n");
508 01e61e2d Jan Kiszka
                banner_printed = 1;
509 01e61e2d Jan Kiszka
            }
510 01e61e2d Jan Kiszka
            printf("Completed %d %%%c", (int)addr,
511 01e61e2d Jan Kiszka
                   (addr == 100) ? '\n' : '\r');
512 01e61e2d Jan Kiszka
            fflush(stdout);
513 a55eb92c Jan Kiszka
        } else if (!(flags & BLK_MIG_FLAG_EOS)) {
514 4b640365 Jan Kiszka
            fprintf(stderr, "Unknown flags\n");
515 4b640365 Jan Kiszka
            return -EINVAL;
516 4b640365 Jan Kiszka
        }
517 4b640365 Jan Kiszka
        if (qemu_file_has_error(f)) {
518 4b640365 Jan Kiszka
            return -EIO;
519 c163b5ca lirans@il.ibm.com
        }
520 a55eb92c Jan Kiszka
    } while (!(flags & BLK_MIG_FLAG_EOS));
521 a55eb92c Jan Kiszka
522 c163b5ca lirans@il.ibm.com
    return 0;
523 c163b5ca lirans@il.ibm.com
}
524 c163b5ca lirans@il.ibm.com
525 c163b5ca lirans@il.ibm.com
static void block_set_params(int blk_enable, int shared_base, void *opaque)
526 c163b5ca lirans@il.ibm.com
{
527 d11ecd3d Jan Kiszka
    block_mig_state.blk_enable = blk_enable;
528 d11ecd3d Jan Kiszka
    block_mig_state.shared_base = shared_base;
529 a55eb92c Jan Kiszka
530 c163b5ca lirans@il.ibm.com
    /* shared base means that blk_enable = 1 */
531 d11ecd3d Jan Kiszka
    block_mig_state.blk_enable |= shared_base;
532 c163b5ca lirans@il.ibm.com
}
533 c163b5ca lirans@il.ibm.com
534 c163b5ca lirans@il.ibm.com
void blk_mig_init(void)
535 a55eb92c Jan Kiszka
{
536 5e5328be Jan Kiszka
    QSIMPLEQ_INIT(&block_mig_state.bmds_list);
537 5e5328be Jan Kiszka
    QSIMPLEQ_INIT(&block_mig_state.blk_list);
538 5e5328be Jan Kiszka
539 a55eb92c Jan Kiszka
    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
540 d11ecd3d Jan Kiszka
                         NULL, block_load, &block_mig_state);
541 c163b5ca lirans@il.ibm.com
}