fs: Make DAX optional

We don't currently have it enabled anywhere but we still always allocate
PCI shared memory regions for it.  Instead make it optional and off by
default.  We can re-enable it on a per-device basis.

BUG=none
TEST=arc.PlayStore.vm

Change-Id: Icf122a561251a3e55757a9ffe4633b96adc4066d
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3168563
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Chirantan Ekbote <chirantan@chromium.org>
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Keiichi Watanabe <keiichiw@chromium.org>
This commit is contained in:
Chirantan Ekbote 2021-09-21 17:25:29 +09:00 committed by Commit Bot
parent b9917a22a3
commit 1b2d8dc856
3 changed files with 43 additions and 2 deletions

View file

@ -234,6 +234,7 @@ impl VirtioDevice for Fs {
}
let fs = self.fs.take().expect("missing file system implementation");
let use_dax = fs.cfg().use_dax;
let server = Arc::new(Server::new(fs));
let irq = Arc::new(interrupt);
@ -242,7 +243,7 @@ impl VirtioDevice for Fs {
// Set up shared memory for DAX.
// TODO(b/176129399): Remove cfg! once DAX is supported on ARM.
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) {
if cfg!(any(target_arch = "x86", target_arch = "x86_64")) && use_dax {
// Create the shared memory region now before we start processing requests.
let request = FsMappingRequest::AllocateSharedMemoryRegion(
self.pci_bar.as_ref().cloned().expect("No pci_bar"),
@ -301,6 +302,10 @@ impl VirtioDevice for Fs {
}
fn get_device_bars(&mut self, address: PciAddress) -> Vec<PciBarConfiguration> {
if self.fs.as_ref().map_or(false, |fs| !fs.cfg().use_dax) {
return vec![];
}
self.pci_bar = Some(Alloc::PciBar {
bus: address.bus,
dev: address.dev,
@ -317,6 +322,10 @@ impl VirtioDevice for Fs {
}
fn get_device_caps(&self) -> Vec<Box<dyn PciCapability>> {
if self.fs.as_ref().map_or(false, |fs| !fs.cfg().use_dax) {
return vec![];
}
vec![Box::new(VirtioPciShmCap::new(
PciCapabilityType::SharedMemoryConfig,
FS_BAR_NUM,

View file

@ -499,6 +499,17 @@ pub struct Config {
// CAP_FOWNER.
#[cfg(feature = "chromeos")]
pub privileged_quota_uids: Vec<libc::uid_t>,
/// Use DAX for shared files.
///
/// Enabling DAX can improve performance for frequently accessed files by mapping regions of the
/// file directly into the VM's memory region, allowing direct access with the cost of slightly
/// increased latency the first time the file is accessed. Additionally, since the mapping is
/// shared directly from the host kernel's file cache, enabling DAX can improve performance even
/// when the cache policy is `Never`.
///
/// The default value for this option is `false`.
pub use_dax: bool,
}
impl Default for Config {
@ -512,6 +523,7 @@ impl Default for Config {
ascii_casefold: false,
#[cfg(feature = "chromeos")]
privileged_quota_uids: Default::default(),
use_dax: false,
}
}
}
@ -625,6 +637,10 @@ impl PassthroughFs {
})
}
pub fn cfg(&self) -> &Config {
&self.cfg
}
pub fn keep_rds(&self) -> Vec<RawDescriptor> {
#[cfg_attr(not(feature = "chromeos"), allow(unused_mut))]
let mut keep_rds = vec![self.proc.as_raw_descriptor()];
@ -2481,6 +2497,10 @@ impl FileSystem for PassthroughFs {
prot: u32,
mapper: M,
) -> io::Result<()> {
if !self.cfg.use_dax {
return Err(io::Error::from_raw_os_error(libc::ENOSYS));
}
let read = prot & libc::PROT_READ as u32 != 0;
let write = prot & libc::PROT_WRITE as u32 != 0;
let mmap_flags = match (read, write) {
@ -2522,6 +2542,10 @@ impl FileSystem for PassthroughFs {
}
fn remove_mapping<M: Mapper>(&self, msgs: &[RemoveMappingOne], mapper: M) -> io::Result<()> {
if !self.cfg.use_dax {
return Err(io::Error::from_raw_os_error(libc::ENOSYS));
}
for RemoveMappingOne { moffset, len } in msgs {
mapper.unmap(*moffset, *len)?;
}

View file

@ -1569,6 +1569,13 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument::
shared_dir.fs_cfg.ascii_casefold = ascii_casefold;
shared_dir.p9_cfg.ascii_casefold = ascii_casefold;
}
"dax" => {
let use_dax = value.parse().map_err(|_| argument::Error::InvalidValue {
value: value.to_owned(),
expected: String::from("`dax` must be a boolean"),
})?;
shared_dir.fs_cfg.use_dax = use_dax;
}
_ => {
return Err(argument::Error::InvalidValue {
value: kind.to_owned(),
@ -2150,7 +2157,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
"Path to put the control socket. If PATH is a directory, a name will be generated."),
Argument::flag("disable-sandbox", "Run all devices in one, non-sandboxed process."),
Argument::value("cid", "CID", "Context ID for virtual sockets."),
Argument::value("shared-dir", "PATH:TAG[:type=TYPE:writeback=BOOL:timeout=SECONDS:uidmap=UIDMAP:gidmap=GIDMAP:cache=CACHE]",
Argument::value("shared-dir", "PATH:TAG[:type=TYPE:writeback=BOOL:timeout=SECONDS:uidmap=UIDMAP:gidmap=GIDMAP:cache=CACHE:dax=BOOL]",
"Colon-separated options for configuring a directory to be shared with the VM.
The first field is the directory to be shared and the second field is the tag that the VM can use to identify the device.
The remaining fields are key=value pairs that may appear in any order. Valid keys are:
@ -2160,6 +2167,7 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> {
cache=(never, auto, always) - Indicates whether the VM can cache the contents of the shared directory (default: auto). When set to \"auto\" and the type is \"fs\", the VM will use close-to-open consistency for file contents.
timeout=SECONDS - How long the VM should consider file attributes and directory entries to be valid (default: 5). If the VM has exclusive access to the directory, then this should be a large value. If the directory can be modified by other processes, then this should be 0.
writeback=BOOL - Indicates whether the VM can use writeback caching (default: false). This is only safe to do when the VM has exclusive access to the files in a directory. Additionally, the server should have read permission for all files as the VM may issue read requests even for files that are opened write-only.
dax=BOOL - Indicates whether DAX support should be enabled. Enabling DAX can improve performance for frequently accessed files by mapping regions of the file directory into the VM's memory, allowing direct access at the cost of slightly increased latency the first time the file is accessed. Since the mapping is shared directly from the host kernel's file cache, enabling DAX can improve performance even when the cache policy is \"Never\". The default value for this option is \"false\".
"),
Argument::value("seccomp-policy-dir", "PATH", "Path to seccomp .policy files."),
Argument::flag("seccomp-log-failures", "Instead of seccomp filter failures being fatal, they will be logged instead."),