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 <acourbot@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Noah Gold <nkgold@google.com>
This commit is contained in:
Noah Gold 2022-04-12 21:36:24 -07:00 committed by Chromeos LUCI
parent 78ef113617
commit 9da4030ab0
5 changed files with 41 additions and 19 deletions

View file

@ -77,6 +77,29 @@ pub trait ReadAsync {
async fn read_u64(&self) -> Result<u64>;
}
pub enum AllocateMode {
#[cfg(unix)]
Default,
PunchHole,
ZeroRange,
}
// This assume we always want KEEP_SIZE
#[cfg(unix)]
impl From<AllocateMode> 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<usize>;
/// 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<()>;

View file

@ -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;

View file

@ -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<F: AsRawFd> WriteAsync for PollSource<F> {
}
/// 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);

View file

@ -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<F: AsRawFd> super::WriteAsync for UringSource<F> {
}
/// 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),

View file

@ -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()
{