Commit Graph

266 Commits

Author SHA1 Message Date
Anatol Belski
fc79d08d7d block: qcow: Remove From<qcow::Error> for BlockError
All public qcow functions now return BlockResult with explicit error
classification at every site. The temporary From impl introduced in
the first commit of this series is no longer needed and is removed.

Internal functions in header.rs and the rebuild_refcounts helpers
stay on qcow::Result. Classification happens at the call site
boundary where qcow::Result meets BlockResult.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
5410d4b2d5 block: qcow: Switch detect_image_type to BlockResult
Switch detect_image_type from qcow::Result to BlockResult with
explicit error classification at every I/O site. This is the last
function migrated before the From scaffolding can be removed.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
9daf1782a8 block: qcow: Switch rebuild_refcounts to BlockResult
Switch rebuild_refcounts from qcow::Result to BlockResult. The
inner helper functions remain on qcow::Result since they are purely
internal, and are wrapped with map_err at each call site where they
cross the BlockResult boundary.

InvalidRefcountTableSize errors are classified as CorruptImage since
they indicate inconsistent internal refcount structures rather than
a format violation.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
f6ec817b9b block: qcow: Switch resize and grow_l1_table to BlockResult
Switch resize and grow_l1_table from qcow::Result to BlockResult.
All I/O error sites use explicit BlockError::new with the Io kind.
The write_to call in grow_l1_table rewraps WritingHeader as
ResizeIo to preserve the existing error semantics.

The two resize tests that check for ShrinkNotSupported and
ResizeWithBackingFile are updated to match on BlockErrorKind with
downcast to inspect the underlying variant.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
524e620240 block: qcow: Classify errors in parse_qcow and BackingFile::new
Replace remaining automatic From conversions in parse_qcow and
BackingFile::new with explicit BlockError::new calls carrying the
appropriate BlockErrorKind at every error site.

Internal functions that still return qcow::Result (QcowHeader::new,
offset_is_cluster_boundary, clear_autoclear_features and others) are
wrapped with map_err at the boundary. These functions stay on
qcow::Result as they are internal to the qcow module and the
classification belongs at the call site rather than inside the
function itself.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +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
c4a5c7f843 block: qcow: Switch QcowFile constructors to BlockResult
Switch the public QcowFile constructors (new, new_from_backing,
new_from_header, from, from_backing, from_file_and_header) from
qcow::Result to BlockResult. Internal calls to header functions
that still return qcow::Result are wrapped with explicit error
classification at each call site.

Test assertions are updated to match on BlockErrorKind and use
downcast to inspect the underlying qcow::Error variant.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-20 22:21:24 +00:00
Anatol Belski
d77e3e7ca2 block: qcow: Add From<qcow::Error> for BlockError
Temporary From impl that classifies each qcow::Error variant into
the appropriate BlockErrorKind. This enables an incremental migration
of qcow functions from qcow::Result to BlockResult, where each
subsequent commit replaces bare ? sites with explicit BlockError::new
calls until this impl can be removed.

The mapping assigns InvalidFormat for structural header violations,
UnsupportedFeature for version and feature mismatches, CorruptImage
for internal inconsistencies, Overflow for nesting depth and Io for
everything else.

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
264013b424 block: disk_file: Add DiskBackend dispatch enum
Introduce DiskBackend with two variants:
- Legacy: wraps Box<dyn async_io::DiskFile> for existing formats
- Next: wraps Box<dyn disk_file::AsyncFullDiskFile>

Methods return BlockResult, with DiskFileError converted up to
BlockError on the Legacy path. The Next path passes through
directly with zero conversion overhead.

This is a transitional type. Once all formats implement
AsyncFullDiskFile, DiskBackend and Legacy are removed and
callers hold Box<dyn AsyncFullDiskFile> directly.

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
dac8707c35 block: disk_file: Add AsyncFullDiskFile trait
Marker trait combining FullDiskFile and AsyncDiskFile. Blanket impl
covers any type implementing both supertraits.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
8623edb8aa block: disk_file: Add FullDiskFile trait
Marker trait bundling all optional capabilities (PhysicalSize, DiskFd,
SparseCapable, Resizable) on top of DiskFile. Blanket impl covers any
type implementing all constituent traits.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
50741cca2a block: disk_file: Add AsyncDiskFile trait
Extend DiskFile with async I/O construction for virtio queue workers.

