Revision 5e5328be

b/block-migration.c
14 14
#include "qemu-common.h"
15 15
#include "block_int.h"
16 16
#include "hw/hw.h"
17
#include "qemu-queue.h"
17 18
#include "block-migration.h"
18 19
#include <assert.h>
19 20

  
......
41 42
    BlockDriverState *bs;
42 43
    int bulk_completed;
43 44
    int shared_base;
44
    struct BlkMigDevState *next;
45 45
    int64_t cur_sector;
46 46
    int64_t total_sectors;
47 47
    int64_t dirty;
48
    QSIMPLEQ_ENTRY(BlkMigDevState) entry;
48 49
} BlkMigDevState;
49 50

  
50 51
typedef struct BlkMigBlock {
......
55 56
    QEMUIOVector qiov;
56 57
    BlockDriverAIOCB *aiocb;
57 58
    int ret;
58
    struct BlkMigBlock *next;
59
    QSIMPLEQ_ENTRY(BlkMigBlock) entry;
59 60
} BlkMigBlock;
60 61

  
61 62
typedef struct BlkMigState {
62 63
    int blk_enable;
63 64
    int shared_base;
64
    BlkMigDevState *bmds_first;
65
    BlkMigBlock *first_blk;
66
    BlkMigBlock *last_blk;
65
    QSIMPLEQ_HEAD(bmds_list, BlkMigDevState) bmds_list;
66
    QSIMPLEQ_HEAD(blk_list, BlkMigBlock) blk_list;
67 67
    int submitted;
68 68
    int read_done;
69 69
    int transferred;
......
78 78

  
79 79
    blk->ret = ret;
80 80

  
81
    /* insert at the end */
82
    if (block_mig_state.last_blk == NULL) {
83
        block_mig_state.first_blk = blk;
84
        block_mig_state.last_blk = blk;
85
    } else {
86
        block_mig_state.last_blk->next = blk;
87
        block_mig_state.last_blk = blk;
88
    }
81
    QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
89 82

  
90 83
    block_mig_state.submitted--;
91 84
    block_mig_state.read_done++;
......
139 132
    bms->cur_sector = cur_sector + nr_sectors;
140 133
    blk->sector = cur_sector;
141 134
    blk->bmds = bms;
142
    blk->next = NULL;
143 135

  
144 136
    blk->iov.iov_base = blk->buf;
145 137
    blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
......
245 237
static void set_dirty_tracking(int enable)
246 238
{
247 239
    BlkMigDevState *bmds;
248
    for (bmds = block_mig_state.bmds_first; bmds != NULL; bmds = bmds->next) {
240

  
241
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
249 242
        bdrv_set_dirty_tracking(bmds->bs, enable);
250 243
    }
251 244
}
252 245

  
253 246
static void init_blk_migration(QEMUFile *f)
254 247
{
255
    BlkMigDevState **pbmds, *bmds;
248
    BlkMigDevState *bmds;
256 249
    BlockDriverState *bs;
257 250

  
258 251
    for (bs = bdrv_first; bs != NULL; bs = bs->next) {
......
270 263
                printf("Start full migration for %s\n", bs->device_name);
271 264
            }
272 265

  
273
            /* insert at the end */
274
            pbmds = &block_mig_state.bmds_first;
275
            while (*pbmds != NULL) {
276
                pbmds = &(*pbmds)->next;
277
            }
278
            *pbmds = bmds;
266
            QSIMPLEQ_INSERT_TAIL(&block_mig_state.bmds_list, bmds, entry);
279 267
        }
280 268
    }
281 269
}
......
284 272
{
285 273
    BlkMigDevState *bmds;
286 274

  
287
    for (bmds = block_mig_state.bmds_first; bmds != NULL; bmds = bmds->next) {
275
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
288 276
        if (bmds->bulk_completed == 0) {
289 277
            if (is_async) {
290 278
                if (mig_read_device_bulk(f, bmds) == 1) {
......
316 304

  
317 305
    buf = qemu_malloc(BLOCK_SIZE);
318 306

  
319
    for (bmds = block_mig_state.bmds_first; bmds != NULL; bmds = bmds->next) {
307
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
320 308
        for (sector = 0; sector < bmds->cur_sector;) {
321 309
            if (bdrv_get_dirty(bmds->bs, sector)) {
322 310
                if (bdrv_read(bmds->bs, sector, buf,
......
347 335

  
348 336
static void flush_blks(QEMUFile* f)
349 337
{
350
    BlkMigBlock *blk, *next;
338
    BlkMigBlock *blk;
351 339

  
352 340
    dprintf("%s Enter submitted %d read_done %d transferred %d\n",
353 341
            __FUNCTION__, block_mig_state.submitted, block_mig_state.read_done,
354 342
            block_mig_state.transferred);
355 343

  
356
    for (blk = block_mig_state.first_blk;
357
         blk != NULL && !qemu_file_rate_limit(f);
358
         blk = next) {
344
    while ((blk = QSIMPLEQ_FIRST(&block_mig_state.blk_list)) != NULL) {
345
        if (qemu_file_rate_limit(f)) {
346
            break;
347
        }
359 348
        send_blk(f, blk);
360 349

  
361
        next = blk->next;
350
        QSIMPLEQ_REMOVE_HEAD(&block_mig_state.blk_list, entry);
362 351
        qemu_free(blk->buf);
363 352
        qemu_free(blk);
364 353

  
......
366 355
        block_mig_state.transferred++;
367 356
        assert(block_mig_state.read_done >= 0);
368 357
    }
369
    block_mig_state.first_blk = blk;
370

  
371
    if (block_mig_state.first_blk == NULL) {
372
        block_mig_state.last_blk = NULL;
373
    }
374 358

  
375 359
    dprintf("%s Exit submitted %d read_done %d transferred %d\n", __FUNCTION__,
376 360
            block_mig_state.submitted, block_mig_state.read_done,
......
385 369
        return 0;
386 370
    }
387 371

  
388
    for (bmds = block_mig_state.bmds_first; bmds != NULL; bmds = bmds->next) {
372
    QSIMPLEQ_FOREACH(bmds, &block_mig_state.bmds_list, entry) {
389 373
        if (bmds->bulk_completed == 0) {
390 374
            return 0;
391 375
        }
......
498 482

  
499 483
void blk_mig_init(void)
500 484
{
485
    QSIMPLEQ_INIT(&block_mig_state.bmds_list);
486
    QSIMPLEQ_INIT(&block_mig_state.blk_list);
487

  
501 488
    register_savevm_live("block", 0, 1, block_set_params, block_save_live,
502 489
                         NULL, block_load, &block_mig_state);
503 490
}

Also available in: Unified diff