Skip to content

Commit c8df4a7

Browse files
author
Juan Quintela
committed
migration: Split save_live_pending() into state_pending_*
We split the function into to: - state_pending_estimate: We estimate the remaining state size without stopping the machine. - state pending_exact: We calculate the exact amount of remaining state. The only "device" that implements different functions for _estimate() and _exact() is ram. Signed-off-by: Juan Quintela <[email protected]> Reviewed-by: Dr. David Alan Gilbert <[email protected]>
1 parent 255dc7a commit c8df4a7

13 files changed

+144
-77
lines changed

docs/devel/migration.rst

+11-9
Original file line numberDiff line numberDiff line change
@@ -482,15 +482,17 @@ An iterative device must provide:
482482
- A ``load_setup`` function that initialises the data structures on the
483483
destination.
484484
485-
- A ``save_live_pending`` function that is called repeatedly and must
486-
indicate how much more data the iterative data must save. The core
487-
migration code will use this to determine when to pause the CPUs
488-
and complete the migration.
489-
490-
- A ``save_live_iterate`` function (called after ``save_live_pending``
491-
when there is significant data still to be sent). It should send
492-
a chunk of data until the point that stream bandwidth limits tell it
493-
to stop. Each call generates one section.
485+
- A ``state_pending_exact`` function that indicates how much more
486+
data we must save. The core migration code will use this to
487+
determine when to pause the CPUs and complete the migration.
488+
489+
- A ``state_pending_estimate`` function that indicates how much more
490+
data we must save. When the estimated amount is smaller than the
491+
threshold, we call ``state_pending_exact``.
492+
493+
- A ``save_live_iterate`` function should send a chunk of data until
494+
the point that stream bandwidth limits tell it to stop. Each call
495+
generates one section.
494496
495497
- A ``save_live_complete_precopy`` function that must transmit the
496498
last section for the device containing any remaining data.

docs/devel/vfio-migration.rst

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ VFIO implements the device hooks for the iterative approach as follows:
2828
* A ``load_setup`` function that sets up the migration region on the
2929
destination and sets _RESUMING flag in the VFIO device state.
3030

31-
* A ``save_live_pending`` function that reads pending_bytes from the vendor
31+
* A ``state_pending_exact`` function that reads pending_bytes from the vendor
3232
driver, which indicates the amount of data that the vendor driver has yet to
3333
save for the VFIO device.
3434

@@ -114,7 +114,7 @@ Live migration save path
114114
(RUNNING, _SETUP, _RUNNING|_SAVING)
115115
|
116116
(RUNNING, _ACTIVE, _RUNNING|_SAVING)
117-
If device is active, get pending_bytes by .save_live_pending()
117+
If device is active, get pending_bytes by .state_pending_exact()
118118
If total pending_bytes >= threshold_size, call .save_live_iterate()
119119
Data of VFIO device for pre-copy phase is copied
120120
Iterate till total pending bytes converge and are less than threshold

hw/s390x/s390-stattrib.c

+6-5
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,10 @@ static int cmma_save_setup(QEMUFile *f, void *opaque)
182182
return 0;
183183
}
184184

185-
static void cmma_save_pending(void *opaque, uint64_t max_size,
186-
uint64_t *res_precopy_only,
187-
uint64_t *res_compatible,
188-
uint64_t *res_postcopy_only)
185+
static void cmma_state_pending(void *opaque, uint64_t max_size,
186+
uint64_t *res_precopy_only,
187+
uint64_t *res_compatible,
188+
uint64_t *res_postcopy_only)
189189
{
190190
S390StAttribState *sas = S390_STATTRIB(opaque);
191191
S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas);
@@ -371,7 +371,8 @@ static SaveVMHandlers savevm_s390_stattrib_handlers = {
371371
.save_setup = cmma_save_setup,
372372
.save_live_iterate = cmma_save_iterate,
373373
.save_live_complete_precopy = cmma_save_complete,
374-
.save_live_pending = cmma_save_pending,
374+
.state_pending_exact = cmma_state_pending,
375+
.state_pending_estimate = cmma_state_pending,
375376
.save_cleanup = cmma_save_cleanup,
376377
.load_state = cmma_load,
377378
.is_active = cmma_active,

hw/vfio/migration.c

+11-10
Original file line numberDiff line numberDiff line change
@@ -456,11 +456,11 @@ static void vfio_save_cleanup(void *opaque)
456456
trace_vfio_save_cleanup(vbasedev->name);
457457
}
458458

