mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 17:44:10 +00:00
Support --pmem-ext2 option
BUG=b:329359333 TEST=run crosvm with `--pmem-ext2 /path/to/crosvm/ext2/src/` Change-Id: Ifd655bd533f637d6c475494c74dbfd544edd0b70 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5439074 Commit-Queue: Keiichi Watanabe <keiichiw@chromium.org> Reviewed-by: Junichi Uekawa <uekawa@chromium.org>
This commit is contained in:
parent
28847f9303
commit
c9f4ad0da9
7 changed files with 110 additions and 4 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -805,6 +805,7 @@ dependencies = [
|
|||
"disk",
|
||||
"document-features",
|
||||
"enumn",
|
||||
"ext2",
|
||||
"futures",
|
||||
"gdbstub",
|
||||
"gdbstub_arch",
|
||||
|
|
|
@ -451,6 +451,7 @@ devices = { path = "devices" }
|
|||
disk = { path = "disk" }
|
||||
document-features = { version = "0.2", optional = true }
|
||||
enumn = "0.1.0"
|
||||
ext2 = { path = "ext2" }
|
||||
gdbstub = { version = "0.7.0", optional = true }
|
||||
gdbstub_arch = { version = "0.3.0", optional = true }
|
||||
rutabaga_gfx = { path = "rutabaga_gfx"}
|
||||
|
|
|
@ -371,7 +371,7 @@ struct PmemSnapshot {
|
|||
impl Pmem {
|
||||
pub fn new(
|
||||
base_features: u64,
|
||||
disk_image: File,
|
||||
disk_image: Option<File>,
|
||||
mapping_address: GuestAddress,
|
||||
mapping_arena_slot: MemSlot,
|
||||
mapping_size: u64,
|
||||
|
@ -391,7 +391,7 @@ impl Pmem {
|
|||
Ok(Pmem {
|
||||
worker_thread: None,
|
||||
features: avail_features,
|
||||
disk_image: Some(disk_image),
|
||||
disk_image,
|
||||
mapping_address,
|
||||
mapping_arena_slot,
|
||||
mapping_size,
|
||||
|
|
|
@ -94,6 +94,7 @@ use crate::crosvm::config::HypervisorKind;
|
|||
use crate::crosvm::config::InputDeviceOption;
|
||||
use crate::crosvm::config::IrqChipKind;
|
||||
use crate::crosvm::config::MemOptions;
|
||||
use crate::crosvm::config::PmemExt2Option;
|
||||
use crate::crosvm::config::TouchDeviceOption;
|
||||
use crate::crosvm::config::VhostUserFrontendOption;
|
||||
use crate::crosvm::config::VhostUserFsOption;
|
||||
|
@ -1837,6 +1838,12 @@ pub struct RunCommand {
|
|||
/// path to a disk image
|
||||
pmem_device: Vec<DiskOption>,
|
||||
|
||||
#[argh(option, arg_name = "PATH")]
|
||||
#[serde(default)]
|
||||
#[merge(strategy = append)]
|
||||
/// (EXPERIMENTAL): construct an ext2 file system on a pmem device from the given directory
|
||||
pub pmem_ext2: Vec<PmemExt2Option>,
|
||||
|
||||
#[cfg(feature = "process-invariants")]
|
||||
#[argh(option, arg_name = "PATH")]
|
||||
#[serde(skip)] // TODO(b/255223604)
|
||||
|
@ -2891,6 +2898,8 @@ impl TryFrom<RunCommand> for super::config::Config {
|
|||
}
|
||||
}
|
||||
|
||||
cfg.pmem_ext2 = cmd.pmem_ext2;
|
||||
|
||||
#[cfg(feature = "pvclock")]
|
||||
{
|
||||
cfg.pvclock = cmd.pvclock.unwrap_or_default();
|
||||
|
|
|
@ -386,6 +386,12 @@ pub struct FileBackedMappingParameters {
|
|||
pub align: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq, serde_keyvalue::FromKeyValues)]
|
||||
#[serde(deny_unknown_fields, rename_all = "kebab-case")]
|
||||
pub struct PmemExt2Option {
|
||||
pub path: PathBuf,
|
||||
}
|
||||
|
||||
fn parse_hex_or_decimal(maybe_hex_string: &str) -> Result<u64, String> {
|
||||
// Parse string starting with 0x as hex and others as numbers.
|
||||
if let Some(hex_string) = maybe_hex_string.strip_prefix("0x") {
|
||||
|
@ -795,6 +801,7 @@ pub struct Config {
|
|||
#[cfg(feature = "plugin")]
|
||||
pub plugin_mounts: Vec<crate::crosvm::plugin::BindMount>,
|
||||
pub plugin_root: Option<PathBuf>,
|
||||
pub pmem_ext2: Vec<PmemExt2Option>,
|
||||
pub pmems: Vec<PmemOption>,
|
||||
#[cfg(feature = "process-invariants")]
|
||||
pub process_invariants_data_handle: Option<u64>,
|
||||
|
@ -1016,6 +1023,7 @@ impl Default for Config {
|
|||
#[cfg(feature = "plugin")]
|
||||
plugin_mounts: Vec::new(),
|
||||
plugin_root: None,
|
||||
pmem_ext2: Vec::new(),
|
||||
pmems: Vec::new(),
|
||||
#[cfg(feature = "process-invariants")]
|
||||
process_invariants_data_handle: None,
|
||||
|
@ -2408,4 +2416,19 @@ mod tests {
|
|||
.unwrap_err()
|
||||
.contains("swap-interval parameter can only be set for writable pmem device"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_pmem_ext2() {
|
||||
let config: Config = crate::crosvm::cmdline::RunCommand::from_args(
|
||||
&[],
|
||||
&["--pmem-ext2", "/path/to/dir", "/dev/null"],
|
||||
)
|
||||
.unwrap()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
let opt = config.pmem_ext2.first().unwrap();
|
||||
|
||||
assert_eq!(opt.path, PathBuf::from("/path/to/dir"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -403,6 +403,19 @@ fn create_virtio_devices(
|
|||
)?);
|
||||
}
|
||||
|
||||
for (index, pmem_ext2) in cfg.pmem_ext2.iter().enumerate() {
|
||||
let pmem_device_tube = pmem_device_tubes.remove(0);
|
||||
devs.push(create_pmem_ext2_device(
|
||||
cfg.protection_type,
|
||||
&cfg.jail_config,
|
||||
vm,
|
||||
resources,
|
||||
pmem_ext2,
|
||||
index,
|
||||
pmem_device_tube,
|
||||
)?);
|
||||
}
|
||||
|
||||
if cfg.rng {
|
||||
devs.push(create_rng_device(cfg.protection_type, &cfg.jail_config)?);
|
||||
}
|
||||
|
@ -1803,7 +1816,7 @@ where
|
|||
}
|
||||
|
||||
let mut pmem_device_tubes = Vec::new();
|
||||
let pmem_count = cfg.pmems.len();
|
||||
let pmem_count = cfg.pmems.len() + cfg.pmem_ext2.len();
|
||||
for _ in 0..pmem_count {
|
||||
let (pmem_host_tube, pmem_device_tube) = Tube::pair().context("failed to create tube")?;
|
||||
pmem_device_tubes.push(pmem_device_tube);
|
||||
|
|
|
@ -88,6 +88,7 @@ use sync::Mutex;
|
|||
use vm_control::api::VmMemoryClient;
|
||||
use vm_memory::GuestAddress;
|
||||
|
||||
use crate::crosvm::config::PmemExt2Option;
|
||||
use crate::crosvm::config::PmemOption;
|
||||
use crate::crosvm::config::VhostUserFrontendOption;
|
||||
use crate::crosvm::config::VhostUserFsOption;
|
||||
|
@ -1169,7 +1170,7 @@ pub fn create_pmem_device(
|
|||
|
||||
let dev = virtio::Pmem::new(
|
||||
virtio::base_features(protection_type),
|
||||
fd,
|
||||
Some(fd),
|
||||
GuestAddress(mapping_address),
|
||||
slot,
|
||||
arena_size,
|
||||
|
@ -1185,6 +1186,64 @@ pub fn create_pmem_device(
|
|||
})
|
||||
}
|
||||
|
||||
pub fn create_pmem_ext2_device(
|
||||
protection_type: ProtectionType,
|
||||
jail_config: &Option<JailConfig>,
|
||||
vm: &mut impl Vm,
|
||||
resources: &mut SystemAllocator,
|
||||
opts: &PmemExt2Option,
|
||||
index: usize,
|
||||
pmem_device_tube: Tube,
|
||||
) -> DeviceResult {
|
||||
let cfg = ext2::Config {
|
||||
inodes_per_group: 4096,
|
||||
blocks_per_group: 1024,
|
||||
};
|
||||
let arena = ext2::create_ext2_region(&cfg, Some(opts.path.as_path()))?;
|
||||
let arena_size = arena.size() as u64;
|
||||
|
||||
let mapping_address = resources
|
||||
.allocate_mmio(
|
||||
arena_size,
|
||||
Alloc::PmemDevice(index),
|
||||
format!("pmem_ext2_image_{}", index),
|
||||
AllocOptions::new()
|
||||
.top_down(true)
|
||||
.prefetchable(true)
|
||||
// 2MB alignment for DAX
|
||||
// cf. https://docs.pmem.io/persistent-memory/getting-started-guide/creating-development-environments/linux-environments/advanced-topics/i-o-alignment-considerations#verifying-io-alignment
|
||||
.align(2 * 1024 * 1024),
|
||||
)
|
||||
.context("failed to allocate memory for pmem device")?;
|
||||
|
||||
let slot = vm
|
||||
.add_memory_region(
|
||||
GuestAddress(mapping_address),
|
||||
Box::new(arena),
|
||||
/* read_only= */ true,
|
||||
/* log_dirty_pages= */ false,
|
||||
MemCacheType::CacheCoherent,
|
||||
)
|
||||
.context("failed to add pmem device memory")?;
|
||||
|
||||
let dev = virtio::Pmem::new(
|
||||
virtio::base_features(protection_type),
|
||||
None,
|
||||
GuestAddress(mapping_address),
|
||||
slot,
|
||||
arena_size,
|
||||
pmem_device_tube,
|
||||
/* swap_interval= */ None,
|
||||
/* mapping_writable= */ false,
|
||||
)
|
||||
.context("failed to create pmem device")?;
|
||||
|
||||
Ok(VirtioDeviceStub {
|
||||
dev: Box::new(dev) as Box<dyn VirtioDevice>,
|
||||
jail: simple_jail(jail_config, "pmem_device")?,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_anonymous_file<P: AsRef<Path>>(path: P, size: u64) -> Result<File> {
|
||||
let file_name = path
|
||||
.as_ref()
|
||||
|
|
Loading…
Reference in a new issue