The only two things the multifd client needs to access are the active
slot and the active slot size:
The active slot itself is obviously needed because it's where the data
is put.
The slot size is needed only by the ram pages code, because it does
not fill the data slot and sends it in one go, it instead fills the
slot partially at each call of multifd_queue_page(), so the size is
needed to differentiate an empty slot (free or recently consumed) from
the slot that is partially full.
Hide the MultiFDSlots implementation so the client is not tempted to
make use of the free list. That field is there simply because we need
the client to carry a handle to that memory, it's not supposed to be
accessed directly.
Signed-off-by: Fabiano Rosas <farosas@suse.de>
---
migration/multifd.c | 26 +++++++++++++++++++++++---
migration/multifd.h | 8 +++-----
2 files changed, 26 insertions(+), 8 deletions(-)
diff --git a/migration/multifd.c b/migration/multifd.c
index f22a1c2e84..9fb719eb0d 100644
--- a/migration/multifd.c
+++ b/migration/multifd.c
@@ -38,6 +38,11 @@
#define MULTIFD_MAGIC 0x11223344U
#define MULTIFD_VERSION 1
+struct MultiFDSlots {
+ MultiFDSendData **free;
+ MultiFDSendData *active;
+};
+
typedef struct {
uint32_t magic;
uint32_t version;
@@ -737,7 +742,22 @@ static inline bool multifd_queue_full(MultiFDPages_t *pages)
static inline void multifd_enqueue(MultiFDPages_t *pages, ram_addr_t offset)
{
pages->offset[pages->num++] = offset;
- multifd_ram_send_slots->active->size += qemu_target_page_size();
+ multifd_set_slot_size(multifd_ram_send_slots, qemu_target_page_size());
+}
+
+void *multifd_get_active_slot(MultiFDSlots *multifd_ram_send_slots)
+{
+ return multifd_ram_send_slots->active->opaque;
+}
+
+void multifd_set_slot_size(MultiFDSlots *multifd_ram_send_slots, size_t size)
+{
+ multifd_ram_send_slots->active->size += size;
+}
+
+bool multifd_slot_has_data(MultiFDSlots *multifd_ram_send_slots)
+{
+ return !!multifd_ram_send_slots->active->size;
}
/* Returns true if enqueue successful, false otherwise */
@@ -746,7 +766,7 @@ bool multifd_queue_page(RAMBlock *block, ram_addr_t offset)
MultiFDPages_t *pages;
retry:
- pages = multifd_ram_send_slots->active->opaque;
+ pages = multifd_get_active_slot(multifd_ram_send_slots);
/* If the queue is empty, we can already enqueue now */
if (multifd_queue_empty(pages)) {
@@ -951,7 +971,7 @@ int multifd_send_sync_main(void)
return 0;
}
- if (multifd_ram_send_slots->active->size) {
+ if (multifd_slot_has_data(multifd_ram_send_slots)) {
if (!multifd_send(multifd_ram_send_slots)) {
error_report("%s: multifd_send_pages fail", __func__);
return -1;
diff --git a/migration/multifd.h b/migration/multifd.h
index 5230729077..8f99fe2652 100644
--- a/migration/multifd.h
+++ b/migration/multifd.h
@@ -102,15 +102,13 @@ struct MultiFDSendData {
void (*cleanup)(void *);
};
-struct MultiFDSlots {
- MultiFDSendData **free;
- MultiFDSendData *active;
-};
-
MultiFDSlots *multifd_allocate_slots(void *(*alloc_fn)(void),
void (*reset_fn)(void *),
void (*cleanup_fn)(void *));
void multifd_ram_save_setup(void);
+void *multifd_get_active_slot(MultiFDSlots *multifd_ram_send_slots);
+void multifd_set_slot_size(MultiFDSlots *multifd_ram_send_slots, size_t size);
+bool multifd_slot_has_data(MultiFDSlots *multifd_ram_send_slots);
typedef struct {
/* Fields are only written at creating/deletion time */
--
2.35.3