mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
committed by
Rob Bradford
parent
6e0c39964a
commit
039b4e6013
@@ -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],
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
@@ -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;
|
||||
Reference in New Issue
Block a user