diff --git a/block/src/io/request.rs b/block/src/io/request.rs index 643164606..dc9b43839 100644 --- a/block/src/io/request.rs +++ b/block/src/io/request.rs @@ -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( + pub fn execute( &self, disk: &mut T, disk_nsectors: u64, @@ -180,32 +181,35 @@ impl Request { ) -> Result { 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 = 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)); diff --git a/block/src/lib.rs b/block/src/lib.rs index 4788bcc83..6fd2d544a 100644 --- a/block/src/lib.rs +++ b/block/src/lib.rs @@ -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,