From 9da4030ab06362a64ea76d72837c1d800fdeb80d Mon Sep 17 00:00:00 2001 From: Noah Gold Date: Tue, 12 Apr 2022 21:36:24 -0700 Subject: [PATCH] cros_async: use portable enum for fallocate modes fallocate modes were previously unix specific constants, which won't work after we add support for Winodws. Here, we've put a generic abstraction in place so that each platform can implement the details as appropriate. Thanks to acourbot@ for suggesting the splits in this series. BUG=b:213147081 TEST=see final CL in series. Change-Id: I822ad6c4a26eea716482029e8a6c0489aa72c595 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3583613 Reviewed-by: Alexandre Courbot Tested-by: kokoro Commit-Queue: Noah Gold --- cros_async/src/io_ext.rs | 25 ++++++++++++++++++++++++- cros_async/src/lib.rs | 4 ++-- cros_async/src/poll_source.rs | 9 +++++++-- cros_async/src/uring_source.rs | 8 +++++--- disk/src/disk.rs | 14 +++----------- 5 files changed, 41 insertions(+), 19 deletions(-) diff --git a/cros_async/src/io_ext.rs b/cros_async/src/io_ext.rs index d48ad10d20..b1486b1083 100644 --- a/cros_async/src/io_ext.rs +++ b/cros_async/src/io_ext.rs @@ -77,6 +77,29 @@ pub trait ReadAsync { async fn read_u64(&self) -> Result; } +pub enum AllocateMode { + #[cfg(unix)] + Default, + PunchHole, + ZeroRange, +} + +// This assume we always want KEEP_SIZE +#[cfg(unix)] +impl From for u32 { + fn from(value: AllocateMode) -> Self { + match value { + AllocateMode::Default => 0, + AllocateMode::PunchHole => { + (libc::FALLOC_FL_PUNCH_HOLE | libc::FALLOC_FL_KEEP_SIZE) as u32 + } + AllocateMode::ZeroRange => { + (libc::FALLOC_FL_ZERO_RANGE | libc::FALLOC_FL_KEEP_SIZE) as u32 + } + } + } +} + /// Ergonomic methods for async writes. #[async_trait(?Send)] pub trait WriteAsync { @@ -96,7 +119,7 @@ pub trait WriteAsync { ) -> Result; /// See `fallocate(2)`. Note this op is synchronous when using the Polled backend. - async fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> Result<()>; + async fn fallocate(&self, file_offset: u64, len: u64, mode: AllocateMode) -> Result<()>; /// Sync all completed write operations to the backing storage. async fn fsync(&self) -> Result<()>; diff --git a/cros_async/src/lib.rs b/cros_async/src/lib.rs index e266f232b2..5afc57a473 100644 --- a/cros_async/src/lib.rs +++ b/cros_async/src/lib.rs @@ -83,8 +83,8 @@ pub use event::EventAsync; pub use executor::Executor; pub use fd_executor::FdExecutor; pub use io_ext::{ - AsyncWrapper, Error as AsyncError, IntoAsync, IoSourceExt, ReadAsync, Result as AsyncResult, - WriteAsync, + AllocateMode, AsyncWrapper, Error as AsyncError, IntoAsync, IoSourceExt, ReadAsync, + Result as AsyncResult, WriteAsync, }; pub use mem::{BackingMemory, MemRegion}; pub use poll_source::PollSource; diff --git a/cros_async/src/poll_source.rs b/cros_async/src/poll_source.rs index 26866b0bf5..3477041dd9 100644 --- a/cros_async/src/poll_source.rs +++ b/cros_async/src/poll_source.rs @@ -17,6 +17,8 @@ use data_model::VolatileSlice; use remain::sorted; use thiserror::Error as ThisError; +use crate::AllocateMode; + use super::{ fd_executor::{ FdExecutor, RegisteredSource, {self}, @@ -317,7 +319,7 @@ impl WriteAsync for PollSource { } /// See `fallocate(2)` for details. - async fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> AsyncResult<()> { + async fn fallocate(&self, file_offset: u64, len: u64, mode: AllocateMode) -> AsyncResult<()> { let ret = unsafe { libc::fallocate64( self.as_raw_fd(), @@ -419,7 +421,10 @@ mod tests { .open(&file_path) .unwrap(); let source = PollSource::new(f, ex).unwrap(); - source.fallocate(0, 4096, 0).await.unwrap(); + source + .fallocate(0, 4096, AllocateMode::Default) + .await + .unwrap(); let meta_data = std::fs::metadata(&file_path).unwrap(); assert_eq!(meta_data.len(), 4096); diff --git a/cros_async/src/uring_source.rs b/cros_async/src/uring_source.rs index 9d8525eae5..bd8bd4e2c2 100644 --- a/cros_async/src/uring_source.rs +++ b/cros_async/src/uring_source.rs @@ -12,6 +12,8 @@ use std::{ use async_trait::async_trait; +use crate::AllocateMode; + use super::{ mem::{BackingMemory, MemRegion, VecIoWrapper}, uring_executor::{Error, RegisteredSource, Result, URingExecutor}, @@ -166,10 +168,10 @@ impl super::WriteAsync for UringSource { } /// See `fallocate(2)`. Note this op is synchronous when using the Polled backend. - async fn fallocate(&self, file_offset: u64, len: u64, mode: u32) -> AsyncResult<()> { + async fn fallocate(&self, file_offset: u64, len: u64, mode: AllocateMode) -> AsyncResult<()> { let op = self .registered_source - .start_fallocate(file_offset, len, mode)?; + .start_fallocate(file_offset, len, mode.into())?; let _ = op.await?; Ok(()) } @@ -507,7 +509,7 @@ mod tests { .open(&file_path) .unwrap(); let source = UringSource::new(f, ex).unwrap(); - if let Err(e) = source.fallocate(0, 4096, 0).await { + if let Err(e) = source.fallocate(0, 4096, AllocateMode::Default).await { match e { super::super::io_ext::Error::Uring( super::super::uring_executor::Error::Io(io_err), diff --git a/disk/src/disk.rs b/disk/src/disk.rs index 9a8aaf66cc..4e4a69e8bd 100644 --- a/disk/src/disk.rs +++ b/disk/src/disk.rs @@ -14,7 +14,7 @@ use base::{ get_filesystem_type, info, AsRawDescriptors, FileAllocate, FileReadWriteAtVolatile, FileSetLen, FileSync, PunchHole, WriteZeroesAt, }; -use cros_async::Executor; +use cros_async::{AllocateMode, Executor}; use remain::sorted; use thiserror::Error as ThisError; use vm_memory::GuestMemory; @@ -372,11 +372,7 @@ impl AsyncDisk for SingleFileDisk { async fn punch_hole(&self, file_offset: u64, length: u64) -> Result<()> { self.inner - .fallocate( - file_offset, - length, - (libc::FALLOC_FL_PUNCH_HOLE | libc::FALLOC_FL_KEEP_SIZE) as u32, - ) + .fallocate(file_offset, length, AllocateMode::ZeroRange) .await .map_err(Error::Fallocate) } @@ -384,11 +380,7 @@ impl AsyncDisk for SingleFileDisk { async fn write_zeroes_at(&self, file_offset: u64, length: u64) -> Result<()> { if self .inner - .fallocate( - file_offset, - length, - (libc::FALLOC_FL_ZERO_RANGE | libc::FALLOC_FL_KEEP_SIZE) as u32, - ) + .fallocate(file_offset, length, AllocateMode::ZeroRange) .await .is_ok() {