[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 18/20] migration/ram: Handle RAMBlocks with a RamDiscardManager on
From: |
Juan Quintela |
Subject: |
[PULL 18/20] migration/ram: Handle RAMBlocks with a RamDiscardManager on background snapshots |
Date: |
Mon, 1 Nov 2021 23:09:10 +0100 |
From: David Hildenbrand <david@redhat.com>
We already don't ever migrate memory that corresponds to discarded ranges
as managed by a RamDiscardManager responsible for the mapped memory region
of the RAMBlock.
virtio-mem uses this mechanism to logically unplug parts of a RAMBlock.
Right now, we still populate zeropages for the whole usable part of the
RAMBlock, which is undesired because:
1. Even populating the shared zeropage will result in memory getting
consumed for page tables.
2. Memory backends without a shared zeropage (like hugetlbfs and shmem)
will populate an actual, fresh page, resulting in an unintended
memory consumption.
Discarded ("logically unplugged") parts have to remain discarded. As
these pages are never part of the migration stream, there is no need to
track modifications via userfaultfd WP reliably for these parts.
Further, any writes to these ranges by the VM are invalid and the
behavior is undefined.
Note that Linux only supports userfaultfd WP on private anonymous memory
for now, which usually results in the shared zeropage getting populated.
The issue will become more relevant once userfaultfd WP supports shmem
and hugetlb.
Acked-by: Peter Xu <peterx@redhat.com>
Signed-off-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Juan Quintela <quintela@redhat.com>
Signed-off-by: Juan Quintela <quintela@redhat.com>
---
migration/ram.c | 38 ++++++++++++++++++++++++++++++++++++--
1 file changed, 36 insertions(+), 2 deletions(-)
diff --git a/migration/ram.c b/migration/ram.c
index 92c7b788ae..680a5158aa 100644
--- a/migration/ram.c
+++ b/migration/ram.c
@@ -1656,6 +1656,17 @@ static inline void populate_read_range(RAMBlock *block,
ram_addr_t offset,
}
}
+static inline int populate_read_section(MemoryRegionSection *section,
+ void *opaque)
+{
+ const hwaddr size = int128_get64(section->size);
+ hwaddr offset = section->offset_within_region;
+ RAMBlock *block = section->mr->ram_block;
+
+ populate_read_range(block, offset, size);
+ return 0;
+}
+
/*
* ram_block_populate_read: preallocate page tables and populate pages in the
* RAM block by reading a byte of each page.
@@ -1665,9 +1676,32 @@ static inline void populate_read_range(RAMBlock *block,
ram_addr_t offset,
*
* @block: RAM block to populate
*/
-static void ram_block_populate_read(RAMBlock *block)
+static void ram_block_populate_read(RAMBlock *rb)
{
- populate_read_range(block, 0, block->used_length);
+ /*
+ * Skip populating all pages that fall into a discarded range as managed by
+ * a RamDiscardManager responsible for the mapped memory region of the
+ * RAMBlock. Such discarded ("logically unplugged") parts of a RAMBlock
+ * must not get populated automatically. We don't have to track
+ * modifications via userfaultfd WP reliably, because these pages will
+ * not be part of the migration stream either way -- see
+ * ramblock_dirty_bitmap_exclude_discarded_pages().
+ *
+ * Note: The result is only stable while migrating (precopy/postcopy).
+ */
+ if (rb->mr && memory_region_has_ram_discard_manager(rb->mr)) {
+ RamDiscardManager *rdm = memory_region_get_ram_discard_manager(rb->mr);
+ MemoryRegionSection section = {
+ .mr = rb->mr,
+ .offset_within_region = 0,
+ .size = rb->mr->size,
+ };
+
+ ram_discard_manager_replay_populated(rdm, §ion,
+ populate_read_section, NULL);
+ } else {
+ populate_read_range(rb, 0, rb->used_length);
+ }
}
/*
--
2.33.1
- [PULL 05/20] migration/dirtyrate: adjust order of registering thread, (continued)
- [PULL 05/20] migration/dirtyrate: adjust order of registering thread, Juan Quintela, 2021/11/01
- [PULL 03/20] memory: make global_dirty_tracking a bitmask, Juan Quintela, 2021/11/01
- [PULL 06/20] migration/dirtyrate: move init step of calculation to main thread, Juan Quintela, 2021/11/01
- [PULL 08/20] migration: Make migration blocker work for snapshots too, Juan Quintela, 2021/11/01
- [PULL 09/20] migration: Add migrate_add_blocker_internal(), Juan Quintela, 2021/11/01
- [PULL 10/20] dump-guest-memory: Block live migration, Juan Quintela, 2021/11/01
- [PULL 11/20] memory: Introduce replay_discarded callback for RamDiscardManager, Juan Quintela, 2021/11/01
- [PULL 12/20] virtio-mem: Implement replay_discarded RamDiscardManager callback, Juan Quintela, 2021/11/01
- [PULL 13/20] migration/ram: Handle RAMBlocks with a RamDiscardManager on the migration source, Juan Quintela, 2021/11/01
- [PULL 14/20] virtio-mem: Drop precopy notifier, Juan Quintela, 2021/11/01
- [PULL 18/20] migration/ram: Handle RAMBlocks with a RamDiscardManager on background snapshots,
Juan Quintela <=
- [PULL 07/20] migration/dirtyrate: implement dirty-ring dirtyrate calculation, Juan Quintela, 2021/11/01
- [PULL 19/20] memory: introduce total_dirty_pages to stat dirty pages, Juan Quintela, 2021/11/01
- [PULL 20/20] migration/dirtyrate: implement dirty-bitmap dirtyrate calculation, Juan Quintela, 2021/11/01
- [PULL 16/20] migration: Simplify alignment and alignment checks, Juan Quintela, 2021/11/01
- [PULL 15/20] migration/postcopy: Handle RAMBlocks with a RamDiscardManager on the destination, Juan Quintela, 2021/11/01
- [PULL 17/20] migration/ram: Factor out populating pages readable in ram_block_populate_pages(), Juan Quintela, 2021/11/01
- Re: [PULL 00/20] Migration 20211031 patches, Richard Henderson, 2021/11/02