Statistics
| Branch: | Revision:

root / block-migration.c @ bf0842b7

History | View | Annotate | Download (19.5 kB)

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
 * Contributions after 2012-01-13 are licensed under the terms of the
13
 * GNU GPL, version 2 or (at your option) any later version.
14
 */
15

    
16
#include "qemu-common.h"
17
#include "block/block_int.h"
18
#include "hw/hw.h"
19
#include "qemu/queue.h"
20
#include "qemu/timer.h"
21
#include "migration/block.h"
22
#include "migration/migration.h"
23
#include "sysemu/blockdev.h"
24
#include <assert.h>
25

    
26
#define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
27

    
28
#define BLK_MIG_FLAG_DEVICE_BLOCK       0x01
29
#define BLK_MIG_FLAG_EOS                0x02
30
#define BLK_MIG_FLAG_PROGRESS           0x04
31

    
32
#define MAX_IS_ALLOCATED_SEARCH 65536
33

    
34
//#define DEBUG_BLK_MIGRATION
35

    
36
#ifdef DEBUG_BLK_MIGRATION
37
#define DPRINTF(fmt, ...) \
38
    do { printf("blk_migration: " fmt, ## __VA_ARGS__); } while (0)
39
#else
40
#define DPRINTF(fmt, ...) \
41
    do { } while (0)
42
#endif
43

    
44
typedef struct BlkMigDevState {
45
    BlockDriverState *bs;
46
    int bulk_completed;
47
    int shared_base;
48
    int64_t cur_sector;
49
    int64_t cur_dirty;
50
    int64_t completed_sectors;
51
    int64_t total_sectors;
52
    int64_t dirty;
53
    QSIMPLEQ_ENTRY(BlkMigDevState) entry;
54
    unsigned long *aio_bitmap;
55
} BlkMigDevState;
56

    
57
typedef struct BlkMigBlock {
58
    uint8_t *buf;
59
    BlkMigDevState *bmds;
60
    int64_t sector;
61
    int nr_sectors;
62
    struct iovec iov;
63
    QEMUIOVector qiov;
64
    BlockDriverAIOCB *aiocb;
65
    int ret;
66
    QSIMPLEQ_ENTRY(BlkMigBlock) entry;
67
} BlkMigBlock;
68

    
69
typedef struct BlkMigState {
70
    int blk_enable;
71
    int shared_base;
72
    QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
73
    QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
74
    int submitted;
75
    int read_done;
76
    int transferred;
77
    int64_t total_sector_sum;
78
    int prev_progress;
79
    int bulk_completed;
80
    long double prev_time_offset;
81
} BlkMigState;
82

    
83
static BlkMigState block_mig_state;
84

    
85
static void blk_send(QEMUFile *f, BlkMigBlock * blk)
86
{
87
    int len;
88

    
89
    /* sector number and flags */
90
    qemu_put_be64(f, (blk->sector << BDRV_SECTOR_BITS)
91
                     | BLK_MIG_FLAG_DEVICE_BLOCK);
92

    
93
    /* device name */
94
    len = strlen(blk->bmds->bs->device_name);
95
    qemu_put_byte(f, len);
96
    qemu_put_buffer(f, (uint8_t *)blk->bmds->bs->device_name, len);
97

    
98
    qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
99
}
100

    
101
int blk_mig_active(void)
102
{
103
    return !QSIMPLEQ_EMPTY(&block_mig_state.bmds_list);
104
}
105

    
106
uint64_t blk_mig_bytes_transferred(void)
107
{
108
    BlkMigDevState *bmds;
109
    uint64_t sum = 0;
110

    
111
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
112
        sum += bmds->completed_sectors;
113
    }
114
    return sum << BDRV_SECTOR_BITS;
115
}
116

    
117
uint64_t blk_mig_bytes_remaining(void)
118
{
119
    return blk_mig_bytes_total() - blk_mig_bytes_transferred();
120
}
121

    
122
uint64_t blk_mig_bytes_total(void)
123
{
124
    BlkMigDevState *bmds;
125
    uint64_t sum = 0;
126

    
127
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
128
        sum += bmds->total_sectors;
129
    }
130
    return sum << BDRV_SECTOR_BITS;
131
}
132

    
133
static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
134
{
135
    int64_t chunk = sector / (int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK;
136

    
137
    if ((sector << BDRV_SECTOR_BITS) < bdrv_getlength(bmds->bs)) {
138
        return !!(bmds->aio_bitmap[chunk / (sizeof(unsigned long) * 8)] &
139
            (1UL << (chunk % (sizeof(unsigned long) * 8))));
140
    } else {
141
        return 0;
142
    }
143
}
144

    
145
static void bmds_set_aio_inflight(BlkMigDevState *bmds, int64_t sector_num,
146
                             int nb_sectors, int set)
147
{
148
    int64_t start, end;
149
    unsigned long val, idx, bit;
150

    
151
    start = sector_num / BDRV_SECTORS_PER_DIRTY_CHUNK;
152
    end = (sector_num + nb_sectors - 1) / BDRV_SECTORS_PER_DIRTY_CHUNK;
153

    
154
    for (; start <= end; start++) {
155
        idx = start / (sizeof(unsigned long) * 8);
156
        bit = start % (sizeof(unsigned long) * 8);
157
        val = bmds->aio_bitmap[idx];
158
        if (set) {
159
            val |= 1UL << bit;
160
        } else {
161
            val &= ~(1UL << bit);
162
        }
163
        bmds->aio_bitmap[idx] = val;
164
    }
165
}
166

    
167
static void alloc_aio_bitmap(BlkMigDevState *bmds)
168
{
169
    BlockDriverState *bs = bmds->bs;
170
    int64_t bitmap_size;
171

    
172
    bitmap_size = (bdrv_getlength(bs) >> BDRV_SECTOR_BITS) +
173
            BDRV_SECTORS_PER_DIRTY_CHUNK * 8 - 1;
174
    bitmap_size /= BDRV_SECTORS_PER_DIRTY_CHUNK * 8;
175

    
176
    bmds->aio_bitmap = g_malloc0(bitmap_size);
177
}
178

    
179
static void blk_mig_read_cb(void *opaque, int ret)
180
{
181
    long double curr_time = qemu_get_clock_ns(rt_clock);
182
    BlkMigBlock *blk = opaque;
183

    
184
    blk->ret = ret;
185

    
186
    block_mig_state.prev_time_offset = curr_time;
187

    
188
    QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
189
    bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
190

    
191
    block_mig_state.submitted--;
192
    block_mig_state.read_done++;
193
    assert(block_mig_state.submitted >= 0);
194
}
195

    
196
static int mig_save_device_bulk(QEMUFile *f, BlkMigDevState *bmds)
197
{
198
    int64_t total_sectors = bmds->total_sectors;
199
    int64_t cur_sector = bmds->cur_sector;
200
    BlockDriverState *bs = bmds->bs;
201
    BlkMigBlock *blk;
202
    int nr_sectors;
203

    
204
    if (bmds->shared_base) {
205
        while (cur_sector < total_sectors &&
206
               !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
207
                                  &nr_sectors)) {
208
            cur_sector += nr_sectors;
209
        }
210
    }
211

    
212
    if (cur_sector >= total_sectors) {
213
        bmds->cur_sector = bmds->completed_sectors = total_sectors;
214
        return 1;
215
    }
216

    
217
    bmds->completed_sectors = cur_sector;
218

    
219
    cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
220

    
221
    /* we are going to transfer a full block even if it is not allocated */
222
    nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
223

    
224
    if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
225
        nr_sectors = total_sectors - cur_sector;
226
    }
