Commit Graph

61 Commits

Author SHA1 Message Date
Julian Schindel
2b6e9df4e3 block: replace as <pointer> casts with safer alternatives
`as` casts can change mutability, which quickly leads to undefined
behavior.

Signed-off-by: Julian Schindel <mail@arctic-alpaca.de>
2026-05-03 08:38:31 +00:00
Anatol Belski
587093ddfd block: qcow: Remove old wrapper structs, restrict visibility
Delete QcowDiskSync and QcowDiskAsync wrapper structs along with
their DiskFile trait impls. Only the AsyncIo worker structs
QcowSync and QcowAsync remain. Reduce module visibility of
qcow_sync and qcow_async to pub(crate).

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-27 11:19:37 +00:00
Anatol Belski
8a77feb813 block: qcow: Update existing tests to use QcowDisk
Replace QcowDiskSync and QcowDiskAsync constructors in the
qcow_sync and qcow_async test modules with QcowDisk::new,
passing use_io_uring=false and use_io_uring=true respectively.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-27 11:19:37 +00:00
Anatol Belski
27ee36449c block: qcow: Add unified QcowDisk wrapper
Introduce QcowDisk, a unified DiskFile implementation for QCOW2
disk images that handles backend selection at runtime via a
use_io_uring flag, matching the pattern used by FixedVhdDisk.

The wrapper delegates to QcowSync or QcowAsync based on the flag
and includes a compile time guard that returns an error when
io_uring is requested but the feature is not enabled.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-27 11:19:37 +00:00
Anatol Belski
21cd13df01 block: Rename AsyncDiskFile::new_async_io to create_async_io
The new_ prefix in Rust conventionally denotes constructors that return
Self (e.g. Vec::new(), File::new()). AsyncDiskFile::new_async_io does
not return Self. It is a factory method that constructs and returns a
Box<dyn AsyncIo> worker bound to the disk file descriptor and
metadata. The create_ prefix communicates this: the caller receives
a freshly constructed object of a different type.

This rename touches every format backend in block plus two external
callers in virtio-devices and performance-metrics. Every change is a
mechanical s/new_async_io/create_async_io/ substitution. No functional
change.

Ref: #7877 (task 3.2.8)
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-21 10:36:52 +00:00
Anatol Belski
16abb28b85 block: qcow: Test compressed cluster read via QcowDiskSync
Write a known data pattern to a QCOW2 image, convert all allocated
clusters to compressed format using compress_allocated_clusters,
reopen the image through QcowDiskSync, and verify that reading back
the full cluster returns the original data.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-20 18:09:12 +00:00
Anatol Belski
5504ad753a block: qcow: Move compressed read decompression out of lock
Move decompression of compressed QCOW2 clusters out of the metadata
lock. Previously, reading a compressed cluster acquired a write lock
on metadata to perform in place decompression. Now, try_map_read
extracts the compressed layout (host offset, size) under a read lock
and returns it in the ClusterReadMapping::Compressed variant. Each
consumer (QcowSync, QcowAsync, Qcow2Backing, QcowFile) performs the
pread and decompression at the call site without holding any lock,
using the pread_alloc and decompress_cluster helpers.

Create the decoder once in QcowMetadata as Arc<dyn Decoder> and
share it via Arc::clone to QcowAsync, QcowSync, and Qcow2Backing
at construction time. This avoids per read RwLock acquisitions and
heap allocations. Add Send + Sync bounds to the Decoder trait.

This eliminates write lock contention on compressed reads, allowing
them to proceed concurrently with other read operations.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-20 18:09:12 +00:00
Anatol Belski
659f7c17e5 block: qcow: Cache cluster_size in per queue structs
Cache the immutable cluster_size value at construction time in
QcowAsync, QcowSync, and Qcow2Backing. This avoids repeated RwLock
read acquisitions on the hot write and deallocation paths.

