From: Trieu Huynh <vikingtc4@gmail.com>
Add start_time, total_time, received_normal_pages,
received_zero_pages, and received_xbzrle_pages to
MigrationIncomingState.
start_time is recorded when the incoming state transitions to ACTIVE;
total_time is recorded when it transitions to COMPLETED. The page
counters are incremented in ram_load_precopy() as each page type is
received from the source.
These fields will be used by a subsequent patch to populate
fill_destination_migration_info() for the migration COMPLETED case.
Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
---
migration/migration.c | 2 ++
migration/migration.h | 17 +++++++++++++++++
migration/ram.c | 3 +++
3 files changed, 22 insertions(+)
diff --git a/migration/migration.c b/migration/migration.c
index 5c9aaa6e58..17c9a8b344 100644
--- a/migration/migration.c
+++ b/migration/migration.c
@@ -726,6 +726,7 @@ static void process_incoming_migration_bh(void *opaque)
*/
migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
MIGRATION_STATUS_COMPLETED);
+ mis->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - mis->start_time;
migration_incoming_state_destroy();
}
@@ -758,6 +759,7 @@ process_incoming_migration_co(void *opaque)
migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP,
MIGRATION_STATUS_ACTIVE);
+ mis->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
mis->loadvm_co = qemu_coroutine_self();
ret = qemu_loadvm_state(mis->from_src_file, &local_err);
mis->loadvm_co = NULL;
diff --git a/migration/migration.h b/migration/migration.h
index b6888daced..cd51ae452c 100644
--- a/migration/migration.h
+++ b/migration/migration.h
@@ -176,6 +176,23 @@ struct MigrationIncomingState {
/* PostCopyFD's for external userfaultfds & handlers of shared memory */
GArray *postcopy_remote_fds;
+ /*
+ * Timestamps for reporting migration duration via query-migrate on the
+ * destination. start_time is recorded when the state moves to ACTIVE;
+ * total_time is recorded when it moves to COMPLETED.
+ */
+ int64_t start_time;
+ int64_t total_time;
+
+ /*
+ * Page counters for reporting RAM statistics via query-migrate on the
+ * destination. Incremented in ram_load_precopy() as each page type
+ * is received.
+ */
+ uint64_t received_normal_pages;
+ uint64_t received_zero_pages;
+ uint64_t received_xbzrle_pages;
+
MigrationStatus state;
/*
diff --git a/migration/ram.c b/migration/ram.c
index 979751f61b..6646e5daad 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -4417,10 +4417,12 @@ static int ram_load_precopy(QEMUFile *f)
break;
}
ram_handle_zero(host, TARGET_PAGE_SIZE);
+ mis->received_zero_pages++;
break;
case RAM_SAVE_FLAG_PAGE:
qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
+ mis->received_normal_pages++;
break;
case RAM_SAVE_FLAG_XBZRLE:
@@ -4430,6 +4432,7 @@ static int ram_load_precopy(QEMUFile *f)
ret = -EINVAL;
break;
}
+ mis->received_xbzrle_pages++;
break;
case RAM_SAVE_FLAG_MULTIFD_FLUSH:
multifd_recv_sync_main();
--
2.43.0
Hello,
On 4/5/26 17:26, Trieu Huynh wrote:
> From: Trieu Huynh <vikingtc4@gmail.com>
>
> Add start_time, total_time, received_normal_pages,
> received_zero_pages, and received_xbzrle_pages to
> MigrationIncomingState.
>
> start_time is recorded when the incoming state transitions to ACTIVE;
> total_time is recorded when it transitions to COMPLETED. The page
> counters are incremented in ram_load_precopy() as each page type is
> received from the source.
>
> These fields will be used by a subsequent patch to populate
> fill_destination_migration_info() for the migration COMPLETED case.
>
> Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
> ---
> migration/migration.c | 2 ++
> migration/migration.h | 17 +++++++++++++++++
> migration/ram.c | 3 +++
> 3 files changed, 22 insertions(+)
>
> diff --git a/migration/migration.c b/migration/migration.c
> index 5c9aaa6e58..17c9a8b344 100644
> --- a/migration/migration.c
> +++ b/migration/migration.c
> @@ -726,6 +726,7 @@ static void process_incoming_migration_bh(void *opaque)
> */
> migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
> MIGRATION_STATUS_COMPLETED);
> + mis->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - mis->start_time;
> migration_incoming_state_destroy();
> }
>
> @@ -758,6 +759,7 @@ process_incoming_migration_co(void *opaque)
> migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP,
> MIGRATION_STATUS_ACTIVE);
>
> + mis->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
> mis->loadvm_co = qemu_coroutine_self();
> ret = qemu_loadvm_state(mis->from_src_file, &local_err);
> mis->loadvm_co = NULL;
> diff --git a/migration/migration.h b/migration/migration.h
> index b6888daced..cd51ae452c 100644
> --- a/migration/migration.h
> +++ b/migration/migration.h
> @@ -176,6 +176,23 @@ struct MigrationIncomingState {
> /* PostCopyFD's for external userfaultfds & handlers of shared memory */
> GArray *postcopy_remote_fds;
>
> + /*
> + * Timestamps for reporting migration duration via query-migrate on the
> + * destination. start_time is recorded when the state moves to ACTIVE;
> + * total_time is recorded when it moves to COMPLETED.
> + */
> + int64_t start_time;
> + int64_t total_time;
nit: since this is a timestamp and these are directly linked to state changes,
why not call these:
int64_t migration_active_ts;
int64_t migration_completed_ts;
or something similar?
Thank you,
Claudio
> +
> + /*
> + * Page counters for reporting RAM statistics via query-migrate on the
> + * destination. Incremented in ram_load_precopy() as each page type
> + * is received.
> + */
> + uint64_t received_normal_pages;
> + uint64_t received_zero_pages;
> + uint64_t received_xbzrle_pages;
> +
> MigrationStatus state;
>
> /*
> diff --git a/migration/ram.c b/migration/ram.c
> index 979751f61b..6646e5daad 100644
> --- a/migration/ram.c
> +++ b/migration/ram.c
> @@ -4417,10 +4417,12 @@ static int ram_load_precopy(QEMUFile *f)
> break;
> }
> ram_handle_zero(host, TARGET_PAGE_SIZE);
> + mis->received_zero_pages++;
> break;
>
> case RAM_SAVE_FLAG_PAGE:
> qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
> + mis->received_normal_pages++;
> break;
>
> case RAM_SAVE_FLAG_XBZRLE:
> @@ -4430,6 +4432,7 @@ static int ram_load_precopy(QEMUFile *f)
> ret = -EINVAL;
> break;
> }
> + mis->received_xbzrle_pages++;
> break;
> case RAM_SAVE_FLAG_MULTIFD_FLUSH:
> multifd_recv_sync_main();
On 4/7/26 14:02, Claudio Fontana wrote:
> Hello,
>
> On 4/5/26 17:26, Trieu Huynh wrote:
>> From: Trieu Huynh <vikingtc4@gmail.com>
>>
>> Add start_time, total_time, received_normal_pages,
>> received_zero_pages, and received_xbzrle_pages to
>> MigrationIncomingState.
>>
>> start_time is recorded when the incoming state transitions to ACTIVE;
>> total_time is recorded when it transitions to COMPLETED. The page
>> counters are incremented in ram_load_precopy() as each page type is
>> received from the source.
>>
>> These fields will be used by a subsequent patch to populate
>> fill_destination_migration_info() for the migration COMPLETED case.
>>
>> Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
>> ---
>> migration/migration.c | 2 ++
>> migration/migration.h | 17 +++++++++++++++++
>> migration/ram.c | 3 +++
>> 3 files changed, 22 insertions(+)
>>
>> diff --git a/migration/migration.c b/migration/migration.c
>> index 5c9aaa6e58..17c9a8b344 100644
>> --- a/migration/migration.c
>> +++ b/migration/migration.c
>> @@ -726,6 +726,7 @@ static void process_incoming_migration_bh(void *opaque)
>> */
>> migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
>> MIGRATION_STATUS_COMPLETED);
>> + mis->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - mis->start_time;
>> migration_incoming_state_destroy();
>> }
>>
>> @@ -758,6 +759,7 @@ process_incoming_migration_co(void *opaque)
>> migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP,
>> MIGRATION_STATUS_ACTIVE);
>>
>> + mis->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
>> mis->loadvm_co = qemu_coroutine_self();
>> ret = qemu_loadvm_state(mis->from_src_file, &local_err);
>> mis->loadvm_co = NULL;
>> diff --git a/migration/migration.h b/migration/migration.h
>> index b6888daced..cd51ae452c 100644
>> --- a/migration/migration.h
>> +++ b/migration/migration.h
>> @@ -176,6 +176,23 @@ struct MigrationIncomingState {
>> /* PostCopyFD's for external userfaultfds & handlers of shared memory */
>> GArray *postcopy_remote_fds;
>>
>> + /*
>> + * Timestamps for reporting migration duration via query-migrate on the
>> + * destination. start_time is recorded when the state moves to ACTIVE;
>> + * total_time is recorded when it moves to COMPLETED.
>> + */
>> + int64_t start_time;
>> + int64_t total_time;
>
> nit: since this is a timestamp and these are directly linked to state changes,
> why not call these:
>
> int64_t migration_active_ts;
> int64_t migration_completed_ts;
I got the second one wrong, it is not a timestamp, that is indeed a time.
So clarity in the name seems to be more than a nit. What about:
int64_t migration_active_ts; /* ms */
int64_t migration_completed_time; /* ms */
Thanks,
Claudio
>
>> +
>> + /*
>> + * Page counters for reporting RAM statistics via query-migrate on the
>> + * destination. Incremented in ram_load_precopy() as each page type
>> + * is received.
>> + */
>> + uint64_t received_normal_pages;
>> + uint64_t received_zero_pages;
>> + uint64_t received_xbzrle_pages;
>> +
>> MigrationStatus state;
>>
>> /*
>> diff --git a/migration/ram.c b/migration/ram.c
>> index 979751f61b..6646e5daad 100644
>> --- a/migration/ram.c
>> +++ b/migration/ram.c
>> @@ -4417,10 +4417,12 @@ static int ram_load_precopy(QEMUFile *f)
>> break;
>> }
>> ram_handle_zero(host, TARGET_PAGE_SIZE);
>> + mis->received_zero_pages++;
>> break;
>>
>> case RAM_SAVE_FLAG_PAGE:
>> qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
>> + mis->received_normal_pages++;
>> break;
>>
>> case RAM_SAVE_FLAG_XBZRLE:
>> @@ -4430,6 +4432,7 @@ static int ram_load_precopy(QEMUFile *f)
>> ret = -EINVAL;
>> break;
>> }
>> + mis->received_xbzrle_pages++;
>> break;
>> case RAM_SAVE_FLAG_MULTIFD_FLUSH:
>> multifd_recv_sync_main();
>
On Tue, Apr 07, 2026 at 02:11:54PM +0200, Claudio Fontana wrote:
> On 4/7/26 14:02, Claudio Fontana wrote:
> > Hello,
> >
> > On 4/5/26 17:26, Trieu Huynh wrote:
> >> From: Trieu Huynh <vikingtc4@gmail.com>
> >>
> >> Add start_time, total_time, received_normal_pages,
> >> received_zero_pages, and received_xbzrle_pages to
> >> MigrationIncomingState.
> >>
> >> start_time is recorded when the incoming state transitions to ACTIVE;
> >> total_time is recorded when it transitions to COMPLETED. The page
> >> counters are incremented in ram_load_precopy() as each page type is
> >> received from the source.
> >>
> >> These fields will be used by a subsequent patch to populate
> >> fill_destination_migration_info() for the migration COMPLETED case.
> >>
> >> Signed-off-by: Trieu Huynh <vikingtc4@gmail.com>
> >> ---
> >> migration/migration.c | 2 ++
> >> migration/migration.h | 17 +++++++++++++++++
> >> migration/ram.c | 3 +++
> >> 3 files changed, 22 insertions(+)
> >>
> >> diff --git a/migration/migration.c b/migration/migration.c
> >> index 5c9aaa6e58..17c9a8b344 100644
> >> --- a/migration/migration.c
> >> +++ b/migration/migration.c
> >> @@ -726,6 +726,7 @@ static void process_incoming_migration_bh(void *opaque)
> >> */
> >> migrate_set_state(&mis->state, MIGRATION_STATUS_ACTIVE,
> >> MIGRATION_STATUS_COMPLETED);
> >> + mis->total_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME) - mis->start_time;
> >> migration_incoming_state_destroy();
> >> }
> >>
> >> @@ -758,6 +759,7 @@ process_incoming_migration_co(void *opaque)
> >> migrate_set_state(&mis->state, MIGRATION_STATUS_SETUP,
> >> MIGRATION_STATUS_ACTIVE);
> >>
> >> + mis->start_time = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
> >> mis->loadvm_co = qemu_coroutine_self();
> >> ret = qemu_loadvm_state(mis->from_src_file, &local_err);
> >> mis->loadvm_co = NULL;
> >> diff --git a/migration/migration.h b/migration/migration.h
> >> index b6888daced..cd51ae452c 100644
> >> --- a/migration/migration.h
> >> +++ b/migration/migration.h
> >> @@ -176,6 +176,23 @@ struct MigrationIncomingState {
> >> /* PostCopyFD's for external userfaultfds & handlers of shared memory */
> >> GArray *postcopy_remote_fds;
> >>
> >> + /*
> >> + * Timestamps for reporting migration duration via query-migrate on the
> >> + * destination. start_time is recorded when the state moves to ACTIVE;
> >> + * total_time is recorded when it moves to COMPLETED.
> >> + */
> >> + int64_t start_time;
> >> + int64_t total_time;
> >
> > nit: since this is a timestamp and these are directly linked to state changes,
> > why not call these:
> >
> > int64_t migration_active_ts;
> > int64_t migration_completed_ts;
>
> I got the second one wrong, it is not a timestamp, that is indeed a time.
> So clarity in the name seems to be more than a nit. What about:
>
> int64_t migration_active_ts; /* ms */
> int64_t migration_completed_time; /* ms */
>
make sense to me. will update in v2. thank you.
> Thanks,
>
> Claudio
>
> >
> >> +
> >> + /*
> >> + * Page counters for reporting RAM statistics via query-migrate on the
> >> + * destination. Incremented in ram_load_precopy() as each page type
> >> + * is received.
> >> + */
> >> + uint64_t received_normal_pages;
> >> + uint64_t received_zero_pages;
> >> + uint64_t received_xbzrle_pages;
> >> +
> >> MigrationStatus state;
> >>
> >> /*
> >> diff --git a/migration/ram.c b/migration/ram.c
> >> index 979751f61b..6646e5daad 100644
> >> --- a/migration/ram.c
> >> +++ b/migration/ram.c
> >> @@ -4417,10 +4417,12 @@ static int ram_load_precopy(QEMUFile *f)
> >> break;
> >> }
> >> ram_handle_zero(host, TARGET_PAGE_SIZE);
> >> + mis->received_zero_pages++;
> >> break;
> >>
> >> case RAM_SAVE_FLAG_PAGE:
> >> qemu_get_buffer(f, host, TARGET_PAGE_SIZE);
> >> + mis->received_normal_pages++;
> >> break;
> >>
> >> case RAM_SAVE_FLAG_XBZRLE:
> >> @@ -4430,6 +4432,7 @@ static int ram_load_precopy(QEMUFile *f)
> >> ret = -EINVAL;
> >> break;
> >> }
> >> + mis->received_xbzrle_pages++;
> >> break;
> >> case RAM_SAVE_FLAG_MULTIFD_FLUSH:
> >> multifd_recv_sync_main();
> >
>
BRs,
Trieu Huynh
© 2016 - 2026 Red Hat, Inc.