227

    
228
    blk = g_malloc(sizeof(BlkMigBlock));
229
    blk->buf = g_malloc(BLOCK_SIZE);
230
    blk->bmds = bmds;
231
    blk->sector = cur_sector;
232
    blk->nr_sectors = nr_sectors;
233

    
234
    blk->iov.iov_base = blk->buf;
235
    blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
236
    qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
237

    
238
    if (block_mig_state.submitted == 0) {
239
        block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
240
    }
241

    
242
    blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
243
                                nr_sectors, blk_mig_read_cb, blk);
244
    block_mig_state.submitted++;
245

    
246
    bdrv_reset_dirty(bs, cur_sector, nr_sectors);
247
    bmds->cur_sector = cur_sector + nr_sectors;
248

    
249
    return (bmds->cur_sector >= total_sectors);
250
}
251

    
252
static void set_dirty_tracking(int enable)
253
{
254
    BlkMigDevState *bmds;
255

    
256
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
257
        bdrv_set_dirty_tracking(bmds->bs, enable);
258
    }
259
}
260

    
261
static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
262
{
263
    BlkMigDevState *bmds;
264
    int64_t sectors;
265

    
266
    if (!bdrv_is_read_only(bs)) {
267
        sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
268
        if (sectors <= 0) {
269
            return;
270
        }
271

    
272
        bmds = g_malloc0(sizeof(BlkMigDevState));
273
        bmds->bs = bs;
274
        bmds->bulk_completed = 0;
275
        bmds->total_sectors = sectors;
276
        bmds->completed_sectors = 0;
277
        bmds->shared_base = block_mig_state.shared_base;
278
        alloc_aio_bitmap(bmds);
279
        drive_get_ref(drive_get_by_blockdev(bs));
280
        bdrv_set_in_use(bs, 1);
281

    
282
        block_mig_state.total_sector_sum += sectors;
283

    
284
        if (bmds->shared_base) {
285
            DPRINTF("Start migration for %s with shared base image\n",
286
                    bs->device_name);
287
        } else {
288
            DPRINTF("Start full migration for %s\n", bs->device_name);
289
        }
290

    
291
        QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
292
    }
293
}
294

    
295
static void init_blk_migration(QEMUFile *f)
296
{
297
    block_mig_state.submitted = 0;
298
    block_mig_state.read_done = 0;
299
    block_mig_state.transferred = 0;
300
    block_mig_state.total_sector_sum = 0;
301
    block_mig_state.prev_progress = -1;
302
    block_mig_state.bulk_completed = 0;
303

    
304
    bdrv_iterate(init_blk_migration_it, NULL);
305
}
306

    
307
static int blk_mig_save_bulked_block(QEMUFile *f)
308
{
309
    int64_t completed_sector_sum = 0;
310
    BlkMigDevState *bmds;
311
    int progress;
312
    int ret = 0;
313

    
314
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
315
        if (bmds->bulk_completed == 0) {
316
            if (mig_save_device_bulk(f, bmds) == 1) {
317
                /* completed bulk section for this device */
318
                bmds->bulk_completed = 1;
319
            }
320
            completed_sector_sum += bmds->completed_sectors;
321
            ret = 1;
322
            break;
323
        } else {
324
            completed_sector_sum += bmds->completed_sectors;
325
        }
326
    }