Replace QcowMetadata::cluster_offset() calls with inline bitmask
operations using the cached cluster_size. Remove the now unused
cluster_offset() method from QcowMetadata.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-20 18:09:12 +00:00
Anatol Belski
dc0e003be0 block: qcow: Add AlignedBuf size rounding test
Verify that AlignedBuf rounds the allocation size up to the
requested alignment. Passes under miri.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
a84a0b8b25 block: qcow: Add AlignedBuf allocation and access test
Test AlignedBuf with 512 and 4096 byte alignment. Verify pointer
alignment, zero initialization, and write/read round trip. Passes
under miri.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
ab81112618 block: qcow: Test aligned pread and pwrite with 4096 alignment
Exercise both aligned_pread and aligned_pwrite with 4096 byte
alignment instead of 512. Verify written data and that surrounding
regions are preserved.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
7aa477936e block: qcow: Test aligned_pwrite unaligned offset
Write at offset 100 with alignment 512 so the read modify write
path is exercised. Verify the written region and that surrounding
data is preserved.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
5ed9f2e3d8 block: qcow: Test aligned_pwrite bounce unaligned buffer
Write 4096 bytes via plain Vec<u8> whose address is not guaranteed
to be aligned. The bounce buffer path copies data into an aligned
allocation before the syscall. Read back with pread_exact to verify
data integrity.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
32af2f2a22 block: qcow: Test aligned_pwrite pass through path
Write 4096 bytes of pattern data at offset 0 using AlignedBuf
and verify data integrity via plain pread_exact. All parameters
are naturally aligned to 512 so the fast path is exercised.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
05d52d0353 block: qcow: Add aligned_pread unaligned offset test
Test that aligned_pread handles a non aligned offset by
rounding down, reading an aligned region, and returning the
correct slice from within the bounce buffer.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
021838b63c block: qcow: Add aligned_pread bounce buffer test
Test that aligned_pread correctly uses a bounce buffer when
the caller buffer address is not aligned.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
fe711b3a0b block: qcow: Add aligned_pread pass through test
Test that aligned_pread takes the fast path when buffer
address, length, and offset are all properly aligned.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
7fd5e74f0e block: qcow: Add multi iovec read/write test
Exercise scatter/gather with multiple iovecs per operation,
covering both the standard and direct_io paths. Write uses
3 iovecs with distinct patterns, read uses 3 iovecs with
different sizes, then reassembles and compares.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
b62525f792 block: qcow: Add direct_io test coverage for QcowSync
Add direct_io variants for suitable tests by extracting
test bodies into _impl(direct_io: bool) functions. Each
original test calls _impl(false) and a new _direct_io test
calls _impl(true).

When direct_io is true, RawFile probes alignment and QcowSync
exercises the AlignedBuf and bounce buffer paths in
read_vectored and write_vectored.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
fd8495b342 block: qcow: Use aligned I/O in QcowSync
Store the alignment from the data file in QcowSync. Use AlignedBuf
directly in read_vectored and write_vectored as the intermediate
buffer so that aligned_pread/aligned_pwrite can skip the bounce
copy when offset and length are naturally aligned.

Use gather_from_iovecs_into to gather iovec data directly into the
aligned buffer.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 17:28:58 +00:00
Anatol Belski
c35749fb39 block: qcow: Rename Qcow2MetadataBacking to Qcow2Backing
The old name read as 'metadata for a QCOW2 backing file' rather
than what it actually is: a QCOW2 backing file reader. Rename to
Qcow2Backing to parallel RawBacking and clarify intent.

Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-15 14:40:14 +00:00
Anatol Belski
8cd2c957ef block: qcow: Move shared_backing_from to qcow/backing
Move the backing file constructor into qcow/backing alongside the
types it creates. Both qcow_sync and qcow_async can now import
shared_backing_from directly from qcow/backing.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-14 22:11:26 +00:00
Anatol Belski
5ec80d45ab block: qcow: Move Qcow2MetadataBacking to qcow/backing
Move the QCOW2 metadata backed reader into qcow/backing alongside
RawBacking.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-14 22:11:26 +00:00
Anatol Belski
e345299f4d block: qcow: Move RawBacking to qcow/backing module
Move the raw backing file reader into the new qcow/backing module
so it can be shared between qcow_sync and the upcoming qcow_async
backend.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-14 22:11:26 +00:00
Anatol Belski
81f43f96c3 block: qcow: Move iovec scatter/gather helpers to qcow_common
Move scatter_to_iovecs, zero_fill_iovecs and gather_from_iovecs into
qcow_common so they can be shared with the upcoming qcow_async backend.

