mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-25 13:23:08 +00:00
swap: merge PageHandler::add_region() into PageHandler::create()
Refactoring to make the codebase simple. BUG=b:260543132 TEST=cargo test -p swap Change-Id: If0f28e28f8678ee764867161910ae60c94a89f73 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4125178 Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Reviewed-by: David Stevens <stevensd@chromium.org> Commit-Queue: Shin Kawamura <kawasin@google.com>
This commit is contained in:
parent
7751813661
commit
2039d31bd3
1 changed files with 45 additions and 59 deletions
|
@ -81,21 +81,57 @@ pub struct PageHandler {
|
|||
impl PageHandler {
|
||||
/// Creates [PageHandler] for the given region.
|
||||
///
|
||||
/// If any of regions overlaps, this returns [Error::RegionOverlap].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `swap_dir` - path to the directory to create a swap file from.
|
||||
/// * `regions` - the list of the region. the start address must align with page. the size must
|
||||
/// be multiple of pagesize.
|
||||
pub fn create(swap_dir: &Path, regions: &[Range<usize>]) -> Result<Self> {
|
||||
let mut handler = Self {
|
||||
regions: Vec::new(),
|
||||
};
|
||||
/// * `address_ranges` - the list of address range of the regions. the start address must align
|
||||
/// with page. the size must be multiple of pagesize.
|
||||
pub fn create(swap_dir: &Path, address_ranges: &[Range<usize>]) -> Result<Self> {
|
||||
let mut regions: Vec<Region> = Vec::new();
|
||||
|
||||
for address_range in regions {
|
||||
handler.add_region(swap_dir, address_range)?;
|
||||
for address_range in address_ranges {
|
||||
let head_page_idx = addr_to_page_idx(address_range.start);
|
||||
let region_size = address_range.end - address_range.start;
|
||||
let num_of_pages = bytes_to_pages(region_size);
|
||||
|
||||
// find an overlaping region
|
||||
match regions.iter().position(|region| {
|
||||
if region.head_page_idx < head_page_idx {
|
||||
region.head_page_idx + region.file.num_pages() > head_page_idx
|
||||
} else {
|
||||
region.head_page_idx < head_page_idx + num_of_pages
|
||||
}
|
||||
}) {
|
||||
Some(i) => {
|
||||
let region = ®ions[i];
|
||||
|
||||
return Err(Error::RegionOverlap(
|
||||
address_range.clone(),
|
||||
page_idx_to_addr(region.head_page_idx)
|
||||
..(page_idx_to_addr(region.head_page_idx + region.file.num_pages())),
|
||||
));
|
||||
}
|
||||
None => {
|
||||
let base_addr = address_range.start;
|
||||
assert!(is_page_aligned(base_addr));
|
||||
assert!(is_page_aligned(region_size));
|
||||
|
||||
let file = SwapFile::new(swap_dir, num_of_pages)?;
|
||||
regions.push(Region {
|
||||
head_page_idx,
|
||||
file,
|
||||
copied_pages: 0,
|
||||
zeroed_pages: 0,
|
||||
redundant_pages: 0,
|
||||
swap_active: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(handler)
|
||||
Ok(Self { regions })
|
||||
}
|
||||
|
||||
fn find_region_position(&self, page_idx: usize) -> Option<usize> {
|
||||
|
@ -112,56 +148,6 @@ impl PageHandler {
|
|||
.map(|i| &mut self.regions[i])
|
||||
}
|
||||
|
||||
/// Create a new internal context to handle userfaultfd events and swap in/out request.
|
||||
///
|
||||
/// If the regions overlaps an existing region, it returns [Error::RegionOverlap].
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `swap_dir` - path to the directory to create a swap file from.
|
||||
/// * `address_range` - the range of the region. the start address must align with page. the
|
||||
/// size must be multiple of pagesize.
|
||||
fn add_region(&mut self, swap_dir: &Path, address_range: &Range<usize>) -> Result<()> {
|
||||
let head_page_idx = addr_to_page_idx(address_range.start);
|
||||
let region_size = address_range.end - address_range.start;
|
||||
let num_of_pages = bytes_to_pages(region_size);
|
||||
|
||||
// find an overlaping region
|
||||
match self.regions.iter().position(|region| {
|
||||
if region.head_page_idx < head_page_idx {
|
||||
region.head_page_idx + region.file.num_pages() > head_page_idx
|
||||
} else {
|
||||
region.head_page_idx < head_page_idx + num_of_pages
|
||||
}
|
||||
}) {
|
||||
Some(i) => {
|
||||
let region = &self.regions[i];
|
||||
|
||||
Err(Error::RegionOverlap(
|
||||
address_range.clone(),
|
||||
page_idx_to_addr(region.head_page_idx)
|
||||
..(page_idx_to_addr(region.head_page_idx + region.file.num_pages())),
|
||||
))
|
||||
}
|
||||
None => {
|
||||
let base_addr = address_range.start;
|
||||
assert!(is_page_aligned(base_addr));
|
||||
assert!(is_page_aligned(region_size));
|
||||
|
||||
let file = SwapFile::new(swap_dir, num_of_pages)?;
|
||||
self.regions.push(Region {
|
||||
head_page_idx,
|
||||
file,
|
||||
copied_pages: 0,
|
||||
zeroed_pages: 0,
|
||||
redundant_pages: 0,
|
||||
swap_active: false,
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn copy_all(
|
||||
uffd: &Userfaultfd,
|
||||
mut page_addr: usize,
|
||||
|
|
Loading…
Reference in a new issue