Statistics
| Branch: | Revision:

root / block-migration.c @ d246673d

History | View | Annotate | Download (16.8 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
 */
13

    
14
#include "qemu-common.h"
15
#include "block_int.h"
16
#include "hw/hw.h"
17
#include "qemu-queue.h"
18
#include "qemu-timer.h"
19
#include "monitor.h"
20
#include "block-migration.h"
21
#include "migration.h"
22
#include <assert.h>
23

    
24
#define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
25

    
26
#define BLK_MIG_FLAG_DEVICE_BLOCK       0x01
27
#define BLK_MIG_FLAG_EOS                0x02
28
#define BLK_MIG_FLAG_PROGRESS           0x04
29

    
30
#define MAX_IS_ALLOCATED_SEARCH 65536
31

    
32
//#define DEBUG_BLK_MIGRATION
33

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

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

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

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

    
81
static BlkMigState block_mig_state;
82

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

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

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

    
96
    qemu_put_buffer(f, blk->buf, BLOCK_SIZE);
97
}
98

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

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

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

    
115
uint64_t blk_mig_bytes_remaining(void)
116
{
117
    return blk_mig_bytes_total() - blk_mig_bytes_transferred();
118
}
119

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

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

    
131
static inline void add_avg_read_time(int64_t time)
132
{
133
    block_mig_state.reads++;
134
    block_mig_state.total_time += time;
135
}
136

    
137
static inline long double compute_read_bwidth(void)
138
{
139
    assert(block_mig_state.total_time != 0);
140
    return  (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time;
141
}
142

    
143
static void blk_mig_read_cb(void *opaque, int ret)
144
{
145
    BlkMigBlock *blk = opaque;
146

    
147
    blk->ret = ret;
148

    
149
    blk->time = qemu_get_clock_ns(rt_clock) - blk->time;
150

    
151
    add_avg_read_time(blk->time);
152

    
153
    QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
154

    
155
    block_mig_state.submitted--;
156
    block_mig_state.read_done++;
157
    assert(block_mig_state.submitted >= 0);
158
}
159

    
160
static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
161
                                BlkMigDevState *bmds)
162
{
163
    int64_t total_sectors = bmds->total_sectors;
164
    int64_t cur_sector = bmds->cur_sector;
165
    BlockDriverState *bs = bmds->bs;
166
    BlkMigBlock *blk;
167
    int nr_sectors;
168

    
169
    if (bmds->shared_base) {
170
        while (cur_sector < total_sectors &&
171
               !bdrv_is_allocated(bs, cur_sector, MAX_IS_ALLOCATED_SEARCH,
172
                                  &nr_sectors)) {
173
            cur_sector += nr_sectors;
174
        }
175
    }
176

    
177
    if (cur_sector >= total_sectors) {
178
        bmds->cur_sector = bmds->completed_sectors = total_sectors;
179
        return 1;
180
    }
181

    
182
    bmds->completed_sectors = cur_sector;
183

    
184
    cur_sector &= ~((int64_t)BDRV_SECTORS_PER_DIRTY_CHUNK - 1);
185

    
186
    /* we are going to transfer a full block even if it is not allocated */
187
    nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
188

    
189
    if (total_sectors - cur_sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
190
        nr_sectors = total_sectors - cur_sector;
191
    }
192

    
193
    blk = qemu_malloc(sizeof(BlkMigBlock));
194
    blk->buf = qemu_malloc(BLOCK_SIZE);
195
    blk->bmds = bmds;
196
    blk->sector = cur_sector;
197

    
198
    blk->iov.iov_base = blk->buf;
199
    blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
200
    qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
201

    
202
    blk->time = qemu_get_clock_ns(rt_clock);
203

    
204
    blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
205
                                nr_sectors, blk_mig_read_cb, blk);
206
    if (!blk->aiocb) {
207
        goto error;
208
    }
209
    block_mig_state.submitted++;
210

    
211
    bdrv_reset_dirty(bs, cur_sector, nr_sectors);
212
    bmds->cur_sector = cur_sector + nr_sectors;
213

    
214
    return (bmds->cur_sector >= total_sectors);
215

    
216
error:
217
    monitor_printf(mon, "Error reading sector %" PRId64 "\n", cur_sector);
218
    qemu_file_set_error(f);
219
    qemu_free(blk->buf);
220
    qemu_free(blk);
221
    return 0;
222
}
223

    
224
static void set_dirty_tracking(int enable)
225
{
226
    BlkMigDevState *bmds;
227

    
228
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
229
        bdrv_set_dirty_tracking(bmds->bs, enable);
230
    }
