migration: Extract blocktime marking helper
Use new function try_mark_postcopy_blocktim_begin() to call mark_postcopy_blocktime_begin if page was not received and return if it actually marked it. This will help in having a cleaner API to call mark_postcopy_blocktime_begin as it requires the page to not be received by asserting on it's existance in RAMBlock->receivedmap. Signed-off-by: Aadeshveer Singh <aadeshveer07@gmail.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: Juraj Marcin <jmarcin@redhat.com> Signed-off-by: Peter Xu <peterx@redhat.com> Signed-off-by: Fabiano Rosas <farosas@suse.de>
Aadeshveer Singh committed
Aug 16, 2026 at 23:16 UTC
664fe212db0a70e365fda767380402d895d8d8fe
3 files changed
+44
-22
migration/migration.c
+2
-22
@@ -577,32 +577,12 @@ int migrate_send_rp_req_pages(MigrationIncomingState *mis,
577
RAMBlock *rb, ram_addr_t start, uint64_t haddr,
578
uint32_t tid)
579
{
580
- void *aligned = (void *)(uintptr_t)ROUND_DOWN(haddr, qemu_ram_pagesize(rb));
581
- bool received = false;
582
-
583
- WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) {
584
- received = ramblock_recv_bitmap_test_byte_offset(rb, start);
585
- if (!received) {
586
- if (!g_tree_lookup(mis->page_requested, aligned)) {
587
- /*
588
- * The page has not been received, and it's not yet in the
589
- * page request list. Queue it. Set the value of element
590
- * to 1, so that things like g_tree_lookup() will return
591
- * TRUE (1) when found.
592
- */
593
- g_tree_insert(mis->page_requested, aligned, (gpointer)1);
594
- qatomic_inc(&mis->page_requested_count);
595
- trace_postcopy_page_req_add(aligned, mis->page_requested_count);
596
- }
597
- mark_postcopy_blocktime_begin(haddr, tid, rb);
598
- }
599
- }
600
-
580
/*
581
+ * If not able to mark page for blocktime it must already be present.
582
* If the page is there, skip sending the message. We don't even need the
583
* lock because as long as the page arrived, it'll be there forever.
584
*/
605
- if (received) {
585
+ if (!try_mark_postcopy_blocktime_begin(mis, rb, start, haddr, tid)) {
586
return 0;
587
}
588
migration/postcopy-ram.c
+39
@@ -1054,6 +1054,37 @@ static void blocktime_fault_inject(PostcopyBlocktimeContext *ctx,
1054
trace_postcopy_blocktime_begin(addr, time, cpu, !!head);
1055
}
1056
1057
+/*
1058
+ * Take @page_request_mutex and try marking postcopy blocktime begin.
1059
+ * Return true if marking is successful and false if page alredy exists.
1060
+ */
1061
+bool try_mark_postcopy_blocktime_begin(MigrationIncomingState *mis,
1062
+ RAMBlock *rb, ram_addr_t start,
1063
+ uint64_t haddr, uint32_t tid)
1064
+{
1065
+ bool received = false;
1066
+ void *aligned = (void *)(uintptr_t)ROUND_DOWN(haddr, qemu_ram_pagesize(rb));
1067
+
1068
+ WITH_QEMU_LOCK_GUARD(&mis->page_request_mutex) {
1069
+ received = ramblock_recv_bitmap_test_byte_offset(rb, start);
1070
+ if (!received) {
1071
+ if (!g_tree_lookup(mis->page_requested, aligned)) {
1072
+ /*
1073
+ * The page has not been received, and it's not yet in the
1074
+ * page request list. Queue it. Set the value of element
1075
+ * to 1, so that things like g_tree_lookup() will return
1076
+ * TRUE (1) when found.
1077
+ */
1078
+ g_tree_insert(mis->page_requested, aligned, (gpointer)1);
1079
+ qatomic_inc(&mis->page_requested_count);
1080
+ trace_postcopy_page_req_add(aligned, mis->page_requested_count);
1081
+ }
1082
+ mark_postcopy_blocktime_begin((uint64_t)aligned, tid, rb);
1083
+ }
1084
+ }
1085
+ return !received;
1086
+}
1087
+
1088
/*
1089
* This function is being called when pagefault occurs. It tracks down vCPU
1090
* blocking time. It's protected by @page_request_mutex.
@@ -1749,6 +1780,14 @@ void mark_postcopy_blocktime_begin(uintptr_t addr, uint32_t ptid,
1780
RAMBlock *rb)
1781
{
1782
}
1783
+
1784
+bool try_mark_postcopy_blocktime_begin(MigrationIncomingState *mis,
1785
+ RAMBlock *rb, ram_addr_t start,
1786
+ uint64_t haddr, uint32_t tid)
1787
+{
1788
+ g_assert_not_reached();
1789
+ return false;
1790
+}
1791
#endif
1792
1793
/* ------------------------------------------------------------------------- */
migration/postcopy-ram.h
+3
@@ -196,6 +196,9 @@ void postcopy_preempt_new_channel(MigrationIncomingState *mis, QEMUFile *file);
196
void postcopy_preempt_setup(MigrationState *s);
197
int postcopy_preempt_establish_channel(MigrationState *s);
198
bool postcopy_is_paused(MigrationStatus status);
199
+bool try_mark_postcopy_blocktime_begin(MigrationIncomingState *mis,
200
+ RAMBlock *rb, ram_addr_t start,
201
+ uint64_t haddr, uint32_t tid);
202
void mark_postcopy_blocktime_begin(uintptr_t addr, uint32_t ptid,
203
RAMBlock *rb);
204