327

    
328
    if (block_mig_state.total_sector_sum != 0) {
329
        progress = completed_sector_sum * 100 /
330
                   block_mig_state.total_sector_sum;
331
    } else {
332
        progress = 100;
333
    }
334
    if (progress != block_mig_state.prev_progress) {
335
        block_mig_state.prev_progress = progress;
336
        qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
337
                         | BLK_MIG_FLAG_PROGRESS);
338
        DPRINTF("Completed %d %%\r", progress);
339
    }
340

    
341
    return ret;
342
}
343

    
344
static void blk_mig_reset_dirty_cursor(void)
345
{
346
    BlkMigDevState *bmds;
347

    
348
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
349
        bmds->cur_dirty = 0;
350
    }
351
}
352

    
353
static int mig_save_device_dirty(QEMUFile *f, BlkMigDevState *bmds,
354
                                 int is_async)
355
{
356
    BlkMigBlock *blk;
357
    int64_t total_sectors = bmds->total_sectors;
358
    int64_t sector;
359
    int nr_sectors;
360
    int ret = -EIO;
361

    
362
    for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
363
        if (bmds_aio_inflight(bmds, sector)) {
364
            bdrv_drain_all();
365
        }
366
        if (bdrv_get_dirty(bmds->bs, sector)) {
367

    
368
            if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
369
                nr_sectors = total_sectors - sector;
370
            } else {
371
                nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
372
            }
373
            blk = g_malloc(sizeof(BlkMigBlock));
374
            blk->buf = g_malloc(BLOCK_SIZE);
375
            blk->bmds = bmds;
376
            blk->sector = sector;
377
            blk->nr_sectors = nr_sectors;
378

    
379
            if (is_async) {
380
                blk->iov.iov_base = blk->buf;
381
                blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
382
                qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
383

    
384
                if (block_mig_state.submitted == 0) {
385
                    block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
386
                }
387

    
388
                blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
389
                                            nr_sectors, blk_mig_read_cb, blk);
390
                block_mig_state.submitted++;
391
                bmds_set_aio_inflight(bmds, sector, nr_sectors, 1);
392
            } else {
393
                ret = bdrv_read(bmds->bs, sector, blk->buf, nr_sectors);
394
                if (ret < 0) {
395
                    goto error;
396
                }
397
                blk_send(f, blk);
398

    
399
                g_free(blk->buf);
400
                g_free(blk);
401
            }