231
}
232

    
233
static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
234
{
235
    Monitor *mon = opaque;
236
    BlkMigDevState *bmds;
237
    int64_t sectors;
238

    
239
    if (!bdrv_is_read_only(bs)) {
240
        sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
241
        if (sectors == 0) {
242
            return;
243
        }
244

    
245
        bmds = qemu_mallocz(sizeof(BlkMigDevState));
246
        bmds->bs = bs;
247
        bmds->bulk_completed = 0;
248
        bmds->total_sectors = sectors;
249
        bmds->completed_sectors = 0;
250
        bmds->shared_base = block_mig_state.shared_base;
251

    
252
        block_mig_state.total_sector_sum += sectors;
253

    
254
        if (bmds->shared_base) {
255
            monitor_printf(mon, "Start migration for %s with shared base "
256
                                "image\n",
257
                           bs->device_name);
258
        } else {
259
            monitor_printf(mon, "Start full migration for %s\n",
260
                           bs->device_name);
261
        }
262

    
263
        QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
264
    }
265
}
266

    
267
static void init_blk_migration(Monitor *mon, QEMUFile *f)
268
{
269
    block_mig_state.submitted = 0;
270
    block_mig_state.read_done = 0;
271
    block_mig_state.transferred = 0;
272
    block_mig_state.total_sector_sum = 0;
273
    block_mig_state.prev_progress = -1;
274
    block_mig_state.bulk_completed = 0;
275
    block_mig_state.total_time = 0;
276
    block_mig_state.reads = 0;
277

    
278
    bdrv_iterate(init_blk_migration_it, mon);
279
}
280

    
281
static int blk_mig_save_bulked_block(Monitor *mon, QEMUFile *f)
282
{
283
    int64_t completed_sector_sum = 0;
284
    BlkMigDevState *bmds;
285
    int progress;
286
    int ret = 0;
287

    
288
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
289
        if (bmds->bulk_completed == 0) {
290
            if (mig_save_device_bulk(mon, f, bmds) == 1) {
291
                /* completed bulk section for this device */
292
                bmds->bulk_completed = 1;
293
            }
294
            completed_sector_sum += bmds->completed_sectors;
295
            ret = 1;
296
            break;
297
        } else {
298
            completed_sector_sum += bmds->completed_sectors;
299
        }
300
    }
301

    
302
    progress = completed_sector_sum * 100 / block_mig_state.total_sector_sum;
303
    if (progress != block_mig_state.prev_progress) {
304
        block_mig_state.prev_progress = progress;
305
        qemu_put_be64(f, (progress << BDRV_SECTOR_BITS)
306
                         | BLK_MIG_FLAG_PROGRESS);
307
        monitor_printf(mon, "Completed %d %%\r", progress);
308
        monitor_flush(mon);
309
    }
310

    
311
    return ret;
312
}
313

    
314
static void blk_mig_reset_dirty_cursor(void)
315
{
316
    BlkMigDevState *bmds;
317

    
318
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
319
        bmds->cur_dirty = 0;
320
    }
321
}
322

    
323
static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
324
                                 BlkMigDevState *bmds, int is_async)
325
{
326
    BlkMigBlock *blk;
327
    int64_t total_sectors = bmds->total_sectors;
328
    int64_t sector;
329
    int nr_sectors;
330

    
331
    for (sector = bmds->cur_dirty; sector < bmds->total_sectors;) {
332
        if (bdrv_get_dirty(bmds->bs, sector)) {
333

    
334
            if (total_sectors - sector < BDRV_SECTORS_PER_DIRTY_CHUNK) {
335
                nr_sectors = total_sectors - sector;
336
            } else {
337
                nr_sectors = BDRV_SECTORS_PER_DIRTY_CHUNK;
338
            }
339
            blk = qemu_malloc(sizeof(BlkMigBlock));
340
            blk->buf = qemu_malloc(BLOCK_SIZE);
341
            blk->bmds = bmds;
342
            blk->sector = sector;
343

    
344
            if (is_async) {
345
                blk->iov.iov_base = blk->buf;
346
                blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
347
                qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
348

    
349
                blk->time = qemu_get_clock_ns(rt_clock);
350

    
351
                blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
352
                                            nr_sectors, blk_mig_read_cb, blk);
353
                if (!blk->aiocb) {
354
                    goto error;
355
                }
356
                block_mig_state.submitted++;
357
            } else {
358
                if (bdrv_read(bmds->bs, sector, blk->buf,
359
                              nr_sectors) < 0) {
360
                    goto error;
361
                }
362
                blk_send(f, blk);
363

    
364
                qemu_free(blk->buf);
365
                qemu_free(blk);
366
            }
367

    
368
            bdrv_reset_dirty(bmds->bs, sector, nr_sectors);
369
            break;
370
        }
371
        sector += BDRV_SECTORS_PER_DIRTY_CHUNK;
372
        bmds->cur_dirty = sector;
373
    }
