From 06371af4fada212ec2596aeaffa233d7968c61d0 Mon Sep 17 00:00:00 2001 From: Shintaro Kawamura Date: Tue, 7 Mar 2023 14:55:36 +0900 Subject: [PATCH] swap: vmm-swap in concurrently A page fault handling may be executed concurrently during swapping in. This is the first step of vmm-swap in optimization. At the last step (https://crrev.com/c/4317028), the background thread executes swapping in. BUG=b:265606668 TEST=cargo test -p swap Change-Id: I42ec6b75485c31c9db26c22aa115b50288951b06 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4314185 Reviewed-by: Daniel Verkamp Reviewed-by: David Stevens Commit-Queue: Shin Kawamura --- swap/src/lib.rs | 76 ++++++++++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/swap/src/lib.rs b/swap/src/lib.rs index 293dd157b4..7d35b049ff 100644 --- a/swap/src/lib.rs +++ b/swap/src/lib.rs @@ -104,6 +104,10 @@ impl From<&SwapState> for State { direction: SwapDirection::Out, .. } => State::SwapOutInProgress, + SwapState::InProgress { + direction: SwapDirection::In, + .. + } => State::SwapInInProgress, SwapState::SwapOutCompleted => State::Active, SwapState::Failed => State::Failed, } @@ -547,29 +551,9 @@ fn start_monitoring<'a>( Ok(page_hander) } -fn disable_monitoring( - mut page_handler: PageHandler, - uffd_list: &UffdList, - guest_memory: &GuestMemory, -) -> anyhow::Result { - let mut num_pages = 0; - loop { - let pages = page_handler - .swap_in(uffd_list.main_uffd(), MAX_SWAP_CHUNK_SIZE) - .context("unregister all regions")?; - if pages == 0 { - break; - } - num_pages += pages; - } - let regions = regions_from_guest_memory(guest_memory); - unregister_regions(®ions, uffd_list.get_list()).context("unregister regions")?; - Ok(num_pages) -} - enum SwapDirection { Out, - // TODO(b/265606668): Add `In` to swap-in concurrently. + In, } enum SwapState { @@ -642,6 +626,28 @@ fn monitor_process( state = SwapState::SwapOutCompleted; } } + // TODO(b/265606668): execute swap-in on a background thread. + SwapDirection::In => { + let num_pages = page_handler + .swap_in(uffd_list.main_uffd(), MAX_SWAP_CHUNK_SIZE) + .context("swap in")?; + state_transition.pages += num_pages; + state_transition.time_ms = started_time.elapsed().as_millis(); + if num_pages == 0 { + info!( + "swap in all {} pages in {} ms.", + state_transition.pages, state_transition.time_ms + ); + page_handler_opt = None; + let regions = regions_from_guest_memory(&guest_memory); + unregister_regions(®ions, uffd_list.get_list()) + .context("unregister regions")?; + // Truncate the swap file to hold minimum resources while disabled. + swap_file.set_len(0).context("clear swap file")?; + info!("vmm-swap is disabled."); + state = SwapState::Disabled; + } + } } continue; } @@ -811,23 +817,21 @@ fn monitor_process( } => { info!("swap out is aborted."); } + SwapState::InProgress { + direction: SwapDirection::In, + .. + } => { + info!("swap in is in progress."); + continue; + } _ => {} } - if let Some(page_handler) = page_handler_opt.take() { - let t0 = std::time::Instant::now(); - state_transition.pages = - disable_monitoring(page_handler, &uffd_list, &guest_memory)?; - state_transition.time_ms = t0.elapsed().as_millis(); - info!( - "swap in all {} pages in {} ms. swap disabled.", - state_transition.pages, state_transition.time_ms - ); - // Truncate the swap file to hold minimum resources while disabled. - swap_file.set_len(0).context("clear swap file")?; - state = SwapState::Disabled; - } else { - error!("swap is already disabled."); - } + state = SwapState::InProgress { + direction: SwapDirection::In, + started_time: std::time::Instant::now(), + }; + state_transition = StateTransition::default(); + info!("start swapping in."); } Command::Exit => { break 'wait;