pub struct PageHandler<'a> {
    ctx: Mutex<PageHandleContext<'a>>,
    channel: Arc<Channel<MoveToStaging>>,
}
Expand description

PageHandler manages the page states of multiple regions.

Handles multiple events derived from userfaultfd and swap out requests. All the addresses and sizes in bytes are converted to page id internally.

Fields§

§ctx: Mutex<PageHandleContext<'a>>§channel: Arc<Channel<MoveToStaging>>

Implementations§

source§

impl<'a> PageHandler<'a>

source

pub fn create( swap_file: &'a File, staging_shmem: &'a SharedMemory, address_ranges: &[Range<usize>], stating_move_context: Arc<Channel<MoveToStaging>> ) -> Result<Self>

Creates PageHandler for the given region.

If any of regions overlaps, this returns Error::RegionOverlap.

§Arguments
  • swap_file - The swap file.
  • staging_shmem - The staging memory. It must have enough size to hold guest memory. Otherwise monitor process crashes on creating a mmap.
  • address_ranges - The list of address range of the regions. the start address must align with page. the size must be multiple of pagesize.
source

fn find_region(regions: &mut [Region], page_idx: usize) -> Option<&mut Region>

source

pub fn handle_page_fault( &self, uffd: &Userfaultfd, address: usize ) -> Result<()>

Fills the faulted page with zero if the page is not initialized, with the content in the swap file if the page is swapped out.

§Arguments
  • uffd - the reference to the Userfaultfd for the faulting process.
  • address - the address that triggered the page fault.
source

pub fn handle_page_remove( &self, start_addr: usize, end_addr: usize ) -> Result<()>

Clear the internal state for the pages.

When pages are removed by madvise with MADV_DONTNEED or MADV_REMOVE, userfaultfd notifies the event as UFFD_EVENT_REMOVE. This handles the remove event.

In crosvm, balloon frees the guest memory and cause UFFD_EVENT_REMOVE.

§Arguments
  • start_addr - the head address of the memory area to be freed.
  • end_addr - the end address of the memory area to be freed. UFFD_EVENT_REMOVE tells the head address of the next memory area of the freed area. (i.e. the exact tail address of the memory area is end_addr - 1.)
source

pub unsafe fn move_to_staging<T>( &self, base_addr: usize, memfd: &T, base_offset: u64 ) -> Result<usize>
where T: AsRawDescriptor,

Move active pages in the memory region to the staging memory.

It only moves active contents in the guest memory to the swap file and skips empty pages (e.g. pages not touched, freed by balloon) using lseek(2) + SEEK_HOLE/DATA.

Returns the count of moved out pages.

§Arguments
  • base_addr - the head address of the memory region.
  • memfd - the file descriptor of the memfd backing the guest memory region.
  • base_offset - the offset of the memory region in the memfd.
§Safety

The region must have been registered to all userfaultfd of processes which may touch the region.

The memory must be protected not to be updated while moving.

The page fault events for the region from the userfaultfd must be handled by Self::handle_page_fault().

Must call Channel::wait_complete() to wait all the copy operation complete within the memory protection period.

source

pub fn swap_out(&self, max_size: usize) -> Result<usize>

Write a chunk of consecutive pages in the staging memory to the swap file.

If there is no active pages in the staging memory, this returns Ok(0).

The pages in guest memory have been moved to staging memory by Self::move_to_staging().

Returns the count of swapped out pages.

Even if swap_out fails on any internal steps, it does not break the page state management and PageHandler can continue working with a little pages leaking in staging memory or swap file. The leaked pages are removed when vmm-swap is disabled and PageHandler is dropped.

§Arguments
  • max_size - the upper limit of the chunk size to write into the swap file at once. The chunk is splitted if it is bigger than max_size.
source

pub fn start_swap_in(&'a self) -> SwapInContext<'a>

Create a new SwapInContext.

source

pub fn start_trim(&'a self) -> TrimContext<'a>

Create a new TrimContext.

source

fn compute_copied_from_file_pages(&self) -> usize

Returns count of pages copied from vmm-swap file to the guest memory.

source

fn compute_copied_from_staging_pages(&self) -> usize

Returns count of pages copied from staging memory to the guest memory.

source

fn compute_zeroed_pages(&self) -> usize

Returns count of pages initialized with zero.

source

fn compute_redundant_pages(&self) -> usize

Returns count of pages which were already initialized on page faults.

source

fn compute_staging_pages(&self) -> usize

Returns count of pages present in the staging memory.

source

fn compute_swap_pages(&self) -> usize

Returns count of pages present in the swap files.

source

pub fn load_metrics(&self, metrics: &mut SwapMetrics)

Fill SwapMetrics with page handler metrics.

Auto Trait Implementations§

§

impl<'a> RefUnwindSafe for PageHandler<'a>

§

impl<'a> Send for PageHandler<'a>

§

impl<'a> Sync for PageHandler<'a>

§

impl<'a> Unpin for PageHandler<'a>

§

impl<'a> UnwindSafe for PageHandler<'a>

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.