374

    
375
    return (bmds->cur_dirty >= bmds->total_sectors);
376

    
377
error:
378
    monitor_printf(mon, "Error reading sector %" PRId64 "\n", sector);
379
    qemu_file_set_error(f);
380
    qemu_free(blk->buf);
381
    qemu_free(blk);
382
    return 0;
383
}
384

    
385
static int blk_mig_save_dirty_block(Monitor *mon, QEMUFile *f, int is_async)
386
{
387
    BlkMigDevState *bmds;
388
    int ret = 0;
389

    
390
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
391
        if (mig_save_device_dirty(mon, f, bmds, is_async) == 0) {
392
            ret = 1;
393
            break;
394
        }
395
    }
396

    
397
    return ret;
398
}
399

    
400
static void flush_blks(QEMUFile* f)
401
{
402
    BlkMigBlock *blk;
403

    
404
    DPRINTF("%s Enter submitted %d read_done %d transferred %d\n",
405
            __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
406
            block_mig_state.transferred);
407

    
408
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
409
        if (qemu_file_rate_limit(f)) {
410
            break;
411
        }
412
        if (blk->ret < 0) {
413
            qemu_file_set_error(f);
414
            break;
415
        }
416
        blk_send(f, blk);
417

    
418
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
419
        qemu_free(blk->buf);
420
        qemu_free(blk);
421

    
422
        block_mig_state.read_done--;
423
        block_mig_state.transferred++;
424
        assert(block_mig_state.read_done >= 0);
425
    }
426

    
427
    DPRINTF("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
428
            block_mig_state.submitted, block_mig_state.read_done,
429
            block_mig_state.transferred);
430
}
431

    
432
static int64_t get_remaining_dirty(void)
433
{
434
    BlkMigDevState *bmds;
435
    int64_t dirty = 0;
436

    
437
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
438
        dirty += bdrv_get_dirty_count(bmds->bs);
439
    }
440

    
441
    return dirty * BLOCK_SIZE;
442
}
443

    
444
static int is_stage2_completed(void)
445
{
446
    int64_t remaining_dirty;
447
    long double bwidth;
448

    
449
    if (block_mig_state.bulk_completed == 1) {
450

    
451
        remaining_dirty = get_remaining_dirty();
452
        if (remaining_dirty == 0) {
453
            return 1;
454
        }
455

    
456
        bwidth = compute_read_bwidth();
457

    
458
        if ((remaining_dirty / bwidth) <=
459
            migrate_max_downtime()) {
460
            /* finish stage2 because we think that we can finish remaing work
461
               below max_downtime */
462

    
463
            return 1;
464
        }
465
    }
466

    
467
    return 0;
468
}
469

    
470
static void blk_mig_cleanup(Monitor *mon)
471
{
472
    BlkMigDevState *bmds;
473
    BlkMigBlock *blk;
474

    
475
    while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
476
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
477
        qemu_free(bmds);
478
    }
479

    
480
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
481
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
482
        qemu_free(blk->buf);
483
        qemu_free(blk);
484
    }
485

    
486
    set_dirty_tracking(0);
487

    
488
    monitor_printf(mon, "\n");
