block: Remove DiskBackend dispatch enum

All disk format backends now implement AsyncFullDiskFile directly.
The DiskBackend enum that dispatched between Legacy and Next arms
is no longer needed since the factory returns trait objects and vmm
no longer constructs format types manually.

Replace DiskBackend with Box<dyn AsyncFullDiskFile> in the Block
struct and its constructor. Remove the DiskBackend::Next wrapping
in device_manager and the fuzz target.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-04-21 22:32:58 +02:00
committed by Rob Bradford
parent 6b6150ebfc
commit 835caf9413
4 changed files with 6 additions and 91 deletions

View File

@@ -34,10 +34,8 @@
//! `&mut self`. Errors are returned as [`BlockResult`].
use std::fmt::Debug;
use std::io;
use crate::async_io::{self, AsyncIo, BorrowedDiskFd};
use crate::error::{BlockError, BlockErrorKind};
use crate::async_io::{AsyncIo, BorrowedDiskFd};
use crate::{BlockResult, DiskTopology};
/// Reported capacity of a disk image.
@@ -158,82 +156,3 @@ pub trait AsyncFullDiskFile: FullDiskFile + AsyncDiskFile {}
/// Blanket implementation: any type implementing both [`FullDiskFile`]
/// and [`AsyncDiskFile`] automatically satisfies [`AsyncFullDiskFile`].
impl<T: FullDiskFile + AsyncDiskFile> AsyncFullDiskFile for T {}
/// A disk backend that dispatches to either the existing [`async_io::DiskFile`]
/// trait or the next-generation [`AsyncFullDiskFile`] trait.
pub enum DiskBackend {
/// Existing disk file backend (raw, vhd, vhdx, etc.).
Legacy(Box<dyn async_io::DiskFile>),
/// Next-generation disk file backend (qcow2, and more formats as they migrate).
Next(Box<dyn AsyncFullDiskFile>),
}
impl DiskBackend {
pub fn logical_size(&mut self) -> BlockResult<u64> {
match self {
Self::Legacy(d) => d
.logical_size()
.map_err(|e| BlockError::new(BlockErrorKind::Io, io::Error::other(e))),
Self::Next(d) => d.logical_size(),
}
}
pub fn physical_size(&mut self) -> BlockResult<u64> {
match self {
Self::Legacy(d) => d
.physical_size()
.map_err(|e| BlockError::new(BlockErrorKind::Io, io::Error::other(e))),
Self::Next(d) => d.physical_size(),
}
}
pub fn topology(&mut self) -> DiskTopology {
match self {
Self::Legacy(d) => d.topology(),
Self::Next(d) => d.topology(),
}
}
pub fn supports_sparse_operations(&self) -> bool {
match self {
Self::Legacy(d) => d.supports_sparse_operations(),
Self::Next(d) => d.supports_sparse_operations(),
}
}
pub fn supports_zero_flag(&self) -> bool {
match self {
Self::Legacy(d) => d.supports_zero_flag(),
Self::Next(d) => d.supports_zero_flag(),
}
}
pub fn fd(&mut self) -> BorrowedDiskFd<'_> {
match self {
Self::Legacy(d) => d.fd(),
Self::Next(d) => d.fd(),
}
}
pub fn create_async_io(&self, ring_depth: u32) -> BlockResult<Box<dyn AsyncIo>> {
match self {
Self::Legacy(d) => d
.create_async_io(ring_depth)
.map_err(|e| BlockError::new(BlockErrorKind::Io, io::Error::other(e))),
Self::Next(d) => d.create_async_io(ring_depth),
}
}
pub fn resize(&mut self, new_size: u64) -> BlockResult<()> {
match self {
Self::Legacy(d) => d.resize(new_size).map_err(|e| match e {
async_io::DiskFileError::Unsupported => BlockError::new(
BlockErrorKind::UnsupportedFeature,
io::Error::other("resize not supported"),
),
_ => BlockError::new(BlockErrorKind::Io, io::Error::other(e)),
}),
Self::Next(d) => d.resize(new_size),
}
}
}

View File

@@ -15,7 +15,6 @@ use std::path::PathBuf;
use std::sync::Arc;
use std::{ffi, io};
use block::disk_file::DiskBackend;
use block::fcntl::LockGranularityChoice;
use block::raw_sync::RawFileDiskSync;
use libfuzzer_sys::{fuzz_target, Corpus};
@@ -55,7 +54,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
let queue_affinity = BTreeMap::new();
let mut block = Block::new(
"tmp".to_owned(),
DiskBackend::Next(Box::new(RawFileDiskSync::new(disk_file))),
Box::new(RawFileDiskSync::new(disk_file)),
PathBuf::from(""),
false,
false,

View File

@@ -20,7 +20,7 @@ use std::{io, result};
use anyhow::anyhow;
use block::async_io::{AsyncIo, AsyncIoError};
use block::disk_file::DiskBackend;
use block::disk_file::AsyncFullDiskFile;
use block::error::BlockError;
use block::fcntl::{LockError, LockGranularity, LockGranularityChoice, LockType, get_lock_state};
use block::{
@@ -713,7 +713,7 @@ impl EpollHelperHandler for BlockEpollHandler {
pub struct Block {
common: VirtioCommon,
id: String,
disk_image: DiskBackend,
disk_image: Box<dyn AsyncFullDiskFile>,
disk_path: PathBuf,
disk_nsectors: Arc<AtomicU64>,
config: VirtioBlockConfig,
@@ -743,7 +743,7 @@ impl Block {
#[allow(clippy::too_many_arguments)]
pub fn new(
id: String,
mut disk_image: DiskBackend,
disk_image: Box<dyn AsyncFullDiskFile>,
disk_path: PathBuf,
read_only: bool,
access_platform_enabled: bool,

View File

@@ -33,7 +33,6 @@ use arch::layout::{APIC_START, IOAPIC_SIZE, IOAPIC_START};
use arch::{DeviceType, MmioDeviceInfo};
use arch::{NumaNodes, layout};
use block::ImageType;
use block::disk_file::DiskBackend;
use block::error::BlockError;
use block::factory::{DiskOpenOptions, open_disk};
#[cfg(target_arch = "riscv64")]
@@ -2719,8 +2718,6 @@ impl DeviceManager {
warn!("Enabling backing_files option only applies for QCOW2 files");
}
let image = DiskBackend::Next(opened.disk);
let rate_limit_group =
if let Some(rate_limiter_cfg) = disk_cfg.rate_limiter_config.as_ref() {
// Create an anonymous RateLimiterGroup that is dropped when the Disk
@@ -2764,7 +2761,7 @@ impl DeviceManager {
let mut virtio_block = virtio_devices::Block::new(
id.clone(),
image,
opened.disk,
disk_cfg
.path
.as_ref()