These helpers treat an iovec array as a flat byte stream and are used by
both read_vectored and write_vectored code paths.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-14 22:11:26 +00:00
Anatol Belski
7f3dfe2154 block: qcow: Extract positional I/O helpers into a common module
These position independent I/O helpers use pread64/pwrite64 to avoid
races on the shared file position when multiple queues operate on
duplicated file descriptors. Extracting them prepares for reuse by
the upcoming qcow_async backend.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-04-14 22:11:26 +00:00
Anatol Belski
be9ef116aa block: qcow: Switch parse_qcow and BackingFile::new to BlockResult
Switch parse_qcow and BackingFile::new from qcow::Result to
BlockResult. Every early return site now produces an explicit
BlockError with the appropriate kind. Remaining internal calls to
functions still on qcow::Result rely on the From scaffolding and
will be converted in subsequent commits.

Two helpers are added to BlockError. with_kind replaces the
classification on an existing error, used in QcowDiskSync::new to
avoid double wrapping when the caller needs a different kind.
into_source consumes the error and returns the boxed source, used
at the recursive BackingFile open to extract the qcow::Error for
BackingFileOpen without letting qcow::Error hold a BlockError.

The qcow_sync boundary is simplified to a single closure that
operates on the BlockError already returned by parse_qcow.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
0d062962ac block: qcow: Remove async_io::DiskFile impl from QcowDiskSync
QcowDiskSync now exclusively uses disk_file::DiskFile and
disk_file::AsyncDiskFile. The old async_io::DiskFile impl is removed
along with its unused imports (DiskFile, DiskFileError, DiskFileResult).

Tests are updated to import the new traits.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
fe6e3e8fef block: qcow_sync: impl AsyncDiskFile for QcowDiskSync
Implement try_clone by sharing the metadata Arc and cloning the data
file descriptor. The new_async_io method creates a QcowSync worker
identical to the async_io::DiskFile version.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
1fc8e4adb6 block: qcow_sync: impl DiskFile for QcowDiskSync
Marker impl binding the DiskSize and HasTopology supertraits.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
f35bec19e8 block: qcow_sync: impl Resizable for QcowDiskSync
Add ErrorOp::Resize variant and implement the Resizable trait.
Resize is rejected when a backing file is present.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
554562fef2 block: qcow_sync: impl SparseCapable for QcowDiskSync
Advertise support for sparse operations and the zero flag. QCOW2
inherently supports both through cluster deallocation.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
63f5e6e97f block: qcow_sync: impl Geometry for QcowDiskSync
Uses the default DiskTopology (512B logical/physical) since
QCOW2 does not probe the underlying device geometry.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
b305a7670b block: qcow_sync: impl DiskFd for QcowDiskSync
Borrows the raw file descriptor from the underlying QcowRawFile
for fcntl() operations. Uses &self for shared access.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
4b731ee771 block: qcow_sync: impl PhysicalSize for QcowDiskSync
Delegate to QcowRawFile::physical_size() which returns the actual
host allocation size of the QCOW2 container file.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
0a7b6b089b block: qcow_sync: impl DiskSize for QcowDiskSync
Delegate to QcowMetadata::virtual_size() which returns the guest
visible capacity stored in the QCOW2 header.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
ad789024f9 block: qcow_sync: Add Debug impl for QcowDiskSync
The new composable traits require Debug. Implement it manually since
QcowMetadata contains RwLock state that cannot auto derive.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
2bcbe25539 block: qcow: Add backing file path to qcow error context
Extend the BackingFileIo and BackingFileOpen variants of
qcow::Error with a path field so that backing file failures
report which file was involved. The path is populated from
the backing file configuration.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
58bdfaee3a block: qcow: QcowDiskSync returns BlockResult with path context
Change QcowDiskSync::new() to return BlockResult instead of
qcow::Result, mapping format specific errors to the appropriate
BlockErrorKind at the crate boundary. The vmm caller attaches
the disk image path to the error so failures identify which
file was being opened.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
fd6891db62 block: qcow: Extend unit tests
Add tests for multiqueue concurrent reads, raw and QCOW2 backing
files, three layer backing chains, COW on partial cluster writes,
discard with backing fallthrough, cross cluster boundary operations,
reads beyond virtual size, and resize.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Anatol Belski
57e89b04f6 block: qcow: Refactor BackingFile for ownership based decomposition
Replace the clone based BackingFileOps trait with a BackingKind enum
so backing files can be decomposed into their concrete owned types.