489
}
490

    
491
static int block_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
492
{
493
    DPRINTF("Enter save live stage %d submitted %d transferred %d\n",
494
            stage, block_mig_state.submitted, block_mig_state.transferred);
495

    
496
    if (stage < 0) {
497
        blk_mig_cleanup(mon);
498
        return 0;
499
    }
500

    
501
    if (block_mig_state.blk_enable != 1) {
502
        /* no need to migrate storage */
503
        qemu_put_be64(f, BLK_MIG_FLAG_EOS);
504
        return 1;
505
    }
506

    
507
    if (stage == 1) {
508
        init_blk_migration(mon, f);
509

    
510
        /* start track dirty blocks */
511
        set_dirty_tracking(1);
512
    }
513

    
514
    flush_blks(f);
515

    
516
    if (qemu_file_has_error(f)) {
517
        blk_mig_cleanup(mon);
518
        return 0;
519
    }
520

    
521
    blk_mig_reset_dirty_cursor();
522

    
523
    if (stage == 2) {
524
        /* control the rate of transfer */
525
        while ((block_mig_state.submitted +
526
                block_mig_state.read_done) * BLOCK_SIZE <
527
               qemu_file_get_rate_limit(f)) {
528
            if (block_mig_state.bulk_completed == 0) {
529
                /* first finish the bulk phase */
530
                if (blk_mig_save_bulked_block(mon, f) == 0) {
531
                    /* finished saving bulk on all devices */
532
                    block_mig_state.bulk_completed = 1;
533
                }
534
            } else {
535
                if (blk_mig_save_dirty_block(mon, f, 1) == 0) {
536
                    /* no more dirty blocks */
537
                    break;
538
                }
539
            }
540
        }
541

    
542
        flush_blks(f);
543

    
544
        if (qemu_file_has_error(f)) {
545
            blk_mig_cleanup(mon);
546
            return 0;
547
        }
548
    }
549

    
550
    if (stage == 3) {
551
        /* we know for sure that save bulk is completed and
552
           all async read completed */
553
        assert(block_mig_state.submitted == 0);
554

    
555
        while (blk_mig_save_dirty_block(mon, f, 0) != 0);
556
        blk_mig_cleanup(mon);
557

    
558
        /* report completion */
559
        qemu_put_be64(f, (100 << BDRV_SECTOR_BITS) | BLK_MIG_FLAG_PROGRESS);
560

    
561
        if (qemu_file_has_error(f)) {
562
            return 0;
563
        }
564

    
565
        monitor_printf(mon, "Block migration completed\n");
566
    }
567

    
568
    qemu_put_be64(f, BLK_MIG_FLAG_EOS);
569

    
570
    return ((stage == 2) && is_stage2_completed());
571
}
572

    
573
static int block_load(QEMUFile *f, void *opaque, int version_id)
574
{
575
    static int banner_printed;
576
    int len, flags;
577
    char device_name[256];
578
    int64_t addr;
579
    BlockDriverState *bs;
580
    uint8_t *buf;
581

    
582
    do {
583
        addr = qemu_get_be64(f);
584

    
585
        flags = addr & ~BDRV_SECTOR_MASK;
586
        addr >>= BDRV_SECTOR_BITS;
587

    
588
        if (flags & BLK_MIG_FLAG_DEVICE_BLOCK) {
589
            /* get device name */
590
            len = qemu_get_byte(f);
591
            qemu_get_buffer(f, (uint8_t *)device_name, len);
592
            device_name[len] = '\0';
593

    
594
            bs = bdrv_find(device_name);
595
            if (!bs) {
596
                fprintf(stderr, "Error unknown block device %s\n",
597
                        device_name);
598
                return -EINVAL;
599
            }
600

    
601
            buf = qemu_malloc(BLOCK_SIZE);
602

    
603
            qemu_get_buffer(f, buf, BLOCK_SIZE);
604
            bdrv_write(bs, addr, buf, BDRV_SECTORS_PER_DIRTY_CHUNK);
605

    
606
            qemu_free(buf);
607
        } else if (flags & BLK_MIG_FLAG_PROGRESS) {
608
            if (!banner_printed) {
609
                printf("Receiving block device images\n");
610
                banner_printed = 1;
611
            }
612
            printf("Completed %d %%%c", (int)addr,
613
                   (addr == 100) ? '\n' : '\r');
614
            fflush(stdout);
615
        } else if (!(flags & BLK_MIG_FLAG_EOS)) {
616
            fprintf(stderr, "Unknown flags\n");
617
            return -EINVAL;
618
        }
619
        if (qemu_file_has_error(f)) {
620
            return -EIO;
621
        }
622
    } while (!(flags & BLK_MIG_FLAG_EOS));
623

    
624
    return 0;
625
}
626

    
627
static void block_set_params(int blk_enable, int shared_base, void *opaque)
628
{
629
    block_mig_state.blk_enable = blk_enable;
630
    block_mig_state.shared_base = shared_base;
631

    
632
    /* shared base means that blk_enable = 1 */
633
    block_mig_state.blk_enable |= shared_base;
634
}
635

    
636
void blk_mig_init(void)
637
{
638
    QSIMPLEQ_INIT(&block_mig_state.bmds_list);
639
    QSIMPLEQ_INIT(&block_mig_state.blk_list);
640

    
641
    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
642
                         NULL, block_load, &block_mig_state);
643
}