AsyncDiskFile adds try_clone() for creating independent handles to
the same backing storage, and new_async_io() for constructing an
async I/O engine at the given ring depth.

Bounds: DiskFile + Unpin. Unpin ensures trait objects can be moved
freely (all concrete disk file types are naturally Unpin since they
hold no self referential state).

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
5d50d64671 block: disk_file: Add DiskFile supertrait
Bundles DiskSize and Geometry as the universal disk
capabilities every format must implement. Adds Sync so
that Arc<dyn DiskFile> can be shared across threads for
concurrent readonly access.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
da1b104493 block: disk_file: Add Resizable trait
Live disk resize support. Single method resize() taking
&mut self and the new size in bytes. Implementations may
return an error if the backend does not support resizing.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
a0a5718b42 block: disk_file: Add SparseCapable trait
Sparse and zero flag support for thin provisioned disk
images. Two methods with false defaults: sparse operations
(punch hole, write zeroes, discard) and zero flag
optimization in WRITE_ZEROES.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
b98a5cc58d block: disk_file: Add Geometry trait
Sector and cluster geometry of a disk image. Returns
DiskTopology with a default implementation providing
512B logical and physical block sizes. Formats that
probe the underlying device override this.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
2fa877e087 block: disk_file: Add DiskFd trait
Backing file descriptor access for disk images backed by
a file. Returns a BorrowedDiskFd that wraps the raw fd
with lifetime tracking. Not available for network or
memory backed disk formats.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
2df731b8d3 block: disk_file: Add PhysicalSize trait
Host allocation size for file-backed disk images. Reports
actual bytes occupied on the host filesystem. Not every
format supports this, e.g. network or memory backed disks.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
85e4e5027c block: disk_file: Add DiskSize trait
Reported capacity of a disk image. Every format, be it
file backed, network, memory, exposes a logical size.
Single method logical_size() returning the virtual size
in bytes.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
a15bfcfee6 block: Add disk_file module skeleton
Composable disk capability traits with DiskFile as a supertrait
bundling DiskSize and Geometry. Optional capabilities are
separate traits: PhysicalSize, DiskFd, SparseCapable, Resizable.
AsyncDiskFile extends DiskFile with async I/O construction.

Empty module with doc comment, trait definitions follow.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 22:29:27 +00:00
Anatol Belski
19fa512f02 block: Batch drain AIO completions in next_completed_request
Collect up to 32 completions per io_getevents call instead of one
at a time, buffering them in the existing VecDeque. This reduces
syscalls from 128 to 4 per drain cycle at the default queue depth.
The stack cost is 1 KB per call.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-19 12:20:19 +00:00
Anatol Belski
9655eaddd5 block: Use offset_of! for virtio_blk_discard_write_zeroes field offsets
Replace magic numeric offsets with mem::offset_of!() referencing the
virtio_blk_discard_write_zeroes struct from the virtio-bindings crate
when reading the sector, num_sectors and flags fields in the DISCARD
and WRITE_ZEROES request handlers.

No functional change.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-18 21:12:12 +00:00
Anatol Belski
3e2e453d89 block: Honor unmap flag in write zeroes requests
The write zeroes segment descriptor (struct
virtio_blk_discard_write_zeroes, virtio spec v1.2 section 5.2.6)
includes a flags field with an unmap bit. Per section 5.2.6.2, if
unmap is set, the device MAY deallocate the specified range of
sectors in the device backend storage, as if the discard command
had been sent.

Read the flags field and when the unmap bit is set, use punch_hole
to deallocate the range. Otherwise continue using write_zeroes via
ZERO_RANGE which preserves allocation.

