mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
block: Execute synchronous block requests positionally
Request::execute seeked the disk to the request sector and then read or wrote sequentially through the cursor. Walk a running offset with read_exact_at and write_all_at instead, and flush with fsync, so the bound becomes FileExt and FileSync rather than Seek, Read, and Write. The seek step is gone, so drop the now unused ExecuteError::Seek. Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
committed by
Rob Bradford
parent
06cad2cdcd
commit
15b59fdd9f
@@ -10,8 +10,8 @@
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use std::mem;
|
||||
use std::os::unix::fs::FileExt;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
|
||||
@@ -29,6 +29,7 @@ use vm_memory::{
|
||||
};
|
||||
use vm_virtio::AccessPlatform;
|
||||
use vm_virtio::checked_descriptor::DescriptorChainExt;
|
||||
use vmm_sys_util::file_traits::FileSync;
|
||||
|
||||
use crate::async_io::{
|
||||
AsyncIo, AsyncIoCompletion, AsyncIoOperation, GuestMemoryTarget, OwnedIoBuffer,
|
||||
@@ -171,7 +172,7 @@ impl Request {
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
pub fn execute<T: Seek + Read + Write, B: Bitmap + 'static>(
|
||||
pub fn execute<T: FileExt + FileSync, B: Bitmap + 'static>(
|
||||
&self,
|
||||
disk: &mut T,
|
||||
disk_nsectors: u64,
|
||||
@@ -180,32 +181,35 @@ impl Request {
|
||||
) -> Result<u32, ExecuteError> {
|
||||
self.check_data_bounds(disk_nsectors)?;
|
||||
|
||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||
.map_err(ExecuteError::Seek)?;
|
||||
let mut offset = self.sector << SECTOR_SHIFT;
|
||||
let mut len = 0;
|
||||
for (data_addr, data_len) in &self.data_descriptors {
|
||||
match self.request_type {
|
||||
RequestType::In => {
|
||||
let mut buf = vec![0u8; *data_len as usize];
|
||||
disk.read_exact(&mut buf).map_err(ExecuteError::ReadExact)?;
|
||||
disk.read_exact_at(&mut buf, offset)
|
||||
.map_err(ExecuteError::ReadExact)?;
|
||||
mem.read_exact_volatile_from(
|
||||
*data_addr,
|
||||
&mut buf.as_slice(),
|
||||
*data_len as usize,
|
||||
)
|
||||
.map_err(ExecuteError::Read)?;
|
||||
offset += u64::from(*data_len);
|
||||
len += data_len;
|
||||
}
|
||||
RequestType::Out => {
|
||||
let mut buf: Vec<u8> = Vec::new();
|
||||
mem.write_all_volatile_to(*data_addr, &mut buf, *data_len as usize)
|
||||
.map_err(ExecuteError::Write)?;
|
||||
disk.write_all(&buf).map_err(ExecuteError::WriteAll)?;
|
||||
disk.write_all_at(&buf, offset)
|
||||
.map_err(ExecuteError::WriteAll)?;
|
||||
if !self.writeback {
|
||||
disk.flush().map_err(ExecuteError::Flush)?;
|
||||
disk.fsync().map_err(ExecuteError::Flush)?;
|
||||
}
|
||||
offset += u64::from(*data_len);
|
||||
}
|
||||
RequestType::Flush => disk.flush().map_err(ExecuteError::Flush)?,
|
||||
RequestType::Flush => disk.fsync().map_err(ExecuteError::Flush)?,
|
||||
RequestType::GetDeviceId => {
|
||||
if (*data_len as usize) < serial.len() {
|
||||
return Err(ExecuteError::BadRequest(Error::InvalidOffset));
|
||||
|
||||
@@ -125,8 +125,6 @@ pub enum ExecuteError {
|
||||
ReadExact(#[source] io::Error),
|
||||
#[error("Can't execute an operation other than `read` or `get_id` on a read-only device")]
|
||||
ReadOnly,
|
||||
#[error("Failed to seek")]
|
||||
Seek(#[source] io::Error),
|
||||
#[error("Failed to write")]
|
||||
Write(#[source] GuestMemoryError),
|
||||
#[error("Failed to write_all")]
|
||||
@@ -161,7 +159,6 @@ impl ExecuteError {
|
||||
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::ReadExact(_) => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::ReadOnly => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::WriteAll(_) => VIRTIO_BLK_S_IOERR,
|
||||
ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP,
|
||||
|
||||
Reference in New Issue
Block a user