1313from tenacity import Retrying , retry_if_exception_type , stop_after_delay , wait_fixed
1414
1515from framework .guest_stats import MeminfoGuest
16- from framework .microvm import HugePagesConfig
16+ from framework .microvm import HugePagesConfig , SnapshotType
1717from framework .properties import global_props
1818from framework .utils import get_kernel_version , get_resident_memory
1919
2222
2323
2424def uvm_booted_memhp (
25- uvm , rootfs , _microvm_factory , vhost_user , memhp_config , huge_pages , _uffd_handler
25+ uvm ,
26+ rootfs ,
27+ _microvm_factory ,
28+ vhost_user ,
29+ memhp_config ,
30+ huge_pages ,
31+ _uffd_handler ,
32+ snapshot_type ,
2633):
2734 """Boots a VM with the given memory hotplugging config"""
2835
@@ -34,7 +41,12 @@ def uvm_booted_memhp(
3441 ssh_key = rootfs .with_suffix (".id_rsa" )
3542 uvm .ssh_key = ssh_key
3643 uvm .basic_config (
37- boot_args = MEMHP_BOOTARGS , add_root_device = False , huge_pages = huge_pages
44+ boot_args = MEMHP_BOOTARGS ,
45+ add_root_device = False ,
46+ huge_pages = huge_pages ,
47+ track_dirty_pages = (
48+ snapshot_type .needs_dirty_page_tracking if snapshot_type else False
49+ ),
3850 )
3951 uvm .add_vhost_user_drive (
4052 "rootfs" , rootfs , is_root_device = True , is_read_only = True
@@ -56,40 +68,70 @@ def uvm_resumed_memhp(
5668 memhp_config ,
5769 huge_pages ,
5870 uffd_handler ,
71+ snapshot_type ,
5972):
6073 """Restores a VM with the given memory hotplugging config after booting and snapshotting"""
6174 if vhost_user :
6275 pytest .skip ("vhost-user doesn't support snapshot/restore" )
6376 if huge_pages and huge_pages != HugePagesConfig .NONE and not uffd_handler :
6477 pytest .skip ("Hugepages requires a UFFD handler" )
6578 uvm = uvm_booted_memhp (
66- uvm_plain , rootfs , microvm_factory , vhost_user , memhp_config , huge_pages , None
79+ uvm_plain ,
80+ rootfs ,
81+ microvm_factory ,
82+ vhost_user ,
83+ memhp_config ,
84+ huge_pages ,
85+ None ,
86+ snapshot_type ,
6787 )
68- snapshot = uvm .snapshot_full ( )
88+ snapshot = uvm .make_snapshot ( snapshot_type )
6989 return microvm_factory .build_from_snapshot (snapshot , uffd_handler_name = uffd_handler )
7090
7191
7292@pytest .fixture (
7393 params = [
74- (uvm_booted_memhp , False , HugePagesConfig .NONE , None ),
75- (uvm_booted_memhp , False , HugePagesConfig .HUGETLBFS_2MB , None ),
76- (uvm_booted_memhp , True , HugePagesConfig .NONE , None ),
77- (uvm_resumed_memhp , False , HugePagesConfig .NONE , None ),
78- (uvm_resumed_memhp , False , HugePagesConfig .NONE , "on_demand" ),
79- (uvm_resumed_memhp , False , HugePagesConfig .HUGETLBFS_2MB , "on_demand" ),
94+ (uvm_booted_memhp , False , HugePagesConfig .NONE , None , None ),
95+ (uvm_booted_memhp , False , HugePagesConfig .HUGETLBFS_2MB , None , None ),
96+ (uvm_booted_memhp , True , HugePagesConfig .NONE , None , None ),
97+ (uvm_resumed_memhp , False , HugePagesConfig .NONE , None , SnapshotType .FULL ),
98+ (uvm_resumed_memhp , False , HugePagesConfig .NONE , None , SnapshotType .DIFF ),
99+ (
100+ uvm_resumed_memhp ,
101+ False ,
102+ HugePagesConfig .NONE ,
103+ None ,
104+ SnapshotType .DIFF_MINCORE ,
105+ ),
106+ (
107+ uvm_resumed_memhp ,
108+ False ,
109+ HugePagesConfig .NONE ,
110+ "on_demand" ,
111+ SnapshotType .FULL ,
112+ ),
113+ (
114+ uvm_resumed_memhp ,
115+ False ,
116+ HugePagesConfig .HUGETLBFS_2MB ,
117+ "on_demand" ,
118+ SnapshotType .FULL ,
119+ ),
80120 ],
81121 ids = [
82122 "booted" ,
83123 "booted-huge-pages" ,
84124 "booted-vhost-user" ,
85125 "resumed" ,
126+ "resumed-diff" ,
127+ "resumed-mincore" ,
86128 "resumed-uffd" ,
87129 "resumed-uffd-huge-pages" ,
88130 ],
89131)
90132def uvm_any_memhp (request , uvm_plain_6_1 , rootfs , microvm_factory ):
91133 """Fixture that yields a booted or resumed VM with memory hotplugging"""
92- ctor , vhost_user , huge_pages , uffd_handler = request .param
134+ ctor , vhost_user , huge_pages , uffd_handler , snapshot_type = request .param
93135 yield ctor (
94136 uvm_plain_6_1 ,
95137 rootfs ,
@@ -98,6 +140,7 @@ def uvm_any_memhp(request, uvm_plain_6_1, rootfs, microvm_factory):
98140 DEFAULT_CONFIG ,
99141 huge_pages ,
100142 uffd_handler ,
143+ snapshot_type ,
101144 )
102145
103146
@@ -237,7 +280,9 @@ def test_virtio_mem_configs(uvm_plain_6_1, memhp_config):
237280 """
238281 Check that the virtio mem device is working as expected for different configs
239282 """
240- uvm = uvm_booted_memhp (uvm_plain_6_1 , None , None , False , memhp_config , None , None )
283+ uvm = uvm_booted_memhp (
284+ uvm_plain_6_1 , None , None , False , memhp_config , None , None , None
285+ )
241286 if not uvm .pci_enabled :
242287 pytest .skip (
243288 "Skip tests on MMIO transport to save time as we don't expect any difference."
@@ -262,7 +307,7 @@ def test_virtio_mem_configs(uvm_plain_6_1, memhp_config):
262307 validate_metrics (uvm )
263308
264309
265- def test_snapshot_restore_persistence (uvm_plain_6_1 , microvm_factory ):
310+ def test_snapshot_restore_persistence (uvm_plain_6_1 , microvm_factory , snapshot_type ):
266311 """
267312 Check that hptplugged memory is persisted across snapshot/restore.
268313 """
@@ -271,7 +316,14 @@ def test_snapshot_restore_persistence(uvm_plain_6_1, microvm_factory):
271316 "Skip tests on MMIO transport to save time as we don't expect any difference."
272317 )
273318 uvm = uvm_booted_memhp (
274- uvm_plain_6_1 , None , microvm_factory , False , DEFAULT_CONFIG , None , None
319+ uvm_plain_6_1 ,
320+ None ,
321+ microvm_factory ,
322+ False ,
323+ DEFAULT_CONFIG ,
324+ None ,
325+ None ,
326+ snapshot_type ,
275327 )
276328
277329 uvm .hotplug_memory (1024 )
@@ -348,7 +400,9 @@ def test_memory_hotplug_latency(
348400 "block_size_mib" : 2 ,
349401 }
350402 uvm_plain_6_1 = microvm_factory .build (guest_kernel_linux_6_1 , rootfs , pci = True )
351- uvm = uvm_booted_memhp (uvm_plain_6_1 , None , None , False , config , None , None )
403+ uvm = uvm_booted_memhp (
404+ uvm_plain_6_1 , None , None , False , config , None , None , None
405+ )
352406
353407 if i == 0 :
354408 metrics .set_dimensions (
0 commit comments