@@ -91,13 +91,21 @@ fn parse_put_snapshot_load(body: &Body) -> Result<ParsedRequest, RequestError> {
9191 // If `mem_file_path` is specified instead of `mem_backend`, we construct the
9292 // `MemBackendConfig` object from the path specified, with `File` as backend type.
9393 let mem_backend = match snapshot_config. mem_backend {
94- Some ( backend_cfg) => backend_cfg,
94+ Some ( backend_cfg) => {
95+ if backend_cfg. use_memfd && backend_cfg. backend_type != MemBackendType :: Uffd {
96+ return Err ( RequestError :: SerdeJson ( serde_json:: Error :: custom (
97+ "use_memfd is only valid when backend_type is Uffd" ,
98+ ) ) ) ;
99+ }
100+ backend_cfg
101+ }
95102 None => {
96103 MemBackendConfig {
97104 // This is safe to unwrap() because we ensure above that one of the two:
98105 // either `mem_file_path` or `mem_backend` field is always specified.
99106 backend_path : snapshot_config. mem_file_path . unwrap ( ) ,
100107 backend_type : MemBackendType :: File ,
108+ use_memfd : false ,
101109 }
102110 }
103111 } ;
@@ -184,6 +192,7 @@ mod tests {
184192 mem_backend : MemBackendConfig {
185193 backend_path : PathBuf :: from ( "bar" ) ,
186194 backend_type : MemBackendType :: File ,
195+ use_memfd : false ,
187196 } ,
188197 track_dirty_pages : false ,
189198 resume_vm : false ,
@@ -215,6 +224,7 @@ mod tests {
215224 mem_backend : MemBackendConfig {
216225 backend_path : PathBuf :: from ( "bar" ) ,
217226 backend_type : MemBackendType :: File ,
227+ use_memfd : false ,
218228 } ,
219229 track_dirty_pages : true ,
220230 resume_vm : false ,
@@ -246,6 +256,7 @@ mod tests {
246256 mem_backend : MemBackendConfig {
247257 backend_path : PathBuf :: from ( "bar" ) ,
248258 backend_type : MemBackendType :: Uffd ,
259+ use_memfd : false ,
249260 } ,
250261 track_dirty_pages : false ,
251262 resume_vm : true ,
@@ -283,6 +294,7 @@ mod tests {
283294 mem_backend : MemBackendConfig {
284295 backend_path : PathBuf :: from ( "bar" ) ,
285296 backend_type : MemBackendType :: Uffd ,
297+ use_memfd : false ,
286298 } ,
287299 track_dirty_pages : false ,
288300 resume_vm : true ,
@@ -314,6 +326,7 @@ mod tests {
314326 mem_backend : MemBackendConfig {
315327 backend_path : PathBuf :: from ( "bar" ) ,
316328 backend_type : MemBackendType :: File ,
329+ use_memfd : false ,
317330 } ,
318331 track_dirty_pages : false ,
319332 resume_vm : true ,
@@ -401,6 +414,45 @@ mod tests {
401414 ) ;
402415 parse_put_snapshot ( & Body :: new ( body) , Some ( "invalid" ) ) . unwrap_err ( ) ;
403416 parse_put_snapshot ( & Body :: new ( body) , None ) . unwrap_err ( ) ;
417+
418+ // use_memfd=true with Uffd backend must be accepted and propagated.
419+ let body = r#"{
420+ "snapshot_path": "foo",
421+ "mem_backend": {
422+ "backend_path": "bar",
423+ "backend_type": "Uffd",
424+ "use_memfd": true
425+ }
426+ }"# ;
427+ let expected_config = LoadSnapshotParams {
428+ snapshot_path : PathBuf :: from ( "foo" ) ,
429+ mem_backend : MemBackendConfig {
430+ backend_path : PathBuf :: from ( "bar" ) ,
431+ backend_type : MemBackendType :: Uffd ,
432+ use_memfd : true ,
433+ } ,
434+ track_dirty_pages : false ,
435+ resume_vm : false ,
436+ network_overrides : vec ! [ ] ,
437+ clock_realtime : false ,
438+ } ;
439+ let mut parsed_request = parse_put_snapshot ( & Body :: new ( body) , Some ( "load" ) ) . unwrap ( ) ;
440+ assert ! ( parsed_request. parsing_info( ) . take_deprecation_message( ) . is_none( ) ) ;
441+ assert_eq ! (
442+ vmm_action_from_request( parsed_request) ,
443+ VmmAction :: LoadSnapshot ( expected_config)
444+ ) ;
445+
446+ // use_memfd=true with File backend must be rejected.
447+ let body = r#"{
448+ "snapshot_path": "foo",
449+ "mem_backend": {
450+ "backend_path": "bar",
451+ "backend_type": "File",
452+ "use_memfd": true
453+ }
454+ }"# ;
455+ parse_put_snapshot ( & Body :: new ( body) , Some ( "load" ) ) . unwrap_err ( ) ;
404456 }
405457
406458 #[ test]
0 commit comments