block: Move VHD format files into formats/vhd/

Move VHD format implementation into a structured directory layout:

  fixed_vhd.rs       -> formats/vhd/internal/fixed.rs     (FixedVhd)
  fixed_vhd_disk.rs  -> formats/vhd/mod.rs                (VhdDisk)
  vhd.rs             -> formats/vhd/internal/footer.rs     (VhdFooter)
  fixed_vhd_sync.rs  -> formats/vhd/worker/sync.rs         (FixedVhdSync)
  fixed_vhd_async.rs -> formats/vhd/worker/async_uring.rs  (FixedVhdAsync)

Add #[allow(dead_code)] to VhdFooter struct and impl because the
module is now pub(crate) and the compiler can see that several
fields and getters are only exercised by unit tests. Re-export
formats::vhd as fixed_vhd_disk in lib.rs for backward
compatibility with external consumers.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-04-24 23:44:30 +02:00
committed by Rob Bradford
parent a11f551572
commit 1ca0c39b4d
10 changed files with 46 additions and 14 deletions
+1 -1
View File
@@ -20,8 +20,8 @@ use log::info;
use crate::block_io_uring_is_supported; use crate::block_io_uring_is_supported;
use crate::disk_file::AsyncFullDiskFile; use crate::disk_file::AsyncFullDiskFile;
use crate::error::{BlockError, BlockErrorKind, BlockResult}; use crate::error::{BlockError, BlockErrorKind, BlockResult};
use crate::fixed_vhd_disk::VhdDisk;
use crate::formats::raw::{RawBackend, RawDisk}; use crate::formats::raw::{RawBackend, RawDisk};
use crate::formats::vhd::VhdDisk;
use crate::qcow_disk::QcowDisk; use crate::qcow_disk::QcowDisk;
use crate::vhdx_sync::VhdxDisk; use crate::vhdx_sync::VhdxDisk;
use crate::{ use crate::{
+1
View File
@@ -8,3 +8,4 @@
//! format specific internals, and sync/async I/O workers. //! format specific internals, and sync/async I/O workers.
pub mod raw; pub mod raw;
pub mod vhd;
@@ -6,8 +6,8 @@ use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write}; use std::io::{Read, Seek, SeekFrom, Write};
use std::os::unix::io::{AsRawFd, RawFd}; use std::os::unix::io::{AsRawFd, RawFd};
use super::footer::VhdFooter;
use crate::BlockBackend; use crate::BlockBackend;
use crate::vhd::VhdFooter;
#[derive(Debug)] #[derive(Debug)]
pub struct FixedVhd { pub struct FixedVhd {
@@ -7,7 +7,11 @@ use std::io::{Seek, SeekFrom};
use crate::{DiskTopology, read_aligned_block_size}; use crate::{DiskTopology, read_aligned_block_size};
// Production code uses: cookie, file_format_version, data_offset,
// current_size, disk_type. The remaining fields are parsed for VHD
// spec completeness and exercised only by unit tests.
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[allow(dead_code)]
pub struct VhdFooter { pub struct VhdFooter {
cookie: u64, cookie: u64,
features: u32, features: u32,
@@ -26,6 +30,7 @@ pub struct VhdFooter {
saved_state: u8, saved_state: u8,
} }
#[allow(dead_code)]
impl VhdFooter { impl VhdFooter {
pub fn new(file: &mut File) -> std::io::Result<VhdFooter> { pub fn new(file: &mut File) -> std::io::Result<VhdFooter> {
let blocksize = DiskTopology::probe(file)?.logical_block_size as usize; let blocksize = DiskTopology::probe(file)?.logical_block_size as usize;
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
//! VHD format parsing and data structures.
//!
//! Contains the footer parser and the low level fixed VHD
//! block backend.
pub(crate) mod fixed;
pub(crate) mod footer;
@@ -4,17 +4,27 @@
// //
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
//! Fixed VHD disk image format.
//!
//! Provides [`VhdDisk`], the `DiskFile` wrapper for fixed size VHD
//! images.
pub(crate) mod internal;
pub(crate) mod worker;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
pub use internal::footer::is_fixed_vhd;
use self::internal::fixed::FixedVhd;
#[cfg(feature = "io_uring")]
use self::worker::async_uring::FixedVhdAsync;
use self::worker::sync::FixedVhdSync;
use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError}; use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError};
use crate::disk_file::DiskSize; use crate::disk_file::DiskSize;
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp}; use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::fixed_vhd::FixedVhd;
#[cfg(feature = "io_uring")]
use crate::fixed_vhd_async::FixedVhdAsync;
use crate::fixed_vhd_sync::FixedVhdSync;
use crate::{BlockBackend, Error, disk_file}; use crate::{BlockBackend, Error, disk_file};
#[derive(Debug)] #[derive(Debug)]
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
//! Sync/async I/O workers for fixed VHD images.
//!
//! Thin wrappers around the raw workers that clamp I/O to the
//! virtual disk size.
#[cfg(feature = "io_uring")]
pub(crate) mod async_uring;
pub(crate) mod sync;
+1 -8
View File
@@ -14,12 +14,6 @@ pub mod factory;
#[path = "io/mod.rs"] #[path = "io/mod.rs"]
mod io_impl; mod io_impl;
pub use io_impl::{async_io, fcntl, request}; pub use io_impl::{async_io, fcntl, request};
pub mod fixed_vhd;
#[cfg(feature = "io_uring")]
/// Enabled with the `"io_uring"` feature
pub mod fixed_vhd_async;
pub mod fixed_vhd_disk;
pub mod fixed_vhd_sync;
pub mod formats; pub mod formats;
pub mod qcow; pub mod qcow;
#[cfg(feature = "io_uring")] #[cfg(feature = "io_uring")]
@@ -29,7 +23,6 @@ pub mod qcow_disk;
pub(crate) mod qcow_sync; pub(crate) mod qcow_sync;
mod sparse; mod sparse;
pub use formats::raw as raw_disk; pub use formats::raw as raw_disk;
pub mod vhd;
pub mod vhdx; pub mod vhdx;
pub mod vhdx_sync; pub mod vhdx_sync;
@@ -521,7 +514,7 @@ pub fn detect_image_type(f: &mut File) -> BlockResult<ImageType> {
// Check 4 first bytes to get the header value and determine the image type // Check 4 first bytes to get the header value and determine the image type
let image_type = if u32::from_be_bytes(block[0..4].try_into().unwrap()) == QCOW_MAGIC { let image_type = if u32::from_be_bytes(block[0..4].try_into().unwrap()) == QCOW_MAGIC {
ImageType::Qcow2 ImageType::Qcow2
} else if vhd::is_fixed_vhd(f) } else if formats::vhd::is_fixed_vhd(f)
.map_err(|e| BlockError::new(BlockErrorKind::Io, e).with_op(ErrorOp::DetectImageType))? .map_err(|e| BlockError::new(BlockErrorKind::Io, e).with_op(ErrorOp::DetectImageType))?
{ {
ImageType::FixedVhd ImageType::FixedVhd