From 701767e5bef174b26458f0912fc10e21aef6979a Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Thu, 23 Apr 2026 13:15:52 +0200 Subject: [PATCH] block: Use RawDisk in factory, remove old wrappers Update open_raw to construct RawDisk instead of choosing between RawFileDisk, RawFileDiskSync and RawFileDiskAio. The backend decision is now made inside RawDisk::create_async_io. Remove the DiskFile wrapper structs from raw_sync.rs, raw_async.rs and raw_async_aio.rs. Only the AsyncIo worker structs remain in those files. Reduce their module visibility to pub(crate). Signed-off-by: Anatol Belski --- block/src/factory.rs | 13 +++-- block/src/lib.rs | 9 ++-- block/src/raw_async.rs | 108 ++----------------------------------- block/src/raw_async_aio.rs | 81 +--------------------------- block/src/raw_sync.rs | 84 ++--------------------------- 5 files changed, 17 insertions(+), 278 deletions(-) diff --git a/block/src/factory.rs b/block/src/factory.rs index 7bfef6729..4d31f9860 100644 --- a/block/src/factory.rs +++ b/block/src/factory.rs @@ -16,6 +16,8 @@ use std::{fmt, fs}; use log::info; +#[cfg(feature = "io_uring")] +use crate::block_io_uring_is_supported; use crate::disk_file::AsyncFullDiskFile; use crate::error::{BlockError, BlockErrorKind, BlockResult}; #[cfg(feature = "io_uring")] @@ -24,14 +26,11 @@ use crate::fixed_vhd_sync::FixedVhdDiskSync; #[cfg(feature = "io_uring")] use crate::qcow_async::QcowDiskAsync; use crate::qcow_sync::QcowDiskSync; -use crate::raw_async_aio::RawFileDiskAio; -use crate::raw_sync::RawFileDiskSync; +use crate::raw_disk::{RawBackend, RawDisk}; use crate::vhdx_sync::VhdxDiskSync; use crate::{ ImageType, block_aio_is_supported, detect_image_type, open_disk_image, preallocate_disk, }; -#[cfg(feature = "io_uring")] -use crate::{block_io_uring_is_supported, raw_async::RawFileDisk}; /// Options for opening a disk image via [`open_disk`]. pub struct DiskOpenOptions<'a> { @@ -156,7 +155,7 @@ fn open_raw( if !options.disable_io_uring { if io_uring_supported() { info!("Opening RAW disk file with io_uring backend"); - return Ok(Box::new(RawFileDisk::new(file))); + return Ok(Box::new(RawDisk::new(file, RawBackend::IoUring))); } info!("io_uring runtime probe failed for RAW, trying next backend"); } @@ -164,13 +163,13 @@ fn open_raw( if !options.disable_aio { if aio_supported() { info!("Opening RAW disk file with AIO backend"); - return Ok(Box::new(RawFileDiskAio::new(file))); + return Ok(Box::new(RawDisk::new(file, RawBackend::Aio))); } info!("AIO runtime probe failed for RAW, using synchronous backend"); } info!("Opening RAW disk file with synchronous backend"); - Ok(Box::new(RawFileDiskSync::new(file))) + Ok(Box::new(RawDisk::new(file, RawBackend::Sync))) } fn open_qcow2( diff --git a/block/src/lib.rs b/block/src/lib.rs index 77fb50315..ff59e514e 100644 --- a/block/src/lib.rs +++ b/block/src/lib.rs @@ -24,15 +24,12 @@ pub mod qcow_async; pub(crate) mod qcow_common; pub mod qcow_sync; #[cfg(feature = "io_uring")] -/// Async primitives based on `io-uring` -/// -/// Enabled with the `"io_uring"` feature -pub mod raw_async; -pub mod raw_async_aio; +pub(crate) mod raw_async; +pub(crate) mod raw_async_aio; #[cfg(test)] mod raw_async_io_tests; pub mod raw_disk; -pub mod raw_sync; +pub(crate) mod raw_sync; mod request; pub mod vhd; pub mod vhdx; diff --git a/block/src/raw_async.rs b/block/src/raw_async.rs index 2b8de99e5..715a39ecc 100644 --- a/block/src/raw_async.rs +++ b/block/src/raw_async.rs @@ -2,118 +2,16 @@ // // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause -use std::fs::File; -use std::io::{self, Error}; -use std::os::unix::fs::FileTypeExt; +use std::io::Error; use std::os::unix::io::{AsRawFd, RawFd}; use io_uring::{IoUring, opcode, types}; use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE}; -use log::warn; use vmm_sys_util::eventfd::EventFd; -use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFileError}; +use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult}; use crate::error::{BlockError, BlockErrorKind, BlockResult}; -use crate::{ - BatchRequest, DiskTopology, RequestType, SECTOR_SIZE, disk_file, probe_sparse_support, - query_device_size, -}; - -#[derive(Debug)] -pub struct RawFileDisk { - file: File, -} - -impl RawFileDisk { - pub fn new(file: File) -> Self { - RawFileDisk { file } - } -} - -impl disk_file::DiskSize for RawFileDisk { - fn logical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(logical_size, _)| logical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::PhysicalSize for RawFileDisk { - fn physical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(_, physical_size)| physical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::DiskFd for RawFileDisk { - fn fd(&self) -> BorrowedDiskFd<'_> { - BorrowedDiskFd::new(self.file.as_raw_fd()) - } -} - -impl disk_file::Geometry for RawFileDisk { - fn topology(&self) -> DiskTopology { - DiskTopology::probe(&self.file).unwrap_or_else(|_| { - warn!("Unable to get device topology. Using default topology"); - DiskTopology::default() - }) - } -} - -impl disk_file::SparseCapable for RawFileDisk { - fn supports_sparse_operations(&self) -> bool { - probe_sparse_support(&self.file) - } -} - -impl disk_file::Resizable for RawFileDisk { - fn resize(&mut self, size: u64) -> BlockResult<()> { - let fd_metadata = self - .file - .metadata() - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e)))?; - - if fd_metadata.file_type().is_block_device() { - // Block devices cannot be resized via ftruncate - they are resized - // externally (LVM, losetup -c, etc.). Verify the size matches. - let (actual_size, _) = query_device_size(&self.file) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e)))?; - if actual_size != size { - return Err(BlockError::new( - BlockErrorKind::Io, - DiskFileError::ResizeError(io::Error::other(format!( - "Block device size {actual_size} does not match requested size {size}" - ))), - )); - } - Ok(()) - } else { - self.file - .set_len(size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e))) - } - } -} - -impl disk_file::DiskFile for RawFileDisk {} - -impl disk_file::AsyncDiskFile for RawFileDisk { - fn try_clone(&self) -> BlockResult> { - let file = self - .file - .try_clone() - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Clone(e)))?; - Ok(Box::new(RawFileDisk { file })) - } - - fn create_async_io(&self, ring_depth: u32) -> BlockResult> { - let mut raw = RawFileAsync::new(self.file.as_raw_fd(), ring_depth)?; - raw.alignment = - DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size); - Ok(Box::new(raw) as Box) - } -} +use crate::{BatchRequest, RequestType, SECTOR_SIZE}; pub struct RawFileAsync { fd: RawFd, diff --git a/block/src/raw_async_aio.rs b/block/src/raw_async_aio.rs index 2b63aa24c..3636fd7fc 100644 --- a/block/src/raw_async_aio.rs +++ b/block/src/raw_async_aio.rs @@ -6,92 +6,15 @@ // use std::collections::VecDeque; -use std::fs::File; use std::os::unix::io::{AsRawFd, RawFd}; use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE}; -use log::warn; use vmm_sys_util::aio; use vmm_sys_util::eventfd::EventFd; -use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFileError}; +use crate::SECTOR_SIZE; +use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult}; use crate::error::{BlockError, BlockErrorKind, BlockResult}; -use crate::{DiskTopology, SECTOR_SIZE, disk_file, probe_sparse_support, query_device_size}; - -#[derive(Debug)] -pub struct RawFileDiskAio { - file: File, -} - -impl RawFileDiskAio { - pub fn new(file: File) -> Self { - RawFileDiskAio { file } - } -} - -impl disk_file::DiskSize for RawFileDiskAio { - fn logical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(logical_size, _)| logical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::PhysicalSize for RawFileDiskAio { - fn physical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(_, physical_size)| physical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::DiskFd for RawFileDiskAio { - fn fd(&self) -> BorrowedDiskFd<'_> { - BorrowedDiskFd::new(self.file.as_raw_fd()) - } -} - -impl disk_file::Geometry for RawFileDiskAio { - fn topology(&self) -> DiskTopology { - DiskTopology::probe(&self.file).unwrap_or_else(|_| { - warn!("Unable to get device topology. Using default topology"); - DiskTopology::default() - }) - } -} - -impl disk_file::SparseCapable for RawFileDiskAio { - fn supports_sparse_operations(&self) -> bool { - probe_sparse_support(&self.file) - } -} - -impl disk_file::Resizable for RawFileDiskAio { - fn resize(&mut self, size: u64) -> BlockResult<()> { - self.file - .set_len(size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e))) - } -} - -impl disk_file::DiskFile for RawFileDiskAio {} - -impl disk_file::AsyncDiskFile for RawFileDiskAio { - fn try_clone(&self) -> BlockResult> { - let file = self - .file - .try_clone() - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Clone(e)))?; - Ok(Box::new(RawFileDiskAio { file })) - } - - fn create_async_io(&self, ring_depth: u32) -> BlockResult> { - let mut raw = RawFileAsyncAio::new(self.file.as_raw_fd(), ring_depth)?; - raw.alignment = - DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size); - Ok(Box::new(raw) as Box) - } -} pub struct RawFileAsyncAio { fd: RawFd, diff --git a/block/src/raw_sync.rs b/block/src/raw_sync.rs index 1b83b6707..659693f29 100644 --- a/block/src/raw_sync.rs +++ b/block/src/raw_sync.rs @@ -3,91 +3,13 @@ // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause use std::collections::VecDeque; -use std::fs::File; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::RawFd; use libc::{FALLOC_FL_KEEP_SIZE, FALLOC_FL_PUNCH_HOLE, FALLOC_FL_ZERO_RANGE}; -use log::warn; use vmm_sys_util::eventfd::EventFd; -use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult, BorrowedDiskFd, DiskFileError}; -use crate::error::{BlockError, BlockErrorKind, BlockResult}; -use crate::{DiskTopology, SECTOR_SIZE, disk_file, probe_sparse_support, query_device_size}; - -#[derive(Debug)] -pub struct RawFileDiskSync { - file: File, -} - -impl RawFileDiskSync { - pub fn new(file: File) -> Self { - RawFileDiskSync { file } - } -} - -impl disk_file::DiskSize for RawFileDiskSync { - fn logical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(logical_size, _)| logical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::PhysicalSize for RawFileDiskSync { - fn physical_size(&self) -> BlockResult { - query_device_size(&self.file) - .map(|(_, physical_size)| physical_size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Size(e))) - } -} - -impl disk_file::DiskFd for RawFileDiskSync { - fn fd(&self) -> BorrowedDiskFd<'_> { - BorrowedDiskFd::new(self.file.as_raw_fd()) - } -} - -impl disk_file::Geometry for RawFileDiskSync { - fn topology(&self) -> DiskTopology { - DiskTopology::probe(&self.file).unwrap_or_else(|_| { - warn!("Unable to get device topology. Using default topology"); - DiskTopology::default() - }) - } -} - -impl disk_file::SparseCapable for RawFileDiskSync { - fn supports_sparse_operations(&self) -> bool { - probe_sparse_support(&self.file) - } -} - -impl disk_file::Resizable for RawFileDiskSync { - fn resize(&mut self, size: u64) -> BlockResult<()> { - self.file - .set_len(size) - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::ResizeError(e))) - } -} - -impl disk_file::DiskFile for RawFileDiskSync {} - -impl disk_file::AsyncDiskFile for RawFileDiskSync { - fn try_clone(&self) -> BlockResult> { - let file = self - .file - .try_clone() - .map_err(|e| BlockError::new(BlockErrorKind::Io, DiskFileError::Clone(e)))?; - Ok(Box::new(RawFileDiskSync { file })) - } - - fn create_async_io(&self, _ring_depth: u32) -> BlockResult> { - let mut raw = RawFileSync::new(self.file.as_raw_fd()); - raw.alignment = - DiskTopology::probe(&self.file).map_or(SECTOR_SIZE, |t| t.logical_block_size); - Ok(Box::new(raw) as Box) - } -} +use crate::SECTOR_SIZE; +use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoResult}; pub struct RawFileSync { fd: RawFd,