2022-11-07 08:12:05 +00:00
|
|
|
// Copyright 2022 The ChromiumOS Authors
|
|
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
|
|
// found in the LICENSE file.
|
|
|
|
|
|
|
|
//! Integration tests for vmm-swap feature
|
|
|
|
|
2023-05-11 05:16:00 +00:00
|
|
|
#[cfg(all(unix, feature = "enable"))]
|
2022-11-07 08:12:05 +00:00
|
|
|
mod common;
|
|
|
|
|
2023-05-11 05:16:00 +00:00
|
|
|
#[cfg(all(unix, feature = "enable"))]
|
2023-02-28 19:01:18 +00:00
|
|
|
mod test {
|
|
|
|
use base::pagesize;
|
|
|
|
use base::sys::wait_for_pid;
|
|
|
|
use base::AsRawDescriptor;
|
|
|
|
use base::FromRawDescriptor;
|
|
|
|
use base::IntoRawDescriptor;
|
|
|
|
use base::SafeDescriptor;
|
|
|
|
use base::Tube;
|
|
|
|
use swap::userfaultfd::register_regions;
|
|
|
|
use swap::userfaultfd::unregister_regions;
|
|
|
|
use swap::userfaultfd::Userfaultfd;
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-03-27 21:11:01 +00:00
|
|
|
use super::common::*;
|
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
pub fn register_region_skip_obsolete_process() {
|
|
|
|
let shm = create_shared_memory("test", 3 * pagesize());
|
2022-11-07 08:12:05 +00:00
|
|
|
let uffd = create_uffd_for_test();
|
2023-02-28 19:01:18 +00:00
|
|
|
let base_addr = shm.base_addr();
|
|
|
|
let regions = [base_addr..(base_addr + 3 * pagesize())];
|
|
|
|
let (tube_main, tube_child) = Tube::pair().unwrap();
|
|
|
|
let pid = unsafe { libc::fork() };
|
|
|
|
if pid == 0 {
|
|
|
|
// child process
|
|
|
|
let uffd = create_uffd_for_test();
|
|
|
|
tube_child
|
|
|
|
.send(&unsafe { SafeDescriptor::from_raw_descriptor(uffd.as_raw_descriptor()) })
|
|
|
|
.unwrap();
|
|
|
|
std::process::exit(0);
|
|
|
|
}
|
|
|
|
let uffd_descriptor = tube_main
|
|
|
|
.recv::<SafeDescriptor>()
|
|
|
|
.unwrap()
|
|
|
|
.into_raw_descriptor();
|
|
|
|
wait_for_pid(pid, 0).unwrap();
|
|
|
|
let uffd_child = unsafe { Userfaultfd::from_raw_descriptor(uffd_descriptor) };
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
let result = unsafe { register_regions(®ions, &[uffd, uffd_child]) };
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
// no error from ENOMEM
|
|
|
|
assert_eq!(result.is_ok(), true);
|
|
|
|
}
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
pub fn unregister_region_skip_obsolete_process() {
|
|
|
|
let shm = create_shared_memory("test", 3 * pagesize());
|
2022-11-07 08:12:05 +00:00
|
|
|
let uffd = create_uffd_for_test();
|
2023-02-28 19:01:18 +00:00
|
|
|
let base_addr = shm.base_addr();
|
|
|
|
let regions = [base_addr..(base_addr + 3 * pagesize())];
|
|
|
|
let (tube_main, tube_child) = Tube::pair().unwrap();
|
|
|
|
let pid = unsafe { libc::fork() };
|
|
|
|
if pid == 0 {
|
|
|
|
// child process
|
|
|
|
let uffd = create_uffd_for_test();
|
|
|
|
tube_child
|
|
|
|
.send(&unsafe { SafeDescriptor::from_raw_descriptor(uffd.as_raw_descriptor()) })
|
|
|
|
.unwrap();
|
|
|
|
tube_child.recv::<u8>().unwrap();
|
|
|
|
std::process::exit(0);
|
|
|
|
}
|
|
|
|
let uffd_descriptor = tube_main
|
|
|
|
.recv::<SafeDescriptor>()
|
|
|
|
.unwrap()
|
|
|
|
.into_raw_descriptor();
|
|
|
|
let uffd_child = unsafe { Userfaultfd::from_raw_descriptor(uffd_descriptor) };
|
|
|
|
let uffds = [uffd, uffd_child];
|
|
|
|
|
|
|
|
unsafe { register_regions(®ions, &uffds) }.unwrap();
|
|
|
|
tube_main.send(&0_u8).unwrap();
|
|
|
|
// wait until the child process die and the uffd_child become obsolete.
|
|
|
|
wait_for_pid(pid, 0).unwrap();
|
|
|
|
let result = unregister_regions(®ions, &uffds);
|
|
|
|
|
|
|
|
// no error from ENOMEM
|
|
|
|
assert_eq!(result.is_ok(), true);
|
2022-11-07 08:12:05 +00:00
|
|
|
}
|
2023-02-28 19:01:18 +00:00
|
|
|
}
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
fn main() {
|
|
|
|
let args = libtest_mimic::Arguments {
|
|
|
|
// Force single-threaded execution to allow safe use of libc::fork in these tests.
|
|
|
|
test_threads: Some(1),
|
|
|
|
..libtest_mimic::Arguments::from_args()
|
|
|
|
};
|
2022-11-07 08:12:05 +00:00
|
|
|
|
2023-02-28 19:01:18 +00:00
|
|
|
let tests = vec![
|
2023-05-11 05:16:00 +00:00
|
|
|
#[cfg(all(unix, feature = "enable"))]
|
2023-02-28 19:01:18 +00:00
|
|
|
libtest_mimic::Trial::test("register_region_skip_obsolete_process", move || {
|
|
|
|
test::register_region_skip_obsolete_process();
|
|
|
|
Ok(())
|
|
|
|
}),
|
2023-05-11 05:16:00 +00:00
|
|
|
#[cfg(all(unix, feature = "enable"))]
|
2023-02-28 19:01:18 +00:00
|
|
|
libtest_mimic::Trial::test("unregister_region_skip_obsolete_process", move || {
|
|
|
|
test::unregister_region_skip_obsolete_process();
|
|
|
|
Ok(())
|
|
|
|
}),
|
|
|
|
];
|
|
|
|
libtest_mimic::run(&args, tests).exit();
|
2022-11-07 08:12:05 +00:00
|
|
|
}
|