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>
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>
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>
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>
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>
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>
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>
Verify that AlignedBuf rounds the allocation size up to the
requested alignment. Passes under miri.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>