402

    
403
            bdrv_reset_dirty(bmds->bs, sector, nr_sectors);
404
            break;
405
        }
406
        sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
407
        bmds->cur_dirty = sector;
408
    }
409

    
410
    return (bmds->cur_dirty >= bmds->total_sectors);
411

    
412
error:
413
    DPRINTF("Error reading sector %" PRId64 "\n", sector);
414
    g_free(blk->buf);
415
    g_free(blk);
416
    return ret;
417
}
418

    
419
/* return value:
420
 * 0: too much data for max_downtime
421
 * 1: few enough data for max_downtime
422
*/
423
static int blk_mig_save_dirty_block(QEMUFile *f, int is_async)
424
{
425
    BlkMigDevState *bmds;
426
    int ret = 1;
427

    
428
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
429
        ret = mig_save_device_dirty(f, bmds, is_async);
430
        if (ret <= 0) {
431
            break;
432
        }
433
    }
434

    
435
    return ret;
436
}
437

    
438
static int flush_blks(QEMUFile *f)
439
{
440
    BlkMigBlock *blk;
441
    int ret = 0;
442

    
443
    DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
444
            __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
445
            block_mig_state.transferred);
446

    
447
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
448
        if (qemu_file_rate_limit(f)) {
449
            break;
450
        }
451
        if (blk->ret < 0) {
452
            ret = blk->ret;
453
            break;
454
        }
455
        blk_send(f, blk);
456

    
457
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
458
        g_free(blk->buf);
459
        g_free(blk);
460

    
461
        block_mig_state.read_done--;
462
        block_mig_state.transferred++;
463
        assert(block_mig_state.read_done >= 0);
464
    }
465

    
466
    DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
467
            block_mig_state.submitted, block_mig_state.read_done,
468
            block_mig_state.transferred);
469
    return ret;
470
}
471

    
472
static int64_t get_remaining_dirty(void)
473
{
474
    BlkMigDevState *bmds;
475
    int64_t dirty = 0;
476

    
477
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
478
        dirty += bdrv_get_dirty_count(bmds->bs);
479
    }
480

    
481
    return dirty * BLOCK_SIZE;