BackingFile::new() for QCOW2 backings now calls parse_qcow() directly
instead of building a full QcowFile. Remove Clone for BackingFile and
QcowFile.

Prerequisite for the qcow_sync rewrite which decomposes a BackingFile
into a raw fd or QcowMetadata for lock free I/O.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Anatol Belski
4d30ba12c8 block: qcow: Add test for BackingFilesDisabled error
Verify that opening a QCOW2 image with a backing file reference
through QcowDiskSync with backing_files=off produces the user-facing
BackingFilesDisabled error rather than MaxNestingDepthExceeded.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-19 13:48:40 +00:00
Anatol Belski
94368c622e block: Add BackingFilesDisabled error for actionable user guidance
When a QCOW2 image has a backing file but backing_files=on is not set,
the error was MaxNestingDepthExceeded which gives no indication that
this is a policy decision or how to resolve it.

Add a BackingFilesDisabled error variant whose message indicates that
backing file support is disabled and references the backing_files
option. The translation from MaxNestingDepthExceeded to
BackingFilesDisabled happens at the QcowDiskSync boundary where the
policy decision is made, preserving the original error for genuine
recursive depth exhaustion.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-19 13:48:40 +00:00
Anatol Belski
4676fdb494 block: Add unit tests for DISCARD zero flag
Add comprehensive tests for DISCARD and WRITE_ZEROES operations:

QCOW2 zero flag test validates the complete workflow: allocate
cluster, DISCARD it, verify reads return zeros, write new data,
verify cluster reallocated.

QcowSync tests verify punch_hole and write_zeroes with Arc<Mutex<>>
sharing, including tests for cache consistency with multiple async
I/O operations.

RawFileSync tests verify punch_hole and write_zeroes using
fallocate.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
6c94975c80 block: qcow: Implement punch_hole and write_zeroes for QcowSync
Implement punch_hole and write_zeroes for QcowSync backend by
delegating to QcowFile::punch_hole which triggers cluster
deallocation. write_zeroes delegates to punch_hole as unallocated
clusters read as zeros in QCOW2.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
0a287793df block: qcow: Thread sparse configuration to QCOW2 constructors
Add sparse parameter to QcowFile constructors and propagate it from
device_manager through QcowDiskSync. This makes the sparse configuration
available throughout the QCOW2 implementation for controlling allocation
and deallocation behavior.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
46e6ecddfe block: Add supports_zero_flag trait method
Add supports_zero_flag() to DiskFile trait to indicate whether a disk
format can mark clusters/blocks as reading zeros without deallocating
storage.

QCOW2 supports this via the zero flag in L2 entries. VHDX also has
PAYLOAD_BLOCK_ZERO state for this, though it's not yet implemented in
cloud-hypervisor.

This enables DISCARD to be advertised even with sparse=false for formats
with zero-flag support, since they can mark regions as zeros (keeps
storage allocated) instead of requiring full deallocation.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
7f4b56b217 block: Add sparse operations capability query
Add capability query to DiskFile trait to check backend
support for sparse operations (punch hole, write zeroes,
discard). Only advertise VIRTIO_BLK_F_DISCARD and
VIRTIO_BLK_F_WRITE_ZEROES when the backend supports these
operations.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
7095605d84 block: Add punch_hole and write_zeroes to AsyncIo trait
Add punch_hole() and write_zeroes() methods to the AsyncIo trait
with stub implementations for all backends. These will be used to
support DISCARD and WRITE_ZEROES operations.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
629c117ff3 block: qcow: Implement live resize with L1 table growth
Add support for live resizing QCOW2 images. This enables growing
the virtual size of a QCOW2 disk while the VM is running.

Key features:
- Growing the image automatically expands the L1 table if needed
- Shrinking is not supported
- Resizing for images with backing files is not supported

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-12 22:47:00 +00:00