459-
static void vfio_save_pending(void *opaque,
460-
uint64_t threshold_size,
461-
uint64_t *res_precopy_only,
462-
uint64_t *res_compatible,
463-
uint64_t *res_postcopy_only)
459+
static void vfio_state_pending(void *opaque,
460+
uint64_t threshold_size,
461+
uint64_t *res_precopy_only,
462+
uint64_t *res_compatible,
463+
uint64_t *res_postcopy_only)
464464
{
465465
VFIODevice *vbasedev = opaque;
466466
VFIOMigration *migration = vbasedev->migration;
@@ -473,7 +473,7 @@ static void vfio_save_pending(void *opaque,
473473

474474
*res_precopy_only += migration->pending_bytes;
475475

476-
trace_vfio_save_pending(vbasedev->name, *res_precopy_only,
476+
trace_vfio_state_pending(vbasedev->name, *res_precopy_only,
477477
*res_postcopy_only, *res_compatible);
478478
}
479479

@@ -515,9 +515,9 @@ static int vfio_save_iterate(QEMUFile *f, void *opaque)
515515
}
516516

517517
/*
518-
* Reset pending_bytes as .save_live_pending is not called during savevm or
519-
* snapshot case, in such case vfio_update_pending() at the start of this
520-
* function updates pending_bytes.
518+
* Reset pending_bytes as state_pending* are not called during
519+
* savevm or snapshot case, in such case vfio_update_pending() at
520+
* the start of this function updates pending_bytes.
521521
*/
522522
migration->pending_bytes = 0;
523523
trace_vfio_save_iterate(vbasedev->name, data_size);
@@ -685,7 +685,8 @@ static int vfio_load_state(QEMUFile *f, void *opaque, int version_id)
685685
static SaveVMHandlers savevm_vfio_handlers = {
686686
.save_setup = vfio_save_setup,
687687
.save_cleanup = vfio_save_cleanup,
688-
.save_live_pending = vfio_save_pending,
688+
.state_pending_exact = vfio_state_pending,
689+
.state_pending_estimate = vfio_state_pending,
689690
.save_live_iterate = vfio_save_iterate,
690691
.save_live_complete_precopy = vfio_save_complete_precopy,
691692
.save_state = vfio_save_state,

hw/vfio/trace-events

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ vfio_save_cleanup(const char *name) " (%s)"
157157
vfio_save_buffer(const char *name, uint64_t data_offset, uint64_t data_size, uint64_t pending) " (%s) Offset 0x%"PRIx64" size 0x%"PRIx64" pending 0x%"PRIx64
158158
vfio_update_pending(const char *name, uint64_t pending) " (%s) pending 0x%"PRIx64
159159
vfio_save_device_config_state(const char *name) " (%s)"
160-
vfio_save_pending(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t compatible) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" compatible 0x%"PRIx64
160+
vfio_state_pending(const char *name, uint64_t precopy, uint64_t postcopy, uint64_t compatible) " (%s) precopy 0x%"PRIx64" postcopy 0x%"PRIx64" compatible 0x%"PRIx64
161161
vfio_save_iterate(const char *name, int data_size) " (%s) data_size %d"
162162
vfio_save_complete_precopy(const char *name) " (%s)"
163163
vfio_load_device_config_state(const char *name) " (%s)"

include/migration/register.h

+12-7
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,6 @@ typedef struct SaveVMHandlers {
4646

4747
/* This runs outside the iothread lock! */
4848
int (*save_setup)(QEMUFile *f, void *opaque);
49-
void (*save_live_pending)(void *opaque,
50-
uint64_t threshold_size,
51-
uint64_t *res_precopy_only,
52-
uint64_t *res_compatible,
53-
uint64_t *res_postcopy_only);
5449
/* Note for save_live_pending:
5550
* - res_precopy_only is for data which must be migrated in precopy phase
5651
* or in stopped state, in other words - before target vm start
@@ -61,8 +56,18 @@ typedef struct SaveVMHandlers {
6156
* Sum of res_postcopy_only, res_compatible and res_postcopy_only is the
6257
* whole amount of pending data.
6358
*/
64-
65-
59+
/* This estimates the remaining data to transfer */
60+
void (*state_pending_estimate)(void *opaque,
61+
uint64_t threshold_size,
62+
uint64_t *res_precopy_only,
63+
uint64_t *res_compatible,
64+
uint64_t *res_postcopy_only);
65+
/* This calculate the exact remaining data to transfer */
66+
void (*state_pending_exact)(void *opaque,
67+
uint64_t threshold_size,
68+
uint64_t *res_precopy_only,
69+
uint64_t *res_compatible,
70+
uint64_t *res_postcopy_only);
6671
LoadStateHandler *load_state;
6772
int (*load_setup)(QEMUFile *f, void *opaque);
6873
int (*load_cleanup)(void *opaque);

migration/block-dirty-bitmap.c

+8-7
Original file line numberDiff line numberDiff line change
@@ -762,11 +762,11 @@ static int dirty_bitmap_save_complete(QEMUFile *f, void *opaque)
762762
return 0;
763763
}
764764

765-
static void dirty_bitmap_save_pending(void *opaque,
766-
uint64_t max_size,
767-
uint64_t *res_precopy_only,
768-
uint64_t *res_compatible,
769-
uint64_t *res_postcopy_only)
765+
static void dirty_bitmap_state_pending(void *opaque,
766+
uint64_t max_size,
767+
uint64_t *res_precopy_only,
768+
uint64_t *res_compatible,
769+
uint64_t *res_postcopy_only)
770770
{
771771
DBMSaveState *s = &((DBMState *)opaque)->save;
772772
SaveBitmapState *dbms;
@@ -784,7 +784,7 @@ static void dirty_bitmap_save_pending(void *opaque,
784784

785785
qemu_mutex_unlock_iothread();
786786

787-
trace_dirty_bitmap_save_pending(pending, max_size);
787+
trace_dirty_bitmap_state_pending(pending);
788788

789789
*res_postcopy_only += pending;
790790
}
@@ -1253,7 +1253,8 @@ static SaveVMHandlers savevm_dirty_bitmap_handlers = {
12531253
.save_live_complete_postcopy = dirty_bitmap_save_complete,
12541254
.save_live_complete_precopy = dirty_bitmap_save_complete,
12551255
.has_postcopy = dirty_bitmap_has_postcopy,
1256-
.save_live_pending = dirty_bitmap_save_pending,
1256+
.state_pending_exact = dirty_bitmap_state_pending,
1257+
.state_pending_estimate = dirty_bitmap_state_pending,
12571258
.save_live_iterate = dirty_bitmap_save_iterate,
12581259
.is_active_iterate = dirty_bitmap_is_active_iterate,
12591260
.load_state = dirty_bitmap_load,

migration/block.c

+7-6
Original file line numberDiff line numberDiff line change
@@ -863,10 +863,10 @@ static int block_save_complete(QEMUFile *f, void *opaque)
863863
return 0;
864864
}
865865

866-
static void block_save_pending(void *opaque, uint64_t max_size,
867-
uint64_t *res_precopy_only,
868-
uint64_t *res_compatible,
869-
uint64_t *res_postcopy_only)
866+
static void block_state_pending(void *opaque, uint64_t max_size,
867+
uint64_t *res_precopy_only,
868+
uint64_t *res_compatible,
869+
uint64_t *res_postcopy_only)
870870
{
871871
/* Estimate pending number of bytes to send */
872872
uint64_t pending;
@@ -885,7 +885,7 @@ static void block_save_pending(void *opaque, uint64_t max_size,
885885
pending = BLK_MIG_BLOCK_SIZE;
886886
}
887887

888-
trace_migration_block_save_pending(pending);
888+
trace_migration_block_state_pending(pending);
889889
/* We don't do postcopy */
890890
*res_precopy_only += pending;
891891
}
@@ -1020,7 +1020,8 @@ static SaveVMHandlers savevm_block_handlers = {
10201020
.save_setup = block_save_setup,
10211021
.save_live_iterate = block_save_iterate,
10221022
.save_live_complete_precopy = block_save_complete,
1023-
.save_live_pending = block_save_pending,
1023+
.state_pending_exact = block_state_pending,
1024+
.state_pending_estimate = block_state_pending,
10241025
.load_state = block_load,
10251026
.save_cleanup = block_migration_cleanup,
10261027
.is_active = block_is_active,

migration/migration.c

+14-6
Original file line numberDiff line numberDiff line change
@@ -3778,15 +3778,23 @@ typedef enum {
37783778
*/
37793779
static MigIterateState migration_iteration_run(MigrationState *s)
37803780
{
3781-
uint64_t pending_size, pend_pre, pend_compat, pend_post;
3781+
uint64_t pend_pre, pend_compat, pend_post;
37823782
bool in_postcopy = s->state == MIGRATION_STATUS_POSTCOPY_ACTIVE;
37833783

3784-
qemu_savevm_state_pending(s->threshold_size, &pend_pre,
3785-
&pend_compat, &pend_post);
3786-
pending_size = pend_pre + pend_compat + pend_post;
3784+
qemu_savevm_state_pending_estimate(s->threshold_size, &pend_pre,
3785+
&pend_compat, &pend_post);
3786+
uint64_t pending_size = pend_pre + pend_compat + pend_post;
37873787

3788-
trace_migrate_pending(pending_size, s->threshold_size,
3789-
pend_pre, pend_compat, pend_post);
3788+
trace_migrate_pending_estimate(pending_size, s->threshold_size,
3789+
pend_pre, pend_compat, pend_post);
3790+
3791+
if (pend_pre + pend_compat <= s->threshold_size) {
3792+
qemu_savevm_state_pending_exact(s->threshold_size, &pend_pre,
3793+
&pend_compat, &pend_post);
3794+
pending_size = pend_pre + pend_compat + pend_post;
3795+
trace_migrate_pending_exact(pending_size, s->threshold_size,
3796+
pend_pre, pend_compat, pend_post);
3797+
}
37903798

37913799
if (pending_size && pending_size >= s->threshold_size) {
37923800
/* Still a significant amount to transfer */

migration/ram.c

+26-9
Original file line numberDiff line numberDiff line change
@@ -3409,19 +3409,35 @@ static int ram_save_complete(QEMUFile *f, void *opaque)
34093409
return 0;
34103410
}
34113411

3412-
static void ram_save_pending(void *opaque, uint64_t max_size,
3413-
uint64_t *res_precopy_only,
3414-
uint64_t *res_compatible,
3415-
uint64_t *res_postcopy_only)
3412+
static void ram_state_pending_estimate(void *opaque, uint64_t max_size,
3413+
uint64_t *res_precopy_only,
3414+
uint64_t *res_compatible,
3415+
uint64_t *res_postcopy_only)
34163416
{
34173417
RAMState **temp = opaque;
34183418
RAMState *rs = *temp;
3419-
uint64_t remaining_size;
34203419

3421-
remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;
3420+
uint64_t remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;
34223421

3423-
if (!migration_in_postcopy() &&
3424-
remaining_size < max_size) {
3422+
if (migrate_postcopy_ram()) {
3423+
/* We can do postcopy, and all the data is postcopiable */
3424+
*res_postcopy_only += remaining_size;
3425+
} else {
3426+
*res_precopy_only += remaining_size;
3427+
}
3428+
}
3429+
3430+
static void ram_state_pending_exact(void *opaque, uint64_t max_size,
3431+
uint64_t *res_precopy_only,
3432+
uint64_t *res_compatible,
3433+
uint64_t *res_postcopy_only)
3434+
{
3435+
RAMState **temp = opaque;
3436+
RAMState *rs = *temp;
3437+
3438+
uint64_t remaining_size = rs->migration_dirty_pages * TARGET_PAGE_SIZE;
3439+
3440+
if (!migration_in_postcopy()) {
34253441
qemu_mutex_lock_iothread();
34263442
WITH_RCU_READ_LOCK_GUARD() {
34273443
migration_bitmap_sync_precopy(rs);
@@ -4577,7 +4593,8 @@ static SaveVMHandlers savevm_ram_handlers = {
45774593
.save_live_complete_postcopy = ram_save_complete,
45784594
.save_live_complete_precopy = ram_save_complete,
45794595
.has_postcopy = ram_has_postcopy,
4580-
.save_live_pending = ram_save_pending,
4596+
.state_pending_exact = ram_state_pending_exact,
4597+
.state_pending_estimate = ram_state_pending_estimate,
45814598
.load_state = ram_load,
45824599
.save_cleanup = ram_save_cleanup,
45834600
.load_setup = ram_load_setup,

migration/savevm.c

+34-8
Original file line numberDiff line numberDiff line change
@@ -1472,10 +1472,10 @@ int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
14721472
* the result is split into the amount for units that can and
14731473
* for units that can't do postcopy.
14741474
*/
1475-
void qemu_savevm_state_pending(uint64_t threshold_size,
1476-
uint64_t *res_precopy_only,
1477-
uint64_t *res_compatible,
1478-
uint64_t *res_postcopy_only)
1475+
void qemu_savevm_state_pending_estimate(uint64_t threshold_size,
1476+
uint64_t *res_precopy_only,
1477+
uint64_t *res_compatible,
1478+
uint64_t *res_postcopy_only)
14791479
{
14801480
SaveStateEntry *se;
14811481

@@ -1485,17 +1485,43 @@ void qemu_savevm_state_pending(uint64_t threshold_size,
14851485

14861486

14871487
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1488-
if (!se->ops || !se->ops->save_live_pending) {
1488+
if (!se->ops || !se->ops->state_pending_exact) {
14891489
continue;
14901490
}
14911491
if (se->ops->is_active) {
14921492
if (!se->ops->is_active(se->opaque)) {
14931493
continue;
14941494
}
14951495
}
1496-
se->ops->save_live_pending(se->opaque, threshold_size,
1497-
res_precopy_only, res_compatible,
1498-
res_postcopy_only);
1496+
se->ops->state_pending_exact(se->opaque, threshold_size,
1497+
res_precopy_only, res_compatible,
1498+
res_postcopy_only);
1499+
}
1500+
}
1501+
1502+
void qemu_savevm_state_pending_exact(uint64_t threshold_size,
1503+
uint64_t *res_precopy_only,
1504+
uint64_t *res_compatible,
1505+
uint64_t *res_postcopy_only)
1506+
{
1507+
SaveStateEntry *se;
1508+
1509+
*res_precopy_only = 0;
1510+
*res_compatible = 0;
1511+
*res_postcopy_only = 0;
1512+
1513+
QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
1514+
if (!se->ops || !se->ops->state_pending_estimate) {
1515+
continue;
1516+
}
1517+
if (se->ops->is_active) {
1518+
if (!se->ops->is_active(se->opaque)) {
1519+
continue;
1520+
}
1521+
}
1522+
se->ops->state_pending_estimate(se->opaque, threshold_size,
1523+
res_precopy_only, res_compatible,
1524+
res_postcopy_only);
14991525
}
15001526
}
15011527

migration/savevm.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,14 @@ void qemu_savevm_state_cleanup(void);
4040
void qemu_savevm_state_complete_postcopy(QEMUFile *f);
4141
int qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only,
4242
bool inactivate_disks);
43-
void qemu_savevm_state_pending(uint64_t max_size,
44-
uint64_t *res_precopy_only,
45-
uint64_t *res_compatible,
46-
uint64_t *res_postcopy_only);
43+
void qemu_savevm_state_pending_exact(uint64_t threshold_size,
44+
uint64_t *res_precopy_only,
45+
uint64_t *res_compatible,
46+
uint64_t *res_postcopy_only);
47+
void qemu_savevm_state_pending_estimate(uint64_t thershold_size,
48+
uint64_t *res_precopy_only,
49+
uint64_t *res_compatible,
50+
uint64_t *res_postcopy_only);
4751
void qemu_savevm_send_ping(QEMUFile *f, uint32_t value);
4852
void qemu_savevm_send_open_return_path(QEMUFile *f);
4953
int qemu_savevm_send_packaged(QEMUFile *f, const uint8_t *buf, size_t len);

0 commit comments

Comments
 (0)