Please note that there are a couple of errors (swapped parameters), which are detailed below. I will address these in the next iteration, along with any additional changes based on your feedback.
Thank you Marco On Wednesday, October 01, 2025 18:18 CEST, Marco Cavenati <[email protected]> wrote: > Make mapped-ram compatible with loadvm snapshot restoring by explicitly > zeroing memory pages in this case. > Skip zeroing for -incoming and -loadvm migrations to preserve performance. > > Signed-off-by: Marco Cavenati <[email protected]> > --- > migration/ram.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 55 insertions(+), 1 deletion(-) > > diff --git a/migration/ram.c b/migration/ram.c > index e238c9233f..597d5ffe9e 100644 > --- a/migration/ram.c > +++ b/migration/ram.c > @@ -3958,12 +3958,55 @@ static size_t ram_load_multifd_pages(void *host_addr, > size_t size, > return size; > } > > +/** > + * handle_zero_mapped_ram: Zero out a range of RAM pages if required during > + * mapped-ram load > + * > + * Zeroing is only performed when restoring from a snapshot (HMP loadvm). > + * During incoming migration or -loadvm cli snapshot load, the function is a > + * no-op and returns true as in those cases the pages are already guaranteed > to > + * be zeroed. > + * > + * Returns: true on success, false on error (with @errp set). > + * @from_bit_idx: Starting index relative to the map of the page (inclusive) > + * @to_bit_idx: Ending index relative to the map of the page (exclusive) > + */ > +static bool handle_zero_mapped_ram(RAMBlock *block, unsigned long > from_bit_idx, > + unsigned long to_bit_idx, Error **errp) > +{ > + ERRP_GUARD(); > + ram_addr_t offset; > + size_t size; > + void *host; > + > + if (runstate_check(RUN_STATE_INMIGRATE) || > + runstate_check(RUN_STATE_PRELAUNCH)) { > + return true; > + } > + > + if (from_bit_idx == to_bit_idx) { > + return true; > + } > + > + size = TARGET_PAGE_SIZE * (to_bit_idx - from_bit_idx); > + offset = from_bit_idx << TARGET_PAGE_BITS; > + host = host_from_ram_block_offset(block, offset); > + if (!host) { > + error_setg(errp, "zero page outside of ramblock %s range", > + block->idstr); > + return false; > + } > + ram_handle_zero(host, size); > + > + return true; > +} > + > static bool read_ramblock_mapped_ram(QEMUFile *f, RAMBlock *block, > long num_pages, unsigned long *bitmap, > Error **errp) > { > ERRP_GUARD(); > - unsigned long set_bit_idx, clear_bit_idx; > + unsigned long set_bit_idx, clear_bit_idx = 0; > ram_addr_t offset; > void *host; > size_t read, unread, size; > @@ -3972,6 +4015,12 @@ static bool read_ramblock_mapped_ram(QEMUFile *f, > RAMBlock *block, > set_bit_idx < num_pages; > set_bit_idx = find_next_bit(bitmap, num_pages, clear_bit_idx + 1)) { > > + /* Zero pages */ > + if (!handle_zero_mapped_ram(block, set_bit_idx, clear_bit_idx, > errp)) { This should be + if (!handle_zero_mapped_ram(block, clear_bit_idx, set_bit_idx, errp)) { > + return false; > + } > + > + /* Non-zero pages */ > clear_bit_idx = find_next_zero_bit(bitmap, num_pages, set_bit_idx + > 1); > > unread = TARGET_PAGE_SIZE * (clear_bit_idx - set_bit_idx); > @@ -4003,6 +4052,11 @@ static bool read_ramblock_mapped_ram(QEMUFile *f, > RAMBlock *block, > } > } > > + /* Handle trailing 0 pages */ > + if (!handle_zero_mapped_ram(block, num_pages, clear_bit_idx, errp)) { This should be + if (!handle_zero_mapped_ram(block, clear_bit_idx, num_pages, errp)) { > + return false; > + } > + > return true; > > err: > -- > 2.48.1 >