This allows the guest to reclaim host disk space through write
zeroes requests on thin provisioned images.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-18 09:40:19 +00:00
Anatol Belski
1733e08a0f block: raw: Replace FALLOC_FL_* consts with libc::* in raw backends
raw_sync, raw_async, and raw_async_aio each defined
FALLOC_FL_PUNCH_HOLE, FALLOC_FL_KEEP_SIZE, and FALLOC_FL_ZERO_RANGE as
local constants in their punch_hole() and write_zeroes()
implementations. These are available from the libc crate directly.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-14 14:00:29 +00:00
Anatol Belski
05aa9ebcd4 block: Replace local FALLOC_FL_* constants with libc::* in probe
probe_file_sparse_support() defined FALLOC_FL_KEEP_SIZE,
FALLOC_FL_PUNCH_HOLE, and FALLOC_FL_ZERO_RANGE as local constants.
These are available from the libc crate directly.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-14 14:00:29 +00:00
Anatol Belski
d883b54fb7 block: Deduplicate raw_sync and raw_async_aio tests
Replace duplicated test bodies with thin wrappers that construct
the backend-specific AsyncIo instance and delegate to the shared
raw_async_io_tests helpers.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-14 13:39:41 +00:00
Anatol Belski
5aa68ddf9e block: Add raw_async_io_tests shared test helpers
Add raw_async_io_tests.rs with punch_hole, write_zeroes, and
multiple_operations helpers that take &mut dyn AsyncIo + &mut File.
These are raw-backend-specific. They verify data by reading the
underlying file directly, which only works for plain file backends
without container format metadata.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-14 13:39:41 +00:00
Julian Schindel
e265543e3c misc: make MSRV workspace-wide for cloud-hypervisor dependencies
Moves the MSRV requirement to the workspace and expands it to all
cloud-hypervisor dependencies and dev-dependencies.
This improves discoverability for new contributors working on crates
other than the cloud-hypervisor itself and creates consistency regarding
the MSRV of cloud-hypervisor dependencies.
Functionally, this doesn't change anything for dependencies of the
cloud-hypervisor crate as the MSRV requirement is already enforced by CI
when building the cloud-hypervisor with the MSRV versioned compiler.

On-behalf-of: SAP julian.schindel@sap.com
Signed-off-by: Julian Schindel <julian.schindel@cyberus-technology.de>
2026-03-13 01:30:25 +00:00
Anatol Belski
32d339c59e block: qcow: Migrate debug/test helpers to BlockResult
Switch l2_table(), refcount_block(), and first_zero_refcount()
to BlockResult. These are public inspection helpers with no
callers within the crate.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
1accf47db4 block: qcow: Migrate convert() to BlockResult
Switch the public convert() entry point to BlockResult. Inner
calls to functions already returning BlockResult propagate
naturally; those still returning qcow::Error get map_err
bridges.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
4930d93090 block: qcow: Migrate convert_reader() to BlockResult
Switch convert_reader() to BlockResult, preserving the original
qcow::Error variants as the BlockError source. The inner
convert_reader_writer() call now propagates naturally. Callers
get map_err bridges where they still return qcow::Error.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
748666fe4d block: qcow: Migrate convert_reader_writer() to BlockResult
Switch convert_reader_writer() to BlockResult, preserving the
original qcow::Error variants as the BlockError source. The
inner convert_copy() call now propagates BlockResult naturally.
Callers get map_err bridges where they still return qcow::Error.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
c59c5687d2 block: qcow: Migrate convert_copy() to BlockResult
Switch convert_copy() to BlockResult, preserving the original
qcow::Error variants as the BlockError source for diagnostics.
A map_err bridge at the caller converts back where needed.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
732cddb8b3 block: qcow: Migrate dirty/corrupt bit helpers to BlockResult
Switch the header dirty and corrupt bit helpers from
qcow::Result to BlockResult. Their callers either discard
the result or unwrap in tests, so no caller signatures change.
A map_err bridge in parse_qcow() converts back where needed.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
4fea912d18 block: qcow: Add open_disk_image helper with path context
Add a small helper in the block crate that opens a disk image
file and wraps any failure in a BlockError carrying the file
path and operation context. Use it from the vmm device manager
so that a failed open now reports which path couldn't be opened.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +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
b1bc376c91 block: Make detect_image_type return BlockResult with context
Convert detect_image_type() from io::Result to BlockResult so
that I/O failures carry the operation name in the error context.
Update the corresponding vmm error variant to wrap BlockError.

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
8c2794533d block: qcow: impl AsFd for RawFile and QcowRawFile
Implement AsFd for both RawFile and QcowRawFile by delegating to
the inner File handle. This enables safe fd borrowing through the
standard AsFd trait, which is a prerequisite for replacing unsafe
libc::dup calls with BorrowedFd::try_clone_to_owned().

Suggested-by: Rob Bradford <rbradford@rivosinc.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
9be154b03c block: Add BlockResult, From<io::Error>
Add the public BlockResult type alias and a From<io::Error>
impl so that bare I/O errors automatically convert into
BlockError with BlockErrorKind::Io via the ? operator.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00