mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: Add owned fixed VHD io_uring I/O path
Add the new AsyncIo apis to fixed_vhd_async. Later commits update callers to use them and remove their unsound counterparts that take iovecs. While doing this, make the owned path validate offset plus length instead of only the starting offset, so requests that extend past the VHD size are rejected. Signed-off-by: Dylan Reid <dgreid@fb.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
// Copyright © 2021 Intel Corporation
|
||||
//
|
||||
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::os::unix::io::RawFd;
|
||||
@@ -7,7 +9,7 @@ use std::os::unix::io::RawFd;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
use crate::BatchRequest;
|
||||
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult};
|
||||
use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult};
|
||||
use crate::error::BlockResult;
|
||||
use crate::raw_async::RawFileAsync;
|
||||
|
||||
@@ -25,6 +27,37 @@ impl FixedVhdAsync {
|
||||
size,
|
||||
})
|
||||
}
|
||||
|
||||
fn validate_operation_bounds(&self, op: &AsyncIoOperation) -> AsyncIoResult<()> {
|
||||
let offset = u64::try_from(op.offset()).map_err(|_| self.bounds_error(op))?;
|
||||
let len = u64::try_from(op.total_len()).map_err(|_| self.bounds_error(op))?;
|
||||
let end = offset
|
||||
.checked_add(len)
|
||||
.ok_or_else(|| self.bounds_error(op))?;
|
||||
|
||||
if end > self.size {
|
||||
return Err(self.bounds_error(op));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bounds_error(&self, op: &AsyncIoOperation) -> AsyncIoError {
|
||||
let error = std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidData,
|
||||
format!(
|
||||
"Invalid request offset {} and length {}, can't exceed file size {}",
|
||||
op.offset(),
|
||||
op.total_len(),
|
||||
self.size
|
||||
),
|
||||
);
|
||||
if op.is_read() {
|
||||
AsyncIoError::ReadVectored(error)
|
||||
} else {
|
||||
AsyncIoError::WriteVectored(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncIo for FixedVhdAsync {
|
||||
@@ -71,12 +104,17 @@ impl AsyncIo for FixedVhdAsync {
|
||||
.write_vectored(offset, iovecs, user_data)
|
||||
}
|
||||
|
||||
fn submit_data_operation(&mut self, op: AsyncIoOperation) -> AsyncIoResult<()> {
|
||||
self.validate_operation_bounds(&op)?;
|
||||
self.raw_file_async.submit_data_operation(op)
|
||||
}
|
||||
|
||||
fn fsync(&mut self, user_data: Option<u64>) -> AsyncIoResult<()> {
|
||||
self.raw_file_async.fsync(user_data)
|
||||
}
|
||||
|
||||
fn next_completed_request(&mut self) -> Option<(u64, i32)> {
|
||||
self.raw_file_async.next_completed_request()
|
||||
fn next_completion(&mut self) -> Option<AsyncIoCompletion> {
|
||||
self.raw_file_async.next_completion()
|
||||
}
|
||||
|
||||
fn punch_hole(&mut self, _offset: u64, _length: u64, _user_data: u64) -> AsyncIoResult<()> {
|
||||
@@ -98,4 +136,15 @@ impl AsyncIo for FixedVhdAsync {
|
||||
fn submit_batch_requests(&mut self, batch_request: &[BatchRequest]) -> AsyncIoResult<()> {
|
||||
self.raw_file_async.submit_batch_requests(batch_request)
|
||||
}
|
||||
|
||||
fn submit_batch_operations(
|
||||
&mut self,
|
||||
batch_request: Vec<AsyncIoOperation>,
|
||||
) -> AsyncIoResult<()> {
|
||||
for op in &batch_request {
|
||||
self.validate_operation_bounds(op)?;
|
||||
}
|
||||
|
||||
self.raw_file_async.submit_batch_operations(batch_request)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user