482
}
483

    
484
static void blk_mig_cleanup(void)
485
{
486
    BlkMigDevState *bmds;
487
    BlkMigBlock *blk;
488

    
489
    bdrv_drain_all();
490

    
491
    set_dirty_tracking(0);
492

    
493
    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
494
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
495
        bdrv_set_in_use(bmds->bs, 0);
496
        drive_put_ref(drive_get_by_blockdev(bmds->bs));
497
        g_free(bmds->aio_bitmap);
498
        g_free(bmds);
499
    }
500

    
501
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
502
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
503
        g_free(blk->buf);
504
        g_free(blk);
505
    }
506
}
507

    
508
static void block_migration_cancel(void *opaque)
509
{
510
    blk_mig_cleanup();
511
}
512

    
513
static int block_save_setup(QEMUFile *f, void *opaque)
514
{
515
    int ret;
516

    
517
    DPRINTF("Enter save live setup submitted %d transferred %d\n",
518
            block_mig_state.submitted, block_mig_state.transferred);
519

    
520
    init_blk_migration(f);
521

    
522
    /* start track dirty blocks */
523
    set_dirty_tracking(1);
524

    
525
    ret = flush_blks(f);
526
    if (ret) {
527
        blk_mig_cleanup();
528
        return ret;
529
    }
530

    
531
    blk_mig_reset_dirty_cursor();
532

    
533
    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
534

    
535
    return 0;
536
}
537

    
538
static int block_save_iterate(QEMUFile *f, void *opaque)
539
{
540
    int ret;
541

    
542
    DPRINTF("Enter save live iterate submitted %d transferred %d\n",
543
            block_mig_state.submitted, block_mig_state.transferred);
544

    
545
    ret = flush_blks(f);
546
    if (ret) {
547
        blk_mig_cleanup();
548
        return ret;
549
    }
550

    
551
    blk_mig_reset_dirty_cursor();
552

    
553
    /* control the rate of transfer */
554
    while ((block_mig_state.submitted +
555
            block_mig_state.read_done) * BLOCK_SIZE <
556
           qemu_file_get_rate_limit(f)) {
557
        if (block_mig_state.bulk_completed == 0) {
558
            /* first finish the bulk phase */
559
            if (blk_mig_save_bulked_block(f) == 0) {
560
                /* finished saving bulk on all devices */
561
                block_mig_state.bulk_completed = 1;
562
            }
563
        } else {
564
            ret = blk_mig_save_dirty_block(f, 1);
565
            if (ret != 0) {
566
                /* no more dirty blocks */
567
                break;
568
            }
569
        }
570
    }
571
    if (ret) {
572
        blk_mig_cleanup();
573
        return ret;
574
    }
575

    
576
    ret = flush_blks(f);
577
    if (ret) {
578
        blk_mig_cleanup();
579
        return ret;
580
    }
581

    
582
    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
583

    
584
    return 0;
585
}
586

    
587
static int block_save_complete(QEMUFile *f, void *opaque)
588
{
589
    int ret;
590

    
591
    DPRINTF("Enter save live complete submitted %d transferred %d\n",
592
            block_mig_state.submitted, block_mig_state.transferred);
593

    
594
    ret = flush_blks(f);
595
    if (ret) {
596
        blk_mig_cleanup();
597
        return ret;
598
    }
599

    
600
    blk_mig_reset_dirty_cursor();
601

    
602
    /* we know for sure that save bulk is completed and
603
       all async read completed */
604
    assert(block_mig_state.submitted == 0);
605

    
606
    do {
607
        ret = blk_mig_save_dirty_block(f, 0);
608
    } while (ret == 0);
609

    
610
    blk_mig_cleanup();
611
    if (ret) {
612
        return ret;
613
    }
614
    /* report completion */
615
    qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
616

    
617
    DPRINTF("Block migration completed\n");
618

    
619
    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
620

    
621
    return 0;
622
}
623

    
624
static uint64_t block_save_pending(QEMUFile *f, void *opaque, uint64_t max_size)
625
{
626

    
627
    DPRINTF("Enter save live pending  %ld\n", get_remaining_dirty());
628

    
629
    return get_remaining_dirty();
630
}
631

    
632
static int block_load(QEMUFile *f, void *opaque, int version_id)
633
{
634
    static int banner_printed;
635
    int len, flags;
636
    char device_name[256];
637
    int64_t addr;
638
    BlockDriverState *bs, *bs_prev = NULL;
639
    uint8_t *buf;
640
    int64_t total_sectors = 0;
641
    int nr_sectors;
642
    int ret;
643

    
644
    do {
645
        addr = qemu_get_be64(f);
646

    
647
        flags = addr & ~BDRV_SECTOR_MASK;
648
        addr >>= BDRV_SECTOR_BITS;
649

    
650
        if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
651
            /* get device name */
652
            len = qemu_get_byte(f);
653
            qemu_get_buffer(f, (uint8_t *)device_name, len);
654
            device_name[len] = '\0';
655

    
656
            bs = bdrv_find(device_name);
657
            if (!bs) {
658
                fprintf(stderr, "Error unknown block device %s\n",
659
                        device_name);
660
                return -EINVAL;
661
            }
662

    
663
            if (bs != bs_prev) {
664
                bs_prev = bs;
665
                total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
666
                if (total_sectors <= 0) {
667
                    error_report("Error getting length of block device %s",
668
                                 device_name);
669
                    return -EINVAL;
670
                }
671
            }
672

    
673
            if (total_sectors - addr < BDRV_SECTORS_PER_DIRTY_CHUNK) {
674
                nr_sectors = total_sectors - addr;
675
            } else {
676
                nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
677
            }
678

    
679
            buf = g_malloc(BLOCK_SIZE);
680

    
681
            qemu_get_buffer(f, buf, BLOCK_SIZE);
682
            ret = bdrv_write(bs, addr, buf, nr_sectors);
683

    
684
            g_free(buf);
685
            if (ret < 0) {
686
                return ret;
687
            }
688
        } else if (flags & BLK_MIG_FLAG_PROGRESS) {
689
            if (!banner_printed) {
690
                printf("Receiving block device images\n");
691
                banner_printed = 1;
692
            }
693
            printf("Completed %d %%%c", (int)addr,
694
                   (addr == 100) ? '\n' : '\r');
695
            fflush(stdout);
696
        } else if (!(flags & BLK_MIG_FLAG_EOS)) {
697
            fprintf(stderr, "Unknown flags\n");
698
            return -EINVAL;
699
        }
700
        ret = qemu_file_get_error(f);
701
        if (ret != 0) {
702
            return ret;
703
        }
704
    } while (!(flags & BLK_MIG_FLAG_EOS));
705

    
706
    return 0;
707
}
708

    
709
static void block_set_params(const MigrationParams *params, void *opaque)
710
{
711
    block_mig_state.blk_enable = params->blk;
712
    block_mig_state.shared_base = params->shared;
713

    
714
    /* shared base means that blk_enable = 1 */
715
    block_mig_state.blk_enable |= params->shared;
716
}
717

    
718
static bool block_is_active(void *opaque)
719
{
720
    return block_mig_state.blk_enable == 1;
721
}
722

    
723
SaveVMHandlers savevm_block_handlers = {
724
    .set_params = block_set_params,
725
    .save_live_setup = block_save_setup,
726
    .save_live_iterate = block_save_iterate,
727
    .save_live_complete = block_save_complete,
728
    .save_live_pending = block_save_pending,
729
    .load_state = block_load,
730
    .cancel = block_migration_cancel,
731
    .is_active = block_is_active,
732
};
733

    
734
void blk_mig_init(void)
735
{
736
    QSIMPLEQ_INIT(&block_mig_state.bmds_list);
737
    QSIMPLEQ_INIT(&block_mig_state.blk_list);
738

    
739
    register_savevm_live(NULL, "block", 0, 1, &savevm_block_handlers,
740
                         &block_mig_state);
741
}