block: vhdx: Flatten internal and worker modules

Remove the internal and worker submodule layers from the VHDX format
directory. The bat, header, io, and metadata parsers move up as
direct children, internal/mod.rs becomes parser.rs, and the sync
backend moves up as engine_sync.rs. The declaration only
worker/mod.rs is dropped.

The public types are surfaced at the vhdx module level, so callers
use block::formats::vhdx instead of reaching into the internal
module.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
This commit is contained in:
Anatol Belski
2026-07-07 23:14:33 +02:00
committed by Rob Bradford
parent 6e0c39964a
commit 039b4e6013
8 changed files with 56 additions and 64 deletions

View File

@@ -14,17 +14,17 @@ use super::metadata::DiskSpec;
use crate::aligned_file::AlignedFile;
// Payload BAT Entry States
pub const PAYLOAD_BLOCK_NOT_PRESENT: u64 = 0;
pub const PAYLOAD_BLOCK_UNDEFINED: u64 = 1;
pub const PAYLOAD_BLOCK_ZERO: u64 = 2;
pub const PAYLOAD_BLOCK_UNMAPPED: u64 = 3;
pub const PAYLOAD_BLOCK_FULLY_PRESENT: u64 = 6;
pub const PAYLOAD_BLOCK_PARTIALLY_PRESENT: u64 = 7;
pub(super) const PAYLOAD_BLOCK_NOT_PRESENT: u64 = 0;
pub(super) const PAYLOAD_BLOCK_UNDEFINED: u64 = 1;
pub(super) const PAYLOAD_BLOCK_ZERO: u64 = 2;
pub(super) const PAYLOAD_BLOCK_UNMAPPED: u64 = 3;
pub(super) const PAYLOAD_BLOCK_FULLY_PRESENT: u64 = 6;
pub(super) const PAYLOAD_BLOCK_PARTIALLY_PRESENT: u64 = 7;
// Mask for the BAT state
pub const BAT_STATE_BIT_MASK: u64 = 0x07;
pub(super) const BAT_STATE_BIT_MASK: u64 = 0x07;
// Mask for the offset within the file in units of 1 MB
pub const BAT_FILE_OFF_MASK: u64 = 0xFFFFFFFFFFF00000;
pub(super) const BAT_FILE_OFF_MASK: u64 = 0xFFFFFFFFFFF00000;
#[sorted]
#[derive(Error, Debug)]
@@ -39,14 +39,14 @@ pub enum VhdxBatError {
WriteBat(#[source] io::Error),
}
pub type Result<T> = result::Result<T, VhdxBatError>;
pub(super) type Result<T> = result::Result<T, VhdxBatError>;
#[derive(Default, Clone, Debug)]
pub struct BatEntry(pub u64);
pub(super) struct BatEntry(pub u64);
impl BatEntry {
// Read all BAT entries presented on the disk and insert them to a vector
pub fn collect_bat_entries(
pub(super) fn collect_bat_entries(
f: &AlignedFile,
disk_spec: &DiskSpec,
bat_entry: &RegionTableEntry,
@@ -79,7 +79,7 @@ impl BatEntry {
}
// Routine for writing BAT entries to the disk
pub fn write_bat_entries(
pub(super) fn write_bat_entries(
f: &AlignedFile,
bat_offset: u64,
bat_entries: &[BatEntry],

View File

@@ -11,9 +11,9 @@ use std::sync::{Arc, Mutex};
use vmm_sys_util::eventfd::EventFd;
use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult};
use crate::formats::vhdx::internal::Vhdx;
use crate::formats::vhdx::Vhdx;
pub struct VhdxSync {
pub(super) struct VhdxSync {
vhdx_file: Arc<Mutex<Vhdx>>,
eventfd: EventFd,
completion_list: VecDeque<AsyncIoCompletion>,
@@ -21,7 +21,7 @@ pub struct VhdxSync {
}
impl VhdxSync {
pub fn new(vhdx_file: Arc<Mutex<Vhdx>>, size: u64) -> Self {
pub(super) fn new(vhdx_file: Arc<Mutex<Vhdx>>, size: u64) -> Self {
VhdxSync {
vhdx_file,
eventfd: EventFd::new(libc::EFD_NONBLOCK)
@@ -120,7 +120,7 @@ mod tests {
use super::*;
use crate::async_io::{AsyncIo, AsyncIoError, AsyncIoOperation, OwnedIoBuffer};
use crate::formats::vhdx::internal::Vhdx;
use crate::formats::vhdx::Vhdx;
use crate::formats::vhdx::test_util::create_dynamic_vhdx;
fn make_vhdx_sync(tf: &TempFile) -> (VhdxSync, u64) {

View File

@@ -21,7 +21,7 @@ const REGION_SIGN: u32 = 0x6967_6572; // "regi"
const FILE_START: u64 = 0; // The first element
const HEADER_1_START: u64 = 64 * 1024; // Header 1 start in Bytes
const HEADER_2_START: u64 = 128 * 1024; // Header 2 start in Bytes
pub const REGION_TABLE_1_START: u64 = 192 * 1024; // Region 1 start in Bytes
pub(super) const REGION_TABLE_1_START: u64 = 192 * 1024; // Region 1 start in Bytes
const REGION_TABLE_2_START: u64 = 256 * 1024; // Region 2 start in Bytes
const HEADER_SIZE: u64 = 4 * 1024; // Each header is 64 KiB, but only first 4 kiB contains info
@@ -84,16 +84,16 @@ pub enum VhdxHeaderError {
WriteHeader(#[source] io::Error),
}
pub type Result<T> = result::Result<T, VhdxHeaderError>;
pub(super) type Result<T> = result::Result<T, VhdxHeaderError>;
#[derive(Clone, Debug)]
pub struct FileTypeIdentifier {
pub(super) struct FileTypeIdentifier {
pub _signature: u64,
}
impl FileTypeIdentifier {
/// Reads the File Type Identifier structure from a reference VHDx file
pub fn new(f: &AlignedFile) -> Result<FileTypeIdentifier> {
pub(super) fn new(f: &AlignedFile) -> Result<FileTypeIdentifier> {
let mut buf = [0u8; size_of::<u64>()];
f.read_exact_at(&mut buf, FILE_START)
.map_err(VhdxHeaderError::ReadFileTypeIdentifier)?;
@@ -108,7 +108,7 @@ impl FileTypeIdentifier {
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, FromBytes, Immutable, IntoBytes)]
pub struct Header {
pub(super) struct Header {
pub signature: u32,
pub checksum: u32,
pub sequence_number: u64,
@@ -123,7 +123,7 @@ pub struct Header {
impl Header {
/// Reads the Header structure from a reference VHDx file
pub fn new(f: &AlignedFile, start: u64) -> Result<Header> {
pub(super) fn new(f: &AlignedFile, start: u64) -> Result<Header> {
// Read the whole header into a buffer. We will need it for
// calculating checksum.
let mut buffer = [0; HEADER_SIZE as usize];
@@ -199,7 +199,7 @@ struct RegionTableHeader {
impl RegionTableHeader {
/// Reads the Region Table Header structure from a reference VHDx file
pub fn new(f: &AlignedFile, start: u64) -> Result<RegionTableHeader> {
pub(crate) fn new(f: &AlignedFile, start: u64) -> Result<RegionTableHeader> {
// Read the whole header into a buffer. We will need it for calculating
// checksum.
let mut buffer = [0u8; REGION_SIZE as usize];
@@ -234,7 +234,7 @@ fn ranges_overlap(a_start: u64, a_end: u64, b_start: u64, b_end: u64) -> bool {
a_start < b_end && b_start < a_end
}
pub struct RegionInfo {
pub(super) struct RegionInfo {
pub bat_entry: RegionTableEntry,
pub mdr_entry: RegionTableEntry,
pub region_entries: BTreeMap<u64, u64>,
@@ -243,7 +243,7 @@ pub struct RegionInfo {
impl RegionInfo {
/// Collect all entries in a BTreeMap from the Region Table and identifies
/// BAT and metadata regions
pub fn new(f: &AlignedFile, region_start: u64, entry_count: u32) -> Result<RegionInfo> {
pub(super) fn new(f: &AlignedFile, region_start: u64, entry_count: u32) -> Result<RegionInfo> {
let mut bat_entry: Option<RegionTableEntry> = None;
let mut mdr_entry: Option<RegionTableEntry> = None;
@@ -321,7 +321,7 @@ impl RegionInfo {
#[repr(C, packed)]
#[derive(Clone, Copy, Debug, FromBytes)]
pub struct RegionTableEntry {
pub(super) struct RegionTableEntry {
guid: [u8; 16],
pub file_offset: u64,
pub length: u32,
@@ -335,7 +335,7 @@ enum HeaderNo {
/// Contains the information from the header of a VHDx file
#[derive(Clone, Debug)]
pub struct VhdxHeader {
pub(super) struct VhdxHeader {
_file_type_identifier: FileTypeIdentifier,
header_1: Header,
header_2: Header,
@@ -345,7 +345,7 @@ pub struct VhdxHeader {
impl VhdxHeader {
/// Creates a VhdxHeader from a reference to a file
pub fn new(f: &AlignedFile) -> Result<VhdxHeader> {
pub(super) fn new(f: &AlignedFile) -> Result<VhdxHeader> {
Ok(VhdxHeader {
_file_type_identifier: FileTypeIdentifier::new(f)?,
header_1: Header::new(f, HEADER_1_START)?,
@@ -415,14 +415,14 @@ impl VhdxHeader {
VhdxHeader::update_header(f, Ok(header_1), Ok(header_2), guid)
}
pub fn update(&mut self, f: &AlignedFile) -> Result<()> {
pub(super) fn update(&mut self, f: &AlignedFile) -> Result<()> {
let headers = VhdxHeader::update_headers(f, Ok(self.header_1), Ok(self.header_2), 0)?;
self.header_1 = headers.0;
self.header_2 = headers.1;
Ok(())
}
pub fn region_entry_count(&self) -> u32 {
pub(super) fn region_entry_count(&self) -> u32 {
self.region_table_1.entry_count
}
}

View File

@@ -33,7 +33,7 @@ pub enum VhdxIoError {
WriteBat(#[source] VhdxBatError),
}
pub type Result<T> = result::Result<T, VhdxIoError>;
pub(super) type Result<T> = result::Result<T, VhdxIoError>;
macro_rules! align {
($n:expr, $align:expr) => {{ $n.div_ceil($align) * $align }};
@@ -51,7 +51,7 @@ struct Sector {
impl Sector {
/// Translate sector index and count of data in file to actual offsets and
/// BAT index.
pub fn new(
pub(crate) fn new(
disk_spec: &DiskSpec,
bat: &[BatEntry],
sector_index: u64,
@@ -86,7 +86,7 @@ impl Sector {
/// VHDx IO read routine: requires relative sector index and count for the
/// requested data.
pub fn read(
pub(super) fn read(
f: &AlignedFile,
buf: &mut [u8],
disk_spec: &DiskSpec,
@@ -138,7 +138,7 @@ pub fn read(
/// VHDx IO write routine: requires relative sector index and count for the
/// requested data.
pub fn write(
pub(super) fn write(
f: &AlignedFile,
buf: &[u8],
disk_spec: &mut DiskSpec,

View File

@@ -21,7 +21,7 @@ const METADATA_TABLE_MAX_SIZE: usize = METADATA_ENTRY_SIZE * (METADATA_MAX_ENTRI
const METADATA_FLAGS_IS_REQUIRED: u32 = 0x04;
pub const BLOCK_SIZE_MIN: u32 = 1 << 20; // 1 MiB
pub(super) const BLOCK_SIZE_MIN: u32 = 1 << 20; // 1 MiB
const BLOCK_SIZE_MAX: u32 = 256 << 20; // 256 MiB
const MAX_SECTORS_PER_BLOCK: u64 = 1 << 23;
@@ -93,10 +93,10 @@ pub enum VhdxMetadataError {
UnsupportedFlag,
}
pub type Result<T> = result::Result<T, VhdxMetadataError>;
pub(super) type Result<T> = result::Result<T, VhdxMetadataError>;
#[derive(Default, Clone, Debug)]
pub struct DiskSpec {
pub(super) struct DiskSpec {
pub disk_id: u128,
pub image_size: u64,
pub block_size: u32,
@@ -112,7 +112,7 @@ pub struct DiskSpec {
impl DiskSpec {
/// Parse all metadata from the provided file and store info in DiskSpec
/// structure.
pub fn new(f: &AlignedFile, metadata_region: &RegionTableEntry) -> Result<DiskSpec> {
pub(super) fn new(f: &AlignedFile, metadata_region: &RegionTableEntry) -> Result<DiskSpec> {
let mut disk_spec = DiskSpec::default();
let mut metadata_presence: u16 = 0;
let mut offset = 0;
@@ -270,7 +270,7 @@ struct MetadataTableHeader {
}
impl MetadataTableHeader {
pub fn new(buffer: &[u8]) -> Result<MetadataTableHeader> {
pub(crate) fn new(buffer: &[u8]) -> Result<MetadataTableHeader> {
let metadata_table_header = MetadataTableHeader::read_from_bytes(buffer).unwrap();
if metadata_table_header.signature != METADATA_SIGN {
@@ -291,7 +291,7 @@ impl MetadataTableHeader {
#[repr(C, packed)]
#[derive(Default, Debug, Clone, Copy, FromBytes)]
pub struct MetadataTableEntry {
pub(super) struct MetadataTableEntry {
item_id: [u8; 16],
offset: u32,
length: u32,

View File

@@ -9,19 +9,23 @@
//! Provides [`VhdxDisk`], the `DiskFile` wrapper for dynamic VHDX
//! images.
pub mod internal;
mod bat;
mod engine_sync;
mod header;
mod io;
mod metadata;
mod parser;
#[cfg(test)]
pub(crate) mod test_util;
pub(crate) mod worker;
mod test_util;
use std::fs::File;
use std::io;
use std::io::Error as IoError;
use std::os::fd::AsRawFd;
use std::sync::{Arc, Mutex};
pub use internal::{Vhdx, VhdxError};
pub use parser::{Vhdx, VhdxError};
use self::worker::sync::VhdxSync;
use self::engine_sync::VhdxSync;
use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError};
use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp};
use crate::{Error, disk_file};
@@ -92,7 +96,7 @@ impl disk_file::Resizable for VhdxDisk {
fn resize(&mut self, _size: u64) -> BlockResult<()> {
Err(BlockError::new(
BlockErrorKind::UnsupportedFeature,
DiskFileError::ResizeError(io::Error::other("resize not supported for VHDX")),
DiskFileError::ResizeError(IoError::other("resize not supported for VHDX")),
)
.with_op(ErrorOp::Resize))
}

View File

@@ -13,17 +13,12 @@ use std::result;
use remain::sorted;
use thiserror::Error;
use self::bat::{BatEntry, VhdxBatError};
use self::header::{RegionInfo, RegionTableEntry, VhdxHeader, VhdxHeaderError};
use self::io::VhdxIoError;
use self::metadata::{DiskSpec, VhdxMetadataError};
use super::bat::{BatEntry, VhdxBatError};
use super::header::{self, RegionInfo, RegionTableEntry, VhdxHeader, VhdxHeaderError};
use super::io::{self, VhdxIoError};
use super::metadata::{DiskSpec, VhdxMetadataError};
use crate::aligned_file::AlignedFile;
mod bat;
mod header;
mod io;
mod metadata;
#[sorted]
#[derive(Error, Debug)]
pub enum VhdxError {
@@ -43,7 +38,7 @@ pub enum VhdxError {
WriteFailed(#[source] VhdxIoError),
}
pub type Result<T> = result::Result<T, VhdxError>;
pub(super) type Result<T> = result::Result<T, VhdxError>;
#[derive(Debug)]
pub struct Vhdx {

View File

@@ -1,7 +0,0 @@
// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0
//! Sync I/O worker for VHDX images.
pub(crate) mod sync;