blob: 897fdbabb51e3247d88e3ef698620b0b7a12ce99 [file] [log] [blame]
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +02001/*
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 *
Paolo Bonzini6b620ca2012-01-13 17:44:23 +010012 * Contributions after 2012-01-13 are licensed under the terms of the
13 * GNU GPL, version 2 or (at your option) any later version.
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020014 */
15
16#include "qemu-common.h"
Paolo Bonzini737e1502012-12-17 18:19:44 +010017#include "block/block_int.h"
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020018#include "hw/hw.h"
Paolo Bonzini1de7afc2012-12-17 18:20:00 +010019#include "qemu/queue.h"
20#include "qemu/timer.h"
Paolo Bonzinicaf71f82012-12-17 18:19:50 +010021#include "migration/block.h"
22#include "migration/migration.h"
Paolo Bonzini9c17d612012-12-17 18:20:04 +010023#include "sysemu/blockdev.h"
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020024#include <assert.h>
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020025
Paolo Bonzini50717e92013-01-21 17:09:45 +010026#define BLOCK_SIZE (1 << 20)
27#define BDRV_SECTORS_PER_DIRTY_CHUNK (BLOCK_SIZE >> BDRV_SECTOR_BITS)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020028
29#define BLK_MIG_FLAG_DEVICE_BLOCK 0x01
30#define BLK_MIG_FLAG_EOS 0x02
Jan Kiszka01e61e22009-12-01 15:20:17 +010031#define BLK_MIG_FLAG_PROGRESS 0x04
Peter Lieven323004a2013-07-18 09:48:50 +020032#define BLK_MIG_FLAG_ZERO_BLOCK 0x08
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020033
34#define MAX_IS_ALLOCATED_SEARCH 65536
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020035
36//#define DEBUG_BLK_MIGRATION
37
38#ifdef DEBUG_BLK_MIGRATION
malcd0f2c4c2010-02-07 02:03:50 +030039#define DPRINTF(fmt, ...) \
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020040 do { printf("blk_migration: " fmt, ## __VA_ARGS__); } while (0)
41#else
malcd0f2c4c2010-02-07 02:03:50 +030042#define DPRINTF(fmt, ...) \
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020043 do { } while (0)
44#endif
45
Jan Kiszkaa55eb922009-11-30 18:21:19 +010046typedef struct BlkMigDevState {
Paolo Bonzini323920c2013-02-22 17:36:24 +010047 /* Written during setup phase. Can be read without a lock. */
Jan Kiszkaa55eb922009-11-30 18:21:19 +010048 BlockDriverState *bs;
Jan Kiszkaa55eb922009-11-30 18:21:19 +010049 int shared_base;
Jan Kiszkaa55eb922009-11-30 18:21:19 +010050 int64_t total_sectors;
Jan Kiszka5e5328b2009-11-30 18:21:20 +010051 QSIMPLEQ_ENTRY(BlkMigDevState) entry;
Paolo Bonzini323920c2013-02-22 17:36:24 +010052
53 /* Only used by migration thread. Does not need a lock. */
54 int bulk_completed;
55 int64_t cur_sector;
56 int64_t cur_dirty;
57
Paolo Bonzini52e850d2013-02-22 17:36:25 +010058 /* Protected by block migration lock. */
Marcelo Tosatti33656af2010-11-08 17:02:56 -020059 unsigned long *aio_bitmap;
Paolo Bonzini323920c2013-02-22 17:36:24 +010060 int64_t completed_sectors;
Fam Zhenge4654d22013-11-13 18:29:43 +080061 BdrvDirtyBitmap *dirty_bitmap;
Jan Kiszkaa55eb922009-11-30 18:21:19 +010062} BlkMigDevState;
63
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020064typedef struct BlkMigBlock {
Paolo Bonzini323920c2013-02-22 17:36:24 +010065 /* Only used by migration thread. */
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020066 uint8_t *buf;
67 BlkMigDevState *bmds;
68 int64_t sector;
Marcelo Tosatti33656af2010-11-08 17:02:56 -020069 int nr_sectors;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020070 struct iovec iov;
71 QEMUIOVector qiov;
72 BlockDriverAIOCB *aiocb;
Paolo Bonzini323920c2013-02-22 17:36:24 +010073
Paolo Bonzini52e850d2013-02-22 17:36:25 +010074 /* Protected by block migration lock. */
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020075 int ret;
Jan Kiszka5e5328b2009-11-30 18:21:20 +010076 QSIMPLEQ_ENTRY(BlkMigBlock) entry;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020077} BlkMigBlock;
78
79typedef struct BlkMigState {
Paolo Bonzini323920c2013-02-22 17:36:24 +010080 /* Written during setup phase. Can be read without a lock. */
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020081 int blk_enable;
82 int shared_base;
Jan Kiszka5e5328b2009-11-30 18:21:20 +010083 QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
Paolo Bonzini323920c2013-02-22 17:36:24 +010084 int64_t total_sector_sum;
Peter Lieven323004a2013-07-18 09:48:50 +020085 bool zero_blocks;
Paolo Bonzini323920c2013-02-22 17:36:24 +010086
Paolo Bonzini52e850d2013-02-22 17:36:25 +010087 /* Protected by lock. */
Jan Kiszka5e5328b2009-11-30 18:21:20 +010088 QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020089 int submitted;
90 int read_done;
Paolo Bonzini323920c2013-02-22 17:36:24 +010091
92 /* Only used by migration thread. Does not need a lock. */
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020093 int transferred;
Jan Kiszka01e61e22009-12-01 15:20:17 +010094 int prev_progress;
Liran Schoure970ec02010-01-26 10:31:45 +020095 int bulk_completed;
Paolo Bonzini52e850d2013-02-22 17:36:25 +010096
97 /* Lock must be taken _inside_ the iothread lock. */
98 QemuMutex lock;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +020099} BlkMigState;
100
Jan Kiszkad11ecd32009-11-30 18:21:20 +0100101static BlkMigState block_mig_state;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200102
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100103static void blk_mig_lock(void)
104{
105 qemu_mutex_lock(&block_mig_state.lock);
106}
107
108static void blk_mig_unlock(void)
109{
110 qemu_mutex_unlock(&block_mig_state.lock);
111}
112
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100113/* Must run outside of the iothread lock during the bulk phase,
114 * or the VM will stall.
115 */
116
Jan Kiszka13f0b672009-11-30 18:21:21 +0100117static void blk_send(QEMUFile *f, BlkMigBlock * blk)
118{
119 int len;
Peter Lieven323004a2013-07-18 09:48:50 +0200120 uint64_t flags = BLK_MIG_FLAG_DEVICE_BLOCK;
121
122 if (block_mig_state.zero_blocks &&
123 buffer_is_zero(blk->buf, BLOCK_SIZE)) {
124 flags |= BLK_MIG_FLAG_ZERO_BLOCK;
125 }
Jan Kiszka13f0b672009-11-30 18:21:21 +0100126
127 /* sector number and flags */
128 qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
Peter Lieven323004a2013-07-18 09:48:50 +0200129 | flags);
Jan Kiszka13f0b672009-11-30 18:21:21 +0100130
131 /* device name */
132 len = strlen(blk->bmds->bs->device_name);
133 qemu_put_byte(f, len);
134 qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
135
Peter Lieven323004a2013-07-18 09:48:50 +0200136 /* if a block is zero we need to flush here since the network
137 * bandwidth is now a lot higher than the storage device bandwidth.
138 * thus if we queue zero blocks we slow down the migration */
139 if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
140 qemu_fflush(f);
141 return;
142 }
143
Jan Kiszka13f0b672009-11-30 18:21:21 +0100144 qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
145}
146
Jan Kiszka25f23642009-11-30 18:21:21 +0100147int blk_mig_active(void)
148{
149 return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
150}
151
152uint64_t blk_mig_bytes_transferred(void)
153{
154 BlkMigDevState *bmds;
155 uint64_t sum = 0;
156
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100157 blk_mig_lock();
Jan Kiszka25f23642009-11-30 18:21:21 +0100158 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
159 sum += bmds->completed_sectors;
160 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100161 blk_mig_unlock();
Jan Kiszka25f23642009-11-30 18:21:21 +0100162 return sum << BDRV_SECTOR_BITS;
163}
164
165uint64_t blk_mig_bytes_remaining(void)
166{
167 return blk_mig_bytes_total() - blk_mig_bytes_transferred();
168}
169
170uint64_t blk_mig_bytes_total(void)
171{
172 BlkMigDevState *bmds;
173 uint64_t sum = 0;
174
175 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
176 sum += bmds->total_sectors;
177 }
178 return sum << BDRV_SECTOR_BITS;
179}
180
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100181
182/* Called with migration lock held. */
183
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200184static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
185{
186 int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
187
Marcelo Tosatti62155e22010-11-12 16:07:50 -0200188 if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200189 return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
190 (1UL << (chunk % (sizeof(unsigned long) * 8))));
191 } else {
192 return 0;
193 }
194}
195
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100196/* Called with migration lock held. */
197
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200198static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
199 int nb_sectors, int set)
200{
201 int64_t start, end;
202 unsigned long val, idx, bit;
203
204 start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
205 end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
206
207 for (; start <= end; start++) {
208 idx = start / (sizeof(unsigned long) * 8);
209 bit = start % (sizeof(unsigned long) * 8);
210 val = bmds->aio_bitmap[idx];
211 if (set) {
Marcelo Tosatti62155e22010-11-12 16:07:50 -0200212 val |= 1UL << bit;
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200213 } else {
Marcelo Tosatti62155e22010-11-12 16:07:50 -0200214 val &= ~(1UL << bit);
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200215 }
216 bmds->aio_bitmap[idx] = val;
217 }
218}
219
220static void alloc_aio_bitmap(BlkMigDevState *bmds)
221{
222 BlockDriverState *bs = bmds->bs;
223 int64_t bitmap_size;
224
225 bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
226 BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
227 bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
228
Anthony Liguori7267c092011-08-20 22:09:37 -0500229 bmds->aio_bitmap = g_malloc0(bitmap_size);
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200230}
231
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100232/* Never hold migration lock when yielding to the main loop! */
233
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200234static void blk_mig_read_cb(void *opaque, int ret)
235{
236 BlkMigBlock *blk = opaque;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100237
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100238 blk_mig_lock();
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200239 blk->ret = ret;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100240
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100241 QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200242 bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100243
Jan Kiszkad11ecd32009-11-30 18:21:20 +0100244 block_mig_state.submitted--;
245 block_mig_state.read_done++;
246 assert(block_mig_state.submitted >= 0);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100247 blk_mig_unlock();
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200248}
249
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100250/* Called with no lock taken. */
251
Luiz Capitulino539de122011-12-05 14:06:56 -0200252static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100253{
Jan Kiszka57cce122009-11-30 18:21:20 +0100254 int64_t total_sectors = bmds->total_sectors;
255 int64_t cur_sector = bmds->cur_sector;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200256 BlockDriverState *bs = bmds->bs;
Jan Kiszka57cce122009-11-30 18:21:20 +0100257 BlkMigBlock *blk;
Jan Kiszka13f0b672009-11-30 18:21:21 +0100258 int nr_sectors;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100259
260 if (bmds->shared_base) {
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100261 qemu_mutex_lock_iothread();
Jan Kiszkab1d10852009-11-30 18:21:20 +0100262 while (cur_sector < total_sectors &&
Jan Kiszka57cce122009-11-30 18:21:20 +0100263 !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
264 &nr_sectors)) {
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200265 cur_sector += nr_sectors;
266 }
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100267 qemu_mutex_unlock_iothread();
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200268 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100269
270 if (cur_sector >= total_sectors) {
Jan Kiszka82801d82009-11-30 18:21:21 +0100271 bmds->cur_sector = bmds->completed_sectors = total_sectors;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200272 return 1;
273 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100274
Jan Kiszka82801d82009-11-30 18:21:21 +0100275 bmds->completed_sectors = cur_sector;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100276
Jan Kiszka6ea44302009-11-30 18:21:19 +0100277 cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100278
Jan Kiszka6ea44302009-11-30 18:21:19 +0100279 /* we are going to transfer a full block even if it is not allocated */
280 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100281
Jan Kiszka6ea44302009-11-30 18:21:19 +0100282 if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
Jan Kiszka57cce122009-11-30 18:21:20 +0100283 nr_sectors = total_sectors - cur_sector;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200284 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100285
Anthony Liguori7267c092011-08-20 22:09:37 -0500286 blk = g_malloc(sizeof(BlkMigBlock));
287 blk->buf = g_malloc(BLOCK_SIZE);
Jan Kiszka13f0b672009-11-30 18:21:21 +0100288 blk->bmds = bmds;
289 blk->sector = cur_sector;
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200290 blk->nr_sectors = nr_sectors;
Jan Kiszka13f0b672009-11-30 18:21:21 +0100291
Liran Schoure970ec02010-01-26 10:31:45 +0200292 blk->iov.iov_base = blk->buf;
293 blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
294 qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
Jan Kiszka57cce122009-11-30 18:21:20 +0100295
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100296 blk_mig_lock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100297 block_mig_state.submitted++;
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100298 blk_mig_unlock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100299
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100300 qemu_mutex_lock_iothread();
Liran Schoure970ec02010-01-26 10:31:45 +0200301 blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
302 nr_sectors, blk_mig_read_cb, blk);
Liran Schourd76cac72010-01-26 14:04:11 +0200303
Jan Kiszka13f0b672009-11-30 18:21:21 +0100304 bdrv_reset_dirty(bs, cur_sector, nr_sectors);
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100305 qemu_mutex_unlock_iothread();
Jan Kiszka13f0b672009-11-30 18:21:21 +0100306
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100307 bmds->cur_sector = cur_sector + nr_sectors;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200308 return (bmds->cur_sector >= total_sectors);
309}
310
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100311/* Called with iothread lock taken. */
312
Fam Zhenge4654d22013-11-13 18:29:43 +0800313static void set_dirty_tracking(void)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200314{
315 BlkMigDevState *bmds;
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100316
317 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
Fam Zhenge4654d22013-11-13 18:29:43 +0800318 bmds->dirty_bitmap = bdrv_create_dirty_bitmap(bmds->bs, BLOCK_SIZE);
319 }
320}
321
322static void unset_dirty_tracking(void)
323{
324 BlkMigDevState *bmds;
325
326 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
327 bdrv_release_dirty_bitmap(bmds->bs, bmds->dirty_bitmap);
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200328 }
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200329}
330
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100331static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200332{
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100333 BlkMigDevState *bmds;
Jan Kiszka792773b2009-11-30 20:34:55 +0100334 int64_t sectors;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100335
Markus Armbrusterd2466732010-06-28 10:45:02 +0200336 if (!bdrv_is_read_only(bs)) {
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100337 sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
Shahar Havivi31f54f22010-07-10 18:59:06 +0300338 if (sectors <= 0) {
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100339 return;
340 }
341
Anthony Liguori7267c092011-08-20 22:09:37 -0500342 bmds = g_malloc0(sizeof(BlkMigDevState));
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100343 bmds->bs = bs;
344 bmds->bulk_completed = 0;
345 bmds->total_sectors = sectors;
346 bmds->completed_sectors = 0;
347 bmds->shared_base = block_mig_state.shared_base;
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200348 alloc_aio_bitmap(bmds);
Marcelo Tosatti85916752011-01-26 12:12:35 -0200349 bdrv_set_in_use(bs, 1);
Fam Zheng8442cfd2013-08-23 09:14:48 +0800350 bdrv_ref(bs);
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100351
352 block_mig_state.total_sector_sum += sectors;
353
354 if (bmds->shared_base) {
Luiz Capitulino539de122011-12-05 14:06:56 -0200355 DPRINTF("Start migration for %s with shared base image\n",
356 bs->device_name);
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100357 } else {
Luiz Capitulino539de122011-12-05 14:06:56 -0200358 DPRINTF("Start full migration for %s\n", bs->device_name);
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100359 }
360
361 QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
362 }
363}
364
Luiz Capitulino539de122011-12-05 14:06:56 -0200365static void init_blk_migration(QEMUFile *f)
Stefan Hajnoczib66460e2010-04-09 15:22:13 +0100366{
Jan Kiszka69d63a92009-11-30 18:21:20 +0100367 block_mig_state.submitted = 0;
368 block_mig_state.read_done = 0;
369 block_mig_state.transferred = 0;
Jan Kiszka82801d82009-11-30 18:21:21 +0100370 block_mig_state.total_sector_sum = 0;
Jan Kiszka01e61e22009-12-01 15:20:17 +0100371 block_mig_state.prev_progress = -1;
Liran Schoure970ec02010-01-26 10:31:45 +0200372 block_mig_state.bulk_completed = 0;
Peter Lieven323004a2013-07-18 09:48:50 +0200373 block_mig_state.zero_blocks = migrate_zero_blocks();
Jan Kiszka69d63a92009-11-30 18:21:20 +0100374
Luiz Capitulino539de122011-12-05 14:06:56 -0200375 bdrv_iterate(init_blk_migration_it, NULL);
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200376}
377
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100378/* Called with no lock taken. */
379
Luiz Capitulino539de122011-12-05 14:06:56 -0200380static int blk_mig_save_bulked_block(QEMUFile *f)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200381{
Jan Kiszka82801d82009-11-30 18:21:21 +0100382 int64_t completed_sector_sum = 0;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200383 BlkMigDevState *bmds;
Jan Kiszka01e61e22009-12-01 15:20:17 +0100384 int progress;
Jan Kiszka82801d82009-11-30 18:21:21 +0100385 int ret = 0;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200386
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100387 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100388 if (bmds->bulk_completed == 0) {
Luiz Capitulino539de122011-12-05 14:06:56 -0200389 if (mig_save_device_bulk(f, bmds) == 1) {
Jan Kiszka57cce122009-11-30 18:21:20 +0100390 /* completed bulk section for this device */
391 bmds->bulk_completed = 1;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200392 }
Jan Kiszka82801d82009-11-30 18:21:21 +0100393 completed_sector_sum += bmds->completed_sectors;
394 ret = 1;
395 break;
396 } else {
397 completed_sector_sum += bmds->completed_sectors;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200398 }
399 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100400
Pierre Riteau8b6b2af2011-01-12 14:41:00 +0100401 if (block_mig_state.total_sector_sum != 0) {
402 progress = completed_sector_sum * 100 /
403 block_mig_state.total_sector_sum;
404 } else {
405 progress = 100;
406 }
Jan Kiszka01e61e22009-12-01 15:20:17 +0100407 if (progress != block_mig_state.prev_progress) {
408 block_mig_state.prev_progress = progress;
409 qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
410 | BLK_MIG_FLAG_PROGRESS);
Luiz Capitulino539de122011-12-05 14:06:56 -0200411 DPRINTF("Completed %d %%\r", progress);
Jan Kiszka82801d82009-11-30 18:21:21 +0100412 }
413
414 return ret;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200415}
416
Liran Schourd76cac72010-01-26 14:04:11 +0200417static void blk_mig_reset_dirty_cursor(void)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200418{
419 BlkMigDevState *bmds;
Jan Kiszka575a58d2009-11-30 18:21:20 +0100420
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100421 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
Liran Schourd76cac72010-01-26 14:04:11 +0200422 bmds->cur_dirty = 0;
423 }
424}
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100425
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100426/* Called with iothread lock taken. */
427
Luiz Capitulino539de122011-12-05 14:06:56 -0200428static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
429 int is_async)
Liran Schourd76cac72010-01-26 14:04:11 +0200430{
431 BlkMigBlock *blk;
432 int64_t total_sectors = bmds->total_sectors;
433 int64_t sector;
434 int nr_sectors;
Juan Quinteladcd1d222011-09-21 23:01:54 +0200435 int ret = -EIO;
Liran Schourd76cac72010-01-26 14:04:11 +0200436
437 for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100438 blk_mig_lock();
Marcelo Tosatti62155e22010-11-12 16:07:50 -0200439 if (bmds_aio_inflight(bmds, sector)) {
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100440 blk_mig_unlock();
Stefan Hajnoczi922453b2011-11-30 12:23:43 +0000441 bdrv_drain_all();
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100442 } else {
443 blk_mig_unlock();
Marcelo Tosatti62155e22010-11-12 16:07:50 -0200444 }
Fam Zhenge4654d22013-11-13 18:29:43 +0800445 if (bdrv_get_dirty(bmds->bs, bmds->dirty_bitmap, sector)) {
Liran Schourd76cac72010-01-26 14:04:11 +0200446
447 if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
448 nr_sectors = total_sectors - sector;
449 } else {
450 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100451 }
Anthony Liguori7267c092011-08-20 22:09:37 -0500452 blk = g_malloc(sizeof(BlkMigBlock));
453 blk->buf = g_malloc(BLOCK_SIZE);
Liran Schourd76cac72010-01-26 14:04:11 +0200454 blk->bmds = bmds;
455 blk->sector = sector;
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200456 blk->nr_sectors = nr_sectors;
Liran Schourd76cac72010-01-26 14:04:11 +0200457
Liran Schour889ae392010-01-26 10:31:49 +0200458 if (is_async) {
Liran Schourd76cac72010-01-26 14:04:11 +0200459 blk->iov.iov_base = blk->buf;
460 blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
461 qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
462
463 blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
464 nr_sectors, blk_mig_read_cb, blk);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100465
466 blk_mig_lock();
Liran Schourd76cac72010-01-26 14:04:11 +0200467 block_mig_state.submitted++;
Marcelo Tosatti33656af2010-11-08 17:02:56 -0200468 bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100469 blk_mig_unlock();
Liran Schourd76cac72010-01-26 14:04:11 +0200470 } else {
Juan Quinteladcd1d222011-09-21 23:01:54 +0200471 ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
472 if (ret < 0) {
Liran Schourd76cac72010-01-26 14:04:11 +0200473 goto error;
474 }
475 blk_send(f, blk);
476
Anthony Liguori7267c092011-08-20 22:09:37 -0500477 g_free(blk->buf);
478 g_free(blk);
Liran Schourd76cac72010-01-26 14:04:11 +0200479 }
480
481 bdrv_reset_dirty(bmds->bs, sector, nr_sectors);
482 break;
483 }
484 sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
485 bmds->cur_dirty = sector;
486 }
487
488 return (bmds->cur_dirty >= bmds->total_sectors);
489
Liran Schour889ae392010-01-26 10:31:49 +0200490error:
Luiz Capitulino539de122011-12-05 14:06:56 -0200491 DPRINTF("Error reading sector %" PRId64 "\n", sector);
Anthony Liguori7267c092011-08-20 22:09:37 -0500492 g_free(blk->buf);
493 g_free(blk);
Juan Quintela43be3a22012-08-29 21:59:22 +0200494 return ret;
Liran Schourd76cac72010-01-26 14:04:11 +0200495}
496
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100497/* Called with iothread lock taken.
498 *
499 * return value:
Juan Quintelaceb2bd02012-08-29 21:37:14 +0200500 * 0: too much data for max_downtime
501 * 1: few enough data for max_downtime
502*/
Luiz Capitulino539de122011-12-05 14:06:56 -0200503static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
Liran Schourd76cac72010-01-26 14:04:11 +0200504{
505 BlkMigDevState *bmds;
Juan Quintelaceb2bd02012-08-29 21:37:14 +0200506 int ret = 1;
Liran Schourd76cac72010-01-26 14:04:11 +0200507
508 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
Juan Quintelaceb2bd02012-08-29 21:37:14 +0200509 ret = mig_save_device_dirty(f, bmds, is_async);
Juan Quintela43be3a22012-08-29 21:59:22 +0200510 if (ret <= 0) {
Liran Schourd76cac72010-01-26 14:04:11 +0200511 break;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200512 }
513 }
Jan Kiszka575a58d2009-11-30 18:21:20 +0100514
Liran Schourd76cac72010-01-26 14:04:11 +0200515 return ret;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200516}
517
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100518/* Called with no locks taken. */
519
Juan Quintela59feec42012-08-29 20:17:13 +0200520static int flush_blks(QEMUFile *f)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200521{
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100522 BlkMigBlock *blk;
Juan Quintela59feec42012-08-29 20:17:13 +0200523 int ret = 0;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100524
malcd0f2c4c2010-02-07 02:03:50 +0300525 DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
Jan Kiszkad11ecd32009-11-30 18:21:20 +0100526 __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
527 block_mig_state.transferred);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100528
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100529 blk_mig_lock();
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100530 while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
531 if (qemu_file_rate_limit(f)) {
532 break;
533 }
Jan Kiszka4b640362009-11-30 18:21:21 +0100534 if (blk->ret < 0) {
Juan Quintela59feec42012-08-29 20:17:13 +0200535 ret = blk->ret;
Jan Kiszka4b640362009-11-30 18:21:21 +0100536 break;
537 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100538
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100539 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100540 blk_mig_unlock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100541 blk_send(f, blk);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100542 blk_mig_lock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100543
Anthony Liguori7267c092011-08-20 22:09:37 -0500544 g_free(blk->buf);
545 g_free(blk);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100546
Jan Kiszkad11ecd32009-11-30 18:21:20 +0100547 block_mig_state.read_done--;
548 block_mig_state.transferred++;
549 assert(block_mig_state.read_done >= 0);
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200550 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100551 blk_mig_unlock();
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200552
malcd0f2c4c2010-02-07 02:03:50 +0300553 DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
Jan Kiszkad11ecd32009-11-30 18:21:20 +0100554 block_mig_state.submitted, block_mig_state.read_done,
555 block_mig_state.transferred);
Juan Quintela59feec42012-08-29 20:17:13 +0200556 return ret;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200557}
558
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100559/* Called with iothread lock taken. */
560
Liran Schour889ae392010-01-26 10:31:49 +0200561static int64_t get_remaining_dirty(void)
562{
563 BlkMigDevState *bmds;
564 int64_t dirty = 0;
565
566 QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
Fam Zhenge4654d22013-11-13 18:29:43 +0800567 dirty += bdrv_get_dirty_count(bmds->bs, bmds->dirty_bitmap);
Liran Schour889ae392010-01-26 10:31:49 +0200568 }
569
Paolo Bonziniacc906c2013-01-21 17:09:44 +0100570 return dirty << BDRV_SECTOR_BITS;
Liran Schour889ae392010-01-26 10:31:49 +0200571}
572
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100573/* Called with iothread lock taken. */
574
Luiz Capitulino539de122011-12-05 14:06:56 -0200575static void blk_mig_cleanup(void)
Jan Kiszka4ec7fcc2009-11-30 18:21:21 +0100576{
Jan Kiszka82801d82009-11-30 18:21:21 +0100577 BlkMigDevState *bmds;
578 BlkMigBlock *blk;
Jan Kiszka4ec7fcc2009-11-30 18:21:21 +0100579
Kevin Wolf946d58b2012-09-25 15:47:36 +0200580 bdrv_drain_all();
581
Fam Zhenge4654d22013-11-13 18:29:43 +0800582 unset_dirty_tracking();
Marcelo Tosatti8f794c52011-01-26 12:12:31 -0200583
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100584 blk_mig_lock();
Jan Kiszka82801d82009-11-30 18:21:21 +0100585 while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
586 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
Marcelo Tosatti85916752011-01-26 12:12:35 -0200587 bdrv_set_in_use(bmds->bs, 0);
Fam Zheng8442cfd2013-08-23 09:14:48 +0800588 bdrv_unref(bmds->bs);
Anthony Liguori7267c092011-08-20 22:09:37 -0500589 g_free(bmds->aio_bitmap);
590 g_free(bmds);
Jan Kiszka4ec7fcc2009-11-30 18:21:21 +0100591 }
592
Jan Kiszka82801d82009-11-30 18:21:21 +0100593 while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
594 QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
Anthony Liguori7267c092011-08-20 22:09:37 -0500595 g_free(blk->buf);
596 g_free(blk);
Jan Kiszka4ec7fcc2009-11-30 18:21:21 +0100597 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100598 blk_mig_unlock();
Jan Kiszka4ec7fcc2009-11-30 18:21:21 +0100599}
600
Juan Quintela9b5bfab2012-06-26 19:26:41 +0200601static void block_migration_cancel(void *opaque)
602{
603 blk_mig_cleanup();
604}
605
Juan Quintelad1315aa2012-06-28 15:11:57 +0200606static int block_save_setup(QEMUFile *f, void *opaque)
607{
608 int ret;
609
610 DPRINTF("Enter save live setup submitted %d transferred %d\n",
611 block_mig_state.submitted, block_mig_state.transferred);
612
Paolo Bonzini9b095032013-02-22 17:36:28 +0100613 qemu_mutex_lock_iothread();
Juan Quintelad1315aa2012-06-28 15:11:57 +0200614 init_blk_migration(f);
615
616 /* start track dirty blocks */
Fam Zhenge4654d22013-11-13 18:29:43 +0800617 set_dirty_tracking();
Paolo Bonzini9b095032013-02-22 17:36:28 +0100618 qemu_mutex_unlock_iothread();
Juan Quintelad1315aa2012-06-28 15:11:57 +0200619
Juan Quintela59feec42012-08-29 20:17:13 +0200620 ret = flush_blks(f);
Juan Quintelad1315aa2012-06-28 15:11:57 +0200621 blk_mig_reset_dirty_cursor();
Juan Quintelad1315aa2012-06-28 15:11:57 +0200622 qemu_put_be64(f, BLK_MIG_FLAG_EOS);
623
Paolo Bonzinid418cf52013-02-22 17:36:11 +0100624 return ret;
Juan Quintelad1315aa2012-06-28 15:11:57 +0200625}
626
Juan Quintela16310a32012-06-28 15:31:37 +0200627static int block_save_iterate(QEMUFile *f, void *opaque)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200628{
Juan Quintela29757252011-10-19 15:22:18 +0200629 int ret;
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100630 int64_t last_ftell = qemu_ftell(f);
Juan Quintela29757252011-10-19 15:22:18 +0200631
Juan Quintela16310a32012-06-28 15:31:37 +0200632 DPRINTF("Enter save live iterate submitted %d transferred %d\n",
633 block_mig_state.submitted, block_mig_state.transferred);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100634
Juan Quintela59feec42012-08-29 20:17:13 +0200635 ret = flush_blks(f);
Juan Quintela29757252011-10-19 15:22:18 +0200636 if (ret) {
Juan Quintela29757252011-10-19 15:22:18 +0200637 return ret;
Jan Kiszka4b640362009-11-30 18:21:21 +0100638 }
639
Liran Schourd76cac72010-01-26 14:04:11 +0200640 blk_mig_reset_dirty_cursor();
641
Juan Quintela16310a32012-06-28 15:31:37 +0200642 /* control the rate of transfer */
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100643 blk_mig_lock();
Juan Quintela16310a32012-06-28 15:31:37 +0200644 while ((block_mig_state.submitted +
645 block_mig_state.read_done) * BLOCK_SIZE <
646 qemu_file_get_rate_limit(f)) {
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100647 blk_mig_unlock();
Juan Quintela16310a32012-06-28 15:31:37 +0200648 if (block_mig_state.bulk_completed == 0) {
649 /* first finish the bulk phase */
650 if (blk_mig_save_bulked_block(f) == 0) {
651 /* finished saving bulk on all devices */
652 block_mig_state.bulk_completed = 1;
Liran Schourd76cac72010-01-26 14:04:11 +0200653 }
Paolo Bonzini13197e32013-02-22 17:36:23 +0100654 ret = 0;
Juan Quintela16310a32012-06-28 15:31:37 +0200655 } else {
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100656 /* Always called with iothread lock taken for
657 * simplicity, block_save_complete also calls it.
658 */
659 qemu_mutex_lock_iothread();
Juan Quintela43be3a22012-08-29 21:59:22 +0200660 ret = blk_mig_save_dirty_block(f, 1);
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100661 qemu_mutex_unlock_iothread();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100662 }
663 if (ret < 0) {
664 return ret;
665 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100666 blk_mig_lock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100667 if (ret != 0) {
668 /* no more dirty blocks */
669 break;
Liran Schourd76cac72010-01-26 14:04:11 +0200670 }
Jan Kiszka4b640362009-11-30 18:21:21 +0100671 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100672 blk_mig_unlock();
Jan Kiszka4b640362009-11-30 18:21:21 +0100673
Juan Quintela59feec42012-08-29 20:17:13 +0200674 ret = flush_blks(f);
Juan Quintela16310a32012-06-28 15:31:37 +0200675 if (ret) {
Juan Quintela16310a32012-06-28 15:31:37 +0200676 return ret;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200677 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100678
679 qemu_put_be64(f, BLK_MIG_FLAG_EOS);
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100680 return qemu_ftell(f) - last_ftell;
Juan Quintela16310a32012-06-28 15:31:37 +0200681}
682
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100683/* Called with iothread lock taken. */
684
Juan Quintela16310a32012-06-28 15:31:37 +0200685static int block_save_complete(QEMUFile *f, void *opaque)
686{
687 int ret;
688
689 DPRINTF("Enter save live complete submitted %d transferred %d\n",
690 block_mig_state.submitted, block_mig_state.transferred);
691
Juan Quintela59feec42012-08-29 20:17:13 +0200692 ret = flush_blks(f);
Juan Quintela16310a32012-06-28 15:31:37 +0200693 if (ret) {
Juan Quintela16310a32012-06-28 15:31:37 +0200694 return ret;
695 }
696
697 blk_mig_reset_dirty_cursor();
698
699 /* we know for sure that save bulk is completed and
700 all async read completed */
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100701 blk_mig_lock();
Juan Quintela16310a32012-06-28 15:31:37 +0200702 assert(block_mig_state.submitted == 0);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100703 blk_mig_unlock();
Juan Quintela16310a32012-06-28 15:31:37 +0200704
Juan Quintela43be3a22012-08-29 21:59:22 +0200705 do {
706 ret = blk_mig_save_dirty_block(f, 0);
Paolo Bonzinid418cf52013-02-22 17:36:11 +0100707 if (ret < 0) {
708 return ret;
709 }
Juan Quintela43be3a22012-08-29 21:59:22 +0200710 } while (ret == 0);
711
Juan Quintela43be3a22012-08-29 21:59:22 +0200712 /* report completion */
713 qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
Juan Quintela16310a32012-06-28 15:31:37 +0200714
715 DPRINTF("Block migration completed\n");
716
717 qemu_put_be64(f, BLK_MIG_FLAG_EOS);
718
Paolo Bonzinid418cf52013-02-22 17:36:11 +0100719 blk_mig_cleanup();
Juan Quintela16310a32012-06-28 15:31:37 +0200720 return 0;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200721}
722
Juan Quintelae4ed1542012-09-21 11:18:18 +0200723static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
724{
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100725 /* Estimate pending number of bytes to send */
Paolo Bonzini13197e32013-02-22 17:36:23 +0100726 uint64_t pending;
727
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100728 qemu_mutex_lock_iothread();
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100729 blk_mig_lock();
Paolo Bonzini13197e32013-02-22 17:36:23 +0100730 pending = get_remaining_dirty() +
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100731 block_mig_state.submitted * BLOCK_SIZE +
732 block_mig_state.read_done * BLOCK_SIZE;
Juan Quintelae4ed1542012-09-21 11:18:18 +0200733
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100734 /* Report at least one block pending during bulk phase */
735 if (pending == 0 && !block_mig_state.bulk_completed) {
736 pending = BLOCK_SIZE;
737 }
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100738 blk_mig_unlock();
Paolo Bonzini32c835b2013-02-22 17:36:27 +0100739 qemu_mutex_unlock_iothread();
Juan Quintelae4ed1542012-09-21 11:18:18 +0200740
Stefan Hajnoczi6aaa9da2013-02-12 10:37:15 +0100741 DPRINTF("Enter save live pending %" PRIu64 "\n", pending);
742 return pending;
Juan Quintelae4ed1542012-09-21 11:18:18 +0200743}
744
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200745static int block_load(QEMUFile *f, void *opaque, int version_id)
746{
Jan Kiszka01e61e22009-12-01 15:20:17 +0100747 static int banner_printed;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200748 int len, flags;
749 char device_name[256];
750 int64_t addr;
Pierre Riteau77358b52011-01-21 12:42:30 +0100751 BlockDriverState *bs, *bs_prev = NULL;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200752 uint8_t *buf;
Pierre Riteau77358b52011-01-21 12:42:30 +0100753 int64_t total_sectors = 0;
754 int nr_sectors;
Juan Quintela42802d42011-10-05 01:14:46 +0200755 int ret;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100756
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200757 do {
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200758 addr = qemu_get_be64(f);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100759
Jan Kiszka6ea44302009-11-30 18:21:19 +0100760 flags = addr & ~BDRV_SECTOR_MASK;
761 addr >>= BDRV_SECTOR_BITS;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100762
763 if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200764 /* get device name */
765 len = qemu_get_byte(f);
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200766 qemu_get_buffer(f, (uint8_t *)device_name, len);
767 device_name[len] = '\0';
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100768
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200769 bs = bdrv_find(device_name);
Jan Kiszka4b640362009-11-30 18:21:21 +0100770 if (!bs) {
771 fprintf(stderr, "Error unknown block device %s\n",
772 device_name);
773 return -EINVAL;
774 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100775
Pierre Riteau77358b52011-01-21 12:42:30 +0100776 if (bs != bs_prev) {
777 bs_prev = bs;
778 total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
779 if (total_sectors <= 0) {
Markus Armbruster6daf1942011-06-22 14:03:54 +0200780 error_report("Error getting length of block device %s",
Pierre Riteau77358b52011-01-21 12:42:30 +0100781 device_name);
782 return -EINVAL;
783 }
784 }
785
786 if (total_sectors - addr < BDRV_SECTORS_PER_DIRTY_CHUNK) {
787 nr_sectors = total_sectors - addr;
788 } else {
789 nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
790 }
791
Peter Lieven323004a2013-07-18 09:48:50 +0200792 if (flags & BLK_MIG_FLAG_ZERO_BLOCK) {
Peter Lievend32f35c2013-10-24 12:06:52 +0200793 ret = bdrv_write_zeroes(bs, addr, nr_sectors,
794 BDRV_REQ_MAY_UNMAP);
Peter Lieven323004a2013-07-18 09:48:50 +0200795 } else {
796 buf = g_malloc(BLOCK_SIZE);
797 qemu_get_buffer(f, buf, BLOCK_SIZE);
798 ret = bdrv_write(bs, addr, buf, nr_sectors);
799 g_free(buf);
800 }
Jan Kiszka575a58d2009-11-30 18:21:20 +0100801
Yoshiaki Tamurab02bea32010-07-20 18:19:00 +0900802 if (ret < 0) {
803 return ret;
804 }
Jan Kiszka01e61e22009-12-01 15:20:17 +0100805 } else if (flags & BLK_MIG_FLAG_PROGRESS) {
806 if (!banner_printed) {
807 printf("Receiving block device images\n");
808 banner_printed = 1;
809 }
810 printf("Completed %d %%%c", (int)addr,
811 (addr == 100) ? '\n' : '\r');
812 fflush(stdout);
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100813 } else if (!(flags & BLK_MIG_FLAG_EOS)) {
Stefan Hajnoczid5f1f282013-02-10 23:12:44 +0100814 fprintf(stderr, "Unknown block migration flags: %#x\n", flags);
Jan Kiszka4b640362009-11-30 18:21:21 +0100815 return -EINVAL;
816 }
Juan Quintela42802d42011-10-05 01:14:46 +0200817 ret = qemu_file_get_error(f);
818 if (ret != 0) {
819 return ret;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200820 }
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100821 } while (!(flags & BLK_MIG_FLAG_EOS));
822
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200823 return 0;
824}
825
Isaku Yamahata6607ae22012-06-19 18:43:09 +0300826static void block_set_params(const MigrationParams *params, void *opaque)
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200827{
Isaku Yamahata6607ae22012-06-19 18:43:09 +0300828 block_mig_state.blk_enable = params->blk;
829 block_mig_state.shared_base = params->shared;
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100830
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200831 /* shared base means that blk_enable = 1 */
Isaku Yamahata6607ae22012-06-19 18:43:09 +0300832 block_mig_state.blk_enable |= params->shared;
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200833}
834
Juan Quintela6bd68782012-06-27 10:59:15 +0200835static bool block_is_active(void *opaque)
836{
837 return block_mig_state.blk_enable == 1;
838}
839
Juan Quintela7908c782012-06-26 18:46:10 +0200840SaveVMHandlers savevm_block_handlers = {
841 .set_params = block_set_params,
Juan Quintelad1315aa2012-06-28 15:11:57 +0200842 .save_live_setup = block_save_setup,
Juan Quintela16310a32012-06-28 15:31:37 +0200843 .save_live_iterate = block_save_iterate,
844 .save_live_complete = block_save_complete,
Juan Quintelae4ed1542012-09-21 11:18:18 +0200845 .save_live_pending = block_save_pending,
Juan Quintela7908c782012-06-26 18:46:10 +0200846 .load_state = block_load,
Juan Quintela9b5bfab2012-06-26 19:26:41 +0200847 .cancel = block_migration_cancel,
Juan Quintela6bd68782012-06-27 10:59:15 +0200848 .is_active = block_is_active,
Juan Quintela7908c782012-06-26 18:46:10 +0200849};
850
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200851void blk_mig_init(void)
Jan Kiszkaa55eb922009-11-30 18:21:19 +0100852{
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100853 QSIMPLEQ_INIT(&block_mig_state.bmds_list);
854 QSIMPLEQ_INIT(&block_mig_state.blk_list);
Paolo Bonzini52e850d2013-02-22 17:36:25 +0100855 qemu_mutex_init(&block_mig_state.lock);
Jan Kiszka5e5328b2009-11-30 18:21:20 +0100856
Juan Quintela7908c782012-06-26 18:46:10 +0200857 register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
858 &block_mig_state);
lirans@il.ibm.comc163b5c2009-11-02 15:40:58 +0200859}