From 25afb8898c92a3f031c46facbd5c9caed23dce22 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Sat, 25 Apr 2026 14:43:56 +0200 Subject: [PATCH] block: Move QCOW2 format files into formats/qcow/ Move QCOW2 format implementation into a structured directory layout: qcow/ -> formats/qcow/internal/ (filenames unchanged) qcow_disk.rs -> formats/qcow/mod.rs (QcowDisk) qcow_sync.rs -> formats/qcow/worker/sync.rs (QcowSync) qcow_async.rs -> formats/qcow/worker/async_uring.rs (QcowAsync) qcow_common.rs -> formats/qcow/common.rs All internal cross references continue to resolve through re-exports in lib.rs: formats::qcow::internal as qcow, formats::qcow as qcow_disk, and formats::qcow::common as qcow_common. Signed-off-by: Anatol Belski --- block/src/factory.rs | 2 +- block/src/formats/mod.rs | 1 + .../qcow/common.rs} | 6 +++-- .../qcow/internal}/backing.rs | 8 +++--- .../qcow/internal}/decoder.rs | 0 .../{qcow => formats/qcow/internal}/header.rs | 0 .../qcow/internal}/metadata.rs | 0 .../{qcow => formats/qcow/internal}/mod.rs | 12 ++++----- .../qcow/internal}/qcow_raw_file.rs | 0 .../qcow/internal}/raw_file.rs | 0 .../qcow/internal}/refcount.rs | 4 +-- .../{qcow => formats/qcow/internal}/util.rs | 0 .../qcow/internal}/vec_cache.rs | 0 .../src/{qcow_disk.rs => formats/qcow/mod.rs} | 25 +++++++++++++------ .../qcow/worker/async_uring.rs} | 24 +++++++++--------- block/src/formats/qcow/worker/mod.rs | 9 +++++++ .../qcow/worker/sync.rs} | 24 ++++++++++-------- block/src/lib.rs | 7 +----- performance-metrics/src/util.rs | 2 +- 19 files changed, 71 insertions(+), 53 deletions(-) rename block/src/{qcow_common.rs => formats/qcow/common.rs} (99%) rename block/src/{qcow => formats/qcow/internal}/backing.rs (96%) rename block/src/{qcow => formats/qcow/internal}/decoder.rs (100%) rename block/src/{qcow => formats/qcow/internal}/header.rs (100%) rename block/src/{qcow => formats/qcow/internal}/metadata.rs (100%) rename block/src/{qcow => formats/qcow/internal}/mod.rs (99%) rename block/src/{qcow => formats/qcow/internal}/qcow_raw_file.rs (100%) rename block/src/{qcow => formats/qcow/internal}/raw_file.rs (100%) rename block/src/{qcow => formats/qcow/internal}/refcount.rs (99%) rename block/src/{qcow => formats/qcow/internal}/util.rs (100%) rename block/src/{qcow => formats/qcow/internal}/vec_cache.rs (100%) rename block/src/{qcow_disk.rs => formats/qcow/mod.rs} (93%) rename block/src/{qcow_async.rs => formats/qcow/worker/async_uring.rs} (99%) create mode 100644 block/src/formats/qcow/worker/mod.rs rename block/src/{qcow_sync.rs => formats/qcow/worker/sync.rs} (99%) diff --git a/block/src/factory.rs b/block/src/factory.rs index ba9abbe81..9877712ea 100644 --- a/block/src/factory.rs +++ b/block/src/factory.rs @@ -20,10 +20,10 @@ use log::info; use crate::block_io_uring_is_supported; use crate::disk_file::AsyncFullDiskFile; use crate::error::{BlockError, BlockErrorKind, BlockResult}; +use crate::formats::qcow::QcowDisk; use crate::formats::raw::{RawBackend, RawDisk}; use crate::formats::vhd::VhdDisk; use crate::formats::vhdx::VhdxDisk; -use crate::qcow_disk::QcowDisk; use crate::{ ImageType, block_aio_is_supported, detect_image_type, open_disk_image, preallocate_disk, }; diff --git a/block/src/formats/mod.rs b/block/src/formats/mod.rs index ba1697320..d199e9cc2 100644 --- a/block/src/formats/mod.rs +++ b/block/src/formats/mod.rs @@ -7,6 +7,7 @@ //! Each format lives in its own submodule with a `DiskFile` wrapper, //! format specific internals, and sync/async I/O workers. +pub mod qcow; pub mod raw; pub mod vhd; pub mod vhdx; diff --git a/block/src/qcow_common.rs b/block/src/formats/qcow/common.rs similarity index 99% rename from block/src/qcow_common.rs rename to block/src/formats/qcow/common.rs index df70c7b0c..1e946fe60 100644 --- a/block/src/qcow_common.rs +++ b/block/src/formats/qcow/common.rs @@ -14,7 +14,9 @@ use std::alloc::{Layout, alloc_zeroed, dealloc}; use std::os::fd::RawFd; use std::{io, slice}; -use crate::qcow::decoder::Decoder; +#[cfg(test)] +use super::internal; +use super::internal::decoder::Decoder; // -- Position independent I/O helpers -- // @@ -201,8 +203,8 @@ pub(crate) mod unit_tests { use flate2::write::DeflateEncoder; use vmm_sys_util::tempfile::TempFile; + use super::internal::decoder::ZlibDecoder; use super::{decompress_cluster, pread_alloc}; - use crate::qcow::decoder::ZlibDecoder; const COMPRESSED_FLAG: u64 = 1 << 62; const CLUSTER_USED_FLAG: u64 = 1 << 63; diff --git a/block/src/qcow/backing.rs b/block/src/formats/qcow/internal/backing.rs similarity index 96% rename from block/src/qcow/backing.rs rename to block/src/formats/qcow/internal/backing.rs index 6b8448861..c680fc0fd 100644 --- a/block/src/qcow/backing.rs +++ b/block/src/formats/qcow/internal/backing.rs @@ -10,11 +10,11 @@ use std::io; use std::os::fd::{AsFd, AsRawFd, BorrowedFd, OwnedFd}; use std::sync::Arc; +use super::decoder::Decoder; +use super::metadata::{BackingRead, ClusterReadMapping, QcowMetadata}; +use super::{BackingFile, BackingKind, Error as QcowError}; use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp}; -use crate::qcow::decoder::Decoder; -use crate::qcow::metadata::{BackingRead, ClusterReadMapping, QcowMetadata}; -use crate::qcow::{BackingFile, BackingKind, Error as QcowError}; -use crate::qcow_common::{decompress_cluster, pread_alloc, pread_exact}; +use crate::formats::qcow::common::{decompress_cluster, pread_alloc, pread_exact}; /// Raw backing file using pread64 on a duplicated fd. pub(crate) struct RawBacking { diff --git a/block/src/qcow/decoder.rs b/block/src/formats/qcow/internal/decoder.rs similarity index 100% rename from block/src/qcow/decoder.rs rename to block/src/formats/qcow/internal/decoder.rs diff --git a/block/src/qcow/header.rs b/block/src/formats/qcow/internal/header.rs similarity index 100% rename from block/src/qcow/header.rs rename to block/src/formats/qcow/internal/header.rs diff --git a/block/src/qcow/metadata.rs b/block/src/formats/qcow/internal/metadata.rs similarity index 100% rename from block/src/qcow/metadata.rs rename to block/src/formats/qcow/internal/metadata.rs diff --git a/block/src/qcow/mod.rs b/block/src/formats/qcow/internal/mod.rs similarity index 99% rename from block/src/qcow/mod.rs rename to block/src/formats/qcow/internal/mod.rs index 9be4190d2..96606e1da 100644 --- a/block/src/qcow/mod.rs +++ b/block/src/formats/qcow/internal/mod.rs @@ -40,6 +40,9 @@ use header::{ use libc::{EINVAL, EIO, ENOSPC}; use log::{error, warn}; use metadata::ClusterReadMapping; +use qcow_raw_file::{BeUint, QcowRawFile}; +pub use raw_file::RawFile; +use refcount::RefCount; use remain::sorted; use thiserror::Error; pub(crate) use util::MAX_NESTING_DEPTH; @@ -49,17 +52,14 @@ use util::{ l2_entry_is_zero, l2_entry_make_std, l2_entry_make_zero, l2_entry_make_zero_plain, l2_entry_std_cluster_addr, }; +use vec_cache::{CacheMap, Cacheable, VecCache}; use vmm_sys_util::file_traits::{FileSetLen, FileSync}; use vmm_sys_util::seek_hole::SeekHole; use vmm_sys_util::write_zeroes::{PunchHole, WriteZeroesAt}; +use super::common::decompress_cluster; use crate::BlockBackend; use crate::error::{BlockError, BlockErrorKind, BlockResult}; -use crate::qcow::qcow_raw_file::{BeUint, QcowRawFile}; -pub use crate::qcow::raw_file::RawFile; -use crate::qcow::refcount::RefCount; -use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache}; -use crate::qcow_common::decompress_cluster; #[sorted] #[derive(Debug, Error)] @@ -2426,7 +2426,7 @@ mod unit_tests { use super::util::{COMPRESSED_FLAG, ZERO_FLAG}; use super::*; - use crate::qcow_common::unit_tests::compress_allocated_clusters; + use crate::formats::qcow::common::unit_tests::compress_allocated_clusters; fn valid_header_v3() -> Vec { vec![ diff --git a/block/src/qcow/qcow_raw_file.rs b/block/src/formats/qcow/internal/qcow_raw_file.rs similarity index 100% rename from block/src/qcow/qcow_raw_file.rs rename to block/src/formats/qcow/internal/qcow_raw_file.rs diff --git a/block/src/qcow/raw_file.rs b/block/src/formats/qcow/internal/raw_file.rs similarity index 100% rename from block/src/qcow/raw_file.rs rename to block/src/formats/qcow/internal/raw_file.rs diff --git a/block/src/qcow/refcount.rs b/block/src/formats/qcow/internal/refcount.rs similarity index 99% rename from block/src/qcow/refcount.rs rename to block/src/formats/qcow/internal/refcount.rs index 5cd61c09b..fa9077a37 100644 --- a/block/src/qcow/refcount.rs +++ b/block/src/formats/qcow/internal/refcount.rs @@ -9,8 +9,8 @@ use std::io; use libc::EINVAL; use thiserror::Error; -use crate::qcow::qcow_raw_file::QcowRawFile; -use crate::qcow::vec_cache::{CacheMap, Cacheable, VecCache}; +use super::qcow_raw_file::QcowRawFile; +use super::vec_cache::{CacheMap, Cacheable, VecCache}; #[derive(Debug, Error)] pub enum Error { diff --git a/block/src/qcow/util.rs b/block/src/formats/qcow/internal/util.rs similarity index 100% rename from block/src/qcow/util.rs rename to block/src/formats/qcow/internal/util.rs diff --git a/block/src/qcow/vec_cache.rs b/block/src/formats/qcow/internal/vec_cache.rs similarity index 100% rename from block/src/qcow/vec_cache.rs rename to block/src/formats/qcow/internal/vec_cache.rs diff --git a/block/src/qcow_disk.rs b/block/src/formats/qcow/mod.rs similarity index 93% rename from block/src/qcow_disk.rs rename to block/src/formats/qcow/mod.rs index ef2730526..b8d598e5b 100644 --- a/block/src/qcow_disk.rs +++ b/block/src/formats/qcow/mod.rs @@ -2,21 +2,30 @@ // // SPDX-License-Identifier: Apache-2.0 +//! QCOW2 disk image format. +//! +//! Provides [`QcowDisk`], the `DiskFile` wrapper for QCOW2 images +//! with backing file and compression support. + +pub(crate) mod common; +pub mod internal; +pub mod worker; + use std::fs::File; use std::os::unix::io::AsRawFd; use std::sync::Arc; use std::{fmt, io}; +use self::internal::backing::shared_backing_from; +use self::internal::metadata::{BackingRead, QcowMetadata}; +use self::internal::qcow_raw_file::QcowRawFile; +use self::internal::{MAX_NESTING_DEPTH, RawFile, parse_qcow}; +#[cfg(feature = "io_uring")] +use self::worker::async_uring::QcowAsync; +use self::worker::sync::QcowSync; use crate::async_io::{AsyncIo, BorrowedDiskFd, DiskFileError}; use crate::disk_file; use crate::error::{BlockError, BlockErrorKind, BlockResult, ErrorOp}; -use crate::qcow::backing::shared_backing_from; -use crate::qcow::metadata::{BackingRead, QcowMetadata}; -use crate::qcow::qcow_raw_file::QcowRawFile; -use crate::qcow::{MAX_NESTING_DEPTH, RawFile, parse_qcow}; -#[cfg(feature = "io_uring")] -use crate::qcow_async::QcowAsync; -use crate::qcow_sync::QcowSync; /// Unified DiskFile wrapper for QCOW2 disk images. /// @@ -191,10 +200,10 @@ impl disk_file::AsyncDiskFile for QcowDisk { mod unit_tests { use vmm_sys_util::tempfile::TempFile; + use self::internal::{QcowFile, RawFile}; use super::*; use crate::async_io::AsyncIo; use crate::disk_file::{AsyncDiskFile, DiskSize, PhysicalSize}; - use crate::qcow::{QcowFile, RawFile}; const TEST_SIZE: u64 = 0x5566_7788; diff --git a/block/src/qcow_async.rs b/block/src/formats/qcow/worker/async_uring.rs similarity index 99% rename from block/src/qcow_async.rs rename to block/src/formats/qcow/worker/async_uring.rs index 32451f0be..a30198228 100644 --- a/block/src/qcow_async.rs +++ b/block/src/formats/qcow/worker/async_uring.rs @@ -16,19 +16,19 @@ use std::sync::Arc; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::write_zeroes::{PunchHole, WriteZeroesAt}; +use super::common::{ + AlignedBuf, aligned_pread, aligned_pwrite, decompress_cluster, pread_alloc, pread_exact, + pwrite_all, +}; +use super::internal::decoder::Decoder; +use super::internal::metadata::{ + BackingRead, ClusterReadMapping, ClusterWriteMapping, DeallocAction, QcowMetadata, +}; +use super::internal::qcow_raw_file::QcowRawFile; use crate::SECTOR_SIZE; use crate::async_io::{ AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult, UringDataIo, }; -use crate::qcow::decoder::Decoder; -use crate::qcow::metadata::{ - BackingRead, ClusterReadMapping, ClusterWriteMapping, DeallocAction, QcowMetadata, -}; -use crate::qcow::qcow_raw_file::QcowRawFile; -use crate::qcow_common::{ - AlignedBuf, aligned_pread, aligned_pwrite, decompress_cluster, pread_alloc, pread_exact, - pwrite_all, -}; /// Per queue QCOW2 I/O worker using io_uring. /// @@ -534,9 +534,9 @@ mod unit_tests { use crate::SECTOR_SIZE; use crate::async_io::{AsyncIoCompletion, AsyncIoOperation, GuestMemoryTarget, OwnedIoBuffer}; use crate::disk_file::AsyncDiskFile; - use crate::qcow::{BackingFileConfig, ImageType, QcowFile, RawFile}; - use crate::qcow_common::unit_tests::compress_allocated_clusters; - use crate::qcow_disk::QcowDisk; + use crate::formats::qcow::QcowDisk; + use crate::formats::qcow::common::unit_tests::compress_allocated_clusters; + use crate::formats::qcow::internal::{BackingFileConfig, ImageType, QcowFile, RawFile}; fn create_disk_with_data( file_size: u64, diff --git a/block/src/formats/qcow/worker/mod.rs b/block/src/formats/qcow/worker/mod.rs new file mode 100644 index 000000000..6da78e821 --- /dev/null +++ b/block/src/formats/qcow/worker/mod.rs @@ -0,0 +1,9 @@ +// Copyright 2026 The Cloud Hypervisor Authors. All rights reserved. +// +// SPDX-License-Identifier: Apache-2.0 + +#[cfg(feature = "io_uring")] +pub(crate) mod async_uring; +pub(crate) mod sync; + +pub(crate) use super::{common, internal}; diff --git a/block/src/qcow_sync.rs b/block/src/formats/qcow/worker/sync.rs similarity index 99% rename from block/src/qcow_sync.rs rename to block/src/formats/qcow/worker/sync.rs index e7a3e5a63..219d598b8 100644 --- a/block/src/qcow_sync.rs +++ b/block/src/formats/qcow/worker/sync.rs @@ -12,16 +12,16 @@ use std::sync::Arc; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::write_zeroes::{PunchHole, WriteZeroesAt}; -use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult}; -use crate::qcow::decoder::Decoder; -use crate::qcow::metadata::{ - BackingRead, ClusterReadMapping, ClusterWriteMapping, DeallocAction, QcowMetadata, -}; -use crate::qcow::qcow_raw_file::QcowRawFile; -use crate::qcow_common::{ +use super::common::{ AlignedBuf, aligned_pread, aligned_pwrite, decompress_cluster, pread_alloc, pread_exact, pwrite_all, }; +use super::internal::decoder::Decoder; +use super::internal::metadata::{ + BackingRead, ClusterReadMapping, ClusterWriteMapping, DeallocAction, QcowMetadata, +}; +use super::internal::qcow_raw_file::QcowRawFile; +use crate::async_io::{AsyncIo, AsyncIoCompletion, AsyncIoError, AsyncIoOperation, AsyncIoResult}; pub struct QcowSync { metadata: Arc, @@ -351,11 +351,11 @@ mod unit_tests { use crate::async_io::{AsyncIoCompletion, OwnedIoBuffer}; use crate::disk_file::{AsyncDiskFile, DiskSize, Resizable}; use crate::error::BlockErrorKind; - use crate::qcow::{ + use crate::formats::qcow::QcowDisk; + use crate::formats::qcow::common::unit_tests::compress_allocated_clusters; + use crate::formats::qcow::internal::{ BackingFileConfig, Error as QcowError, ImageType, QcowFile, QcowHeader, RawFile, }; - use crate::qcow_common::unit_tests::compress_allocated_clusters; - use crate::qcow_disk::QcowDisk; const TEST_L1_L2_ADDR_MASK: u64 = 0x00ff_ffff_ffff_fe00; const TEST_HEADER_L1_TABLE_OFFSET: u64 = 40; @@ -893,7 +893,9 @@ mod unit_tests { .to_string_lossy() .into_owned(); match err.downcast_ref::() { - Some(QcowError::BackingFileIo(path, _)) => assert_eq!(path, &expected_path), + Some(QcowError::BackingFileIo(path, _)) => { + assert_eq!(path.as_str(), expected_path.as_str()); + } other => panic!("unexpected error: {other:?}"), } } diff --git a/block/src/lib.rs b/block/src/lib.rs index 18e92b3c0..891c1329c 100644 --- a/block/src/lib.rs +++ b/block/src/lib.rs @@ -15,12 +15,6 @@ pub mod factory; mod io_impl; pub use io_impl::{async_io, fcntl, request}; pub mod formats; -pub mod qcow; -#[cfg(feature = "io_uring")] -pub(crate) mod qcow_async; -pub(crate) mod qcow_common; -pub mod qcow_disk; -pub(crate) mod qcow_sync; mod sparse; use std::alloc::{Layout, alloc_zeroed}; use std::fmt::{self, Debug}; @@ -33,6 +27,7 @@ use std::path::Path; use std::str::FromStr; use std::{cmp, mem, result}; +pub use formats::qcow::internal as qcow; pub use formats::raw as raw_disk; pub use formats::vhdx::internal as vhdx; #[cfg(feature = "io_uring")] diff --git a/performance-metrics/src/util.rs b/performance-metrics/src/util.rs index eed4d5e14..dc632970d 100644 --- a/performance-metrics/src/util.rs +++ b/performance-metrics/src/util.rs @@ -15,8 +15,8 @@ use std::thread; use std::time::Duration; use block::async_io::{AsyncIo, GuestMemoryTarget}; +use block::formats::qcow::QcowDisk; use block::qcow::{BackingFileConfig, ImageType, QcowFile, RawFile}; -use block::qcow_disk::QcowDisk; use vm_memory::{Bytes, GuestAddress, GuestMemoryMmap}; use vmm_sys_util::eventfd::EventFd; use vmm_sys_util::tempfile::TempFile;