block: Simplify AsyncAdaptor

It shouldn't be necessary to lock the file for the adaptor. This removes
two layers of indirection for QcowDiskSync and VhdxDiskSync.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
Wei Liu
2025-07-17 23:15:50 +00:00
committed by Bo Chen
parent 03b22a510d
commit 930a911862
4 changed files with 36 additions and 50 deletions
+19 -21
View File
@@ -39,7 +39,7 @@ use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
use std::os::linux::fs::MetadataExt; use std::os::linux::fs::MetadataExt;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::path::Path; use std::path::Path;
use std::sync::{Arc, MutexGuard}; use std::sync::Arc;
use std::time::Instant; use std::time::Instant;
use std::{cmp, result}; use std::{cmp, result};
@@ -646,10 +646,7 @@ pub fn block_io_uring_is_supported() -> bool {
} }
} }
pub trait AsyncAdaptor<F> pub trait AsyncAdaptor {
where
F: Read + Write + Seek,
{
fn read_vectored_sync( fn read_vectored_sync(
&mut self, &mut self,
offset: libc::off_t, offset: libc::off_t,
@@ -657,7 +654,10 @@ where
user_data: u64, user_data: u64,
eventfd: &EventFd, eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>, completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> { ) -> AsyncIoResult<()>
where
Self: Read + Seek,
{
// Convert libc::iovec into IoSliceMut // Convert libc::iovec into IoSliceMut
let mut slices: SmallVec<[IoSliceMut; DEFAULT_DESCRIPTOR_VEC_SIZE]> = let mut slices: SmallVec<[IoSliceMut; DEFAULT_DESCRIPTOR_VEC_SIZE]> =
SmallVec::with_capacity(iovecs.len()); SmallVec::with_capacity(iovecs.len());
@@ -669,15 +669,13 @@ where
} }
let result = { let result = {
let mut file = self.file();
// Move the cursor to the right offset // Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64)) self.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::ReadVectored)?; .map_err(AsyncIoError::ReadVectored)?;
let mut r = 0; let mut r = 0;
for b in slices.iter_mut() { for b in slices.iter_mut() {
r += file.read(b).map_err(AsyncIoError::ReadVectored)?; r += self.read(b).map_err(AsyncIoError::ReadVectored)?;
} }
r r
}; };
@@ -695,7 +693,10 @@ where
user_data: u64, user_data: u64,
eventfd: &EventFd, eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>, completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> { ) -> AsyncIoResult<()>
where
Self: Write + Seek,
{
// Convert libc::iovec into IoSlice // Convert libc::iovec into IoSlice
let mut slices: SmallVec<[IoSlice; DEFAULT_DESCRIPTOR_VEC_SIZE]> = let mut slices: SmallVec<[IoSlice; DEFAULT_DESCRIPTOR_VEC_SIZE]> =
SmallVec::with_capacity(iovecs.len()); SmallVec::with_capacity(iovecs.len());
@@ -707,15 +708,13 @@ where
} }
let result = { let result = {
let mut file = self.file();
// Move the cursor to the right offset // Move the cursor to the right offset
file.seek(SeekFrom::Start(offset as u64)) self.seek(SeekFrom::Start(offset as u64))
.map_err(AsyncIoError::WriteVectored)?; .map_err(AsyncIoError::WriteVectored)?;
let mut r = 0; let mut r = 0;
for b in slices.iter() { for b in slices.iter() {
r += file.write(b).map_err(AsyncIoError::WriteVectored)?; r += self.write(b).map_err(AsyncIoError::WriteVectored)?;
} }
r r
}; };
@@ -731,12 +730,13 @@ where
user_data: Option<u64>, user_data: Option<u64>,
eventfd: &EventFd, eventfd: &EventFd,
completion_list: &mut VecDeque<(u64, i32)>, completion_list: &mut VecDeque<(u64, i32)>,
) -> AsyncIoResult<()> { ) -> AsyncIoResult<()>
where
Self: Write,
{
let result: i32 = { let result: i32 = {
let mut file = self.file();
// Flush // Flush
file.flush().map_err(AsyncIoError::Fsync)?; self.flush().map_err(AsyncIoError::Fsync)?;
0 0
}; };
@@ -748,8 +748,6 @@ where
Ok(()) Ok(())
} }
fn file(&mut self) -> MutexGuard<'_, F>;
} }
pub enum ImageType { pub enum ImageType {
+1 -1
View File
@@ -425,7 +425,7 @@ fn max_refcount_clusters(refcount_order: u32, cluster_size: u32, num_clusters: u
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// ``` /// ```
#[derive(Debug)] #[derive(Clone, Debug)]
pub struct QcowFile { pub struct QcowFile {
raw_file: QcowRawFile, raw_file: QcowRawFile,
header: QcowHeader, header: QcowHeader,
+9 -15
View File
@@ -6,7 +6,6 @@ use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::io::{Seek, SeekFrom}; use std::io::{Seek, SeekFrom};
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::sync::{Arc, Mutex, MutexGuard};
use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::eventfd::EventFd;
@@ -17,22 +16,22 @@ use crate::qcow::{QcowFile, RawFile, Result as QcowResult};
use crate::AsyncAdaptor; use crate::AsyncAdaptor;
pub struct QcowDiskSync { pub struct QcowDiskSync {
qcow_file: Arc<Mutex<QcowFile>>, qcow_file: QcowFile,
} }
impl QcowDiskSync { impl QcowDiskSync {
pub fn new(file: File, direct_io: bool) -> QcowResult<Self> { pub fn new(file: File, direct_io: bool) -> QcowResult<Self> {
Ok(QcowDiskSync { Ok(QcowDiskSync {
qcow_file: Arc::new(Mutex::new(QcowFile::from(RawFile::new(file, direct_io))?)), qcow_file: QcowFile::from(RawFile::new(file, direct_io))?,
}) })
} }
} }
impl DiskFile for QcowDiskSync { impl DiskFile for QcowDiskSync {
fn size(&mut self) -> DiskFileResult<u64> { fn size(&mut self) -> DiskFileResult<u64> {
let mut file = self.qcow_file.lock().unwrap(); self.qcow_file
.seek(SeekFrom::End(0))
file.seek(SeekFrom::End(0)).map_err(DiskFileError::Size) .map_err(DiskFileError::Size)
} }
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> { fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
@@ -40,19 +39,18 @@ impl DiskFile for QcowDiskSync {
} }
fn fd(&mut self) -> BorrowedDiskFd<'_> { fn fd(&mut self) -> BorrowedDiskFd<'_> {
let lock = self.qcow_file.lock().unwrap(); BorrowedDiskFd::new(self.qcow_file.as_raw_fd())
BorrowedDiskFd::new(lock.as_raw_fd())
} }
} }
pub struct QcowSync { pub struct QcowSync {
qcow_file: Arc<Mutex<QcowFile>>, qcow_file: QcowFile,
eventfd: EventFd, eventfd: EventFd,
completion_list: VecDeque<(u64, i32)>, completion_list: VecDeque<(u64, i32)>,
} }
impl QcowSync { impl QcowSync {
pub fn new(qcow_file: Arc<Mutex<QcowFile>>) -> Self { pub fn new(qcow_file: QcowFile) -> Self {
QcowSync { QcowSync {
qcow_file, qcow_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK) eventfd: EventFd::new(libc::EFD_NONBLOCK)
@@ -62,11 +60,7 @@ impl QcowSync {
} }
} }
impl AsyncAdaptor<QcowFile> for Arc<Mutex<QcowFile>> { impl AsyncAdaptor for QcowFile {}
fn file(&mut self) -> MutexGuard<'_, QcowFile> {
self.lock().unwrap()
}
}
impl AsyncIo for QcowSync { impl AsyncIo for QcowSync {
fn notifier(&self) -> &EventFd { fn notifier(&self) -> &EventFd {
+7 -13
View File
@@ -5,7 +5,6 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use std::fs::File; use std::fs::File;
use std::os::fd::AsRawFd; use std::os::fd::AsRawFd;
use std::sync::{Arc, Mutex, MutexGuard};
use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::eventfd::EventFd;
@@ -16,20 +15,20 @@ use crate::vhdx::{Result as VhdxResult, Vhdx};
use crate::AsyncAdaptor; use crate::AsyncAdaptor;
pub struct VhdxDiskSync { pub struct VhdxDiskSync {
vhdx_file: Arc<Mutex<Vhdx>>, vhdx_file: Vhdx,
} }
impl VhdxDiskSync { impl VhdxDiskSync {
pub fn new(f: File) -> VhdxResult<Self> { pub fn new(f: File) -> VhdxResult<Self> {
Ok(VhdxDiskSync { Ok(VhdxDiskSync {
vhdx_file: Arc::new(Mutex::new(Vhdx::new(f)?)), vhdx_file: Vhdx::new(f)?,
}) })
} }
} }
impl DiskFile for VhdxDiskSync { impl DiskFile for VhdxDiskSync {
fn size(&mut self) -> DiskFileResult<u64> { fn size(&mut self) -> DiskFileResult<u64> {
Ok(self.vhdx_file.lock().unwrap().virtual_disk_size()) Ok(self.vhdx_file.virtual_disk_size())
} }
fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> { fn new_async_io(&self, _ring_depth: u32) -> DiskFileResult<Box<dyn AsyncIo>> {
@@ -40,19 +39,18 @@ impl DiskFile for VhdxDiskSync {
} }
fn fd(&mut self) -> BorrowedDiskFd<'_> { fn fd(&mut self) -> BorrowedDiskFd<'_> {
let lock = self.vhdx_file.lock().unwrap(); BorrowedDiskFd::new(self.vhdx_file.as_raw_fd())
BorrowedDiskFd::new(lock.as_raw_fd())
} }
} }
pub struct VhdxSync { pub struct VhdxSync {
vhdx_file: Arc<Mutex<Vhdx>>, vhdx_file: Vhdx,
eventfd: EventFd, eventfd: EventFd,
completion_list: VecDeque<(u64, i32)>, completion_list: VecDeque<(u64, i32)>,
} }
impl VhdxSync { impl VhdxSync {
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>) -> std::io::Result<Self> { pub fn new(vhdx_file: Vhdx) -> std::io::Result<Self> {
Ok(VhdxSync { Ok(VhdxSync {
vhdx_file, vhdx_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)?, eventfd: EventFd::new(libc::EFD_NONBLOCK)?,
@@ -61,11 +59,7 @@ impl VhdxSync {
} }
} }
impl AsyncAdaptor<Vhdx> for Arc<Mutex<Vhdx>> { impl AsyncAdaptor for Vhdx {}
fn file(&mut self) -> MutexGuard<'_, Vhdx> {
self.lock().unwrap()
}
}
impl AsyncIo for VhdxSync { impl AsyncIo for VhdxSync {
fn notifier(&self) -> &EventFd { fn notifier(&self) -> &EventFd {