Commit Graph

448 Commits

Author SHA1 Message Date
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
Anatol Belski
4c29548736 block: Add BlockError constructors and builder methods
Add the construction and inspection API for BlockError,
consisting on constructors that accept a kind and optional
source, builder methods that attach context after
the fact, and accessors for retrieving the kind, context,
and typed source references. The builder pattern allows
callers to enrich errors at each level of the call stack.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
d5467dca8e block: Add BlockError struct with Display and Error impls
Add the single public crate error type. It combines a
BlockErrorKind for classification, an optional boxed source
for the underlying cause, and an optional ErrorContext for
diagnostics. Display renders the kind and context only,
leaving source traversal to error reporters so the cause
chain is not duplicated in human readable output.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
55504177cb block: Add ErrorContext for path/offset/op diagnostics
Add a struct that carries optional diagnostic metadata - file
path, byte offset, and operation name that can be attached
to any BlockError. This lets errors report *where* and *during
what* a failure occurred, which is especially useful when the
same I/O kind shows up at multiple call sites.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
e4e74a9d93 block: Add BlockErrorKind classification enum
Add a small, stable enum that classifies block errors into
broad categories - I/O, invalid format, unsupported feature,
corrupt image, out of bounds, not found, overflow. Callers
match on this for control flow rather than on format specific
error variants.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Anatol Belski
f184a0f0f3 block: Add error module skeleton
Introduce error.rs as the home for a unified error hierarchy that
will replace the per format error types at the public crate
boundary. This commit is intentionally empty beyond the copyright
header and module declaration in lib.rs.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-12 14:18:45 +00:00
Emir Beganovic
623af62743 block: Implement write_zeroes and punch_hole for AIO backend
The AIO block backend advertises VIRTIO_BLK_F_WRITE_ZEROES
and VIRTIO_BLK_F_DISCARD to guests because the filesystem
probe (supports_sparse_operations) returns true on ext4/XFS.
However, RawFileAsyncAio::write_zeroes() and punch_hole()
return errors because Linux AIO (io_submit) has no IOCB
command for fallocate.

When io_uring is unavailable (e.g. io_uring_disabled=2, a
common security hardening on enterprise Linux), Cloud
Hypervisor falls back to the AIO backend. The guest
negotiates the feature, issues WRITE_ZEROES requests, and
gets I/O errors.

Implement write_zeroes and punch_hole using synchronous
libc::fallocate() calls, matching the pattern used by the
sync backend (RawFileSync). A VecDeque-based completion
list signals results to the caller via the existing eventfd
mechanism.

Unit tests mirror the existing raw_sync.rs test suite.
Integration tests add AIO-specific variants of the discard
and fstrim tests using _disable_io_uring=on.

Signed-off-by: Emir Beganovic <beganovic.emir@gmail.com>
2026-03-12 12:08:01 +00:00
Rob Bradford
0a4fe0e41e vmm: Fix OpenAPI definition of for lock granularity
Use CamelCase as per the existing definitions (which allows the removal
of the serde transformation)

Signed-off-by: Rob Bradford <rbradford@meta.com>
2026-03-12 02:10:43 +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
a4a5b19f64 block: qcow: Add resize() to QcowMetadata
Add resize() and grow_l1_table() so the metadata layer can grow
the virtual disk size. Only grow is supported.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Anatol Belski
9d686b0866 block: qcow: Add QcowMetadata with RwLock
Introduce QcowMetadata, a thread safe wrapper around QCOW2 metadata
tables and caches using RwLock.

Provides cluster resolution for reads and writes, and deallocate
operations for discard.

Extract parse_qcow() from QcowFile so both QcowFile and QcowDiskSync
can share the parsing and validation logic.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Anatol Belski
63db385c3c block: qcow: Extract utility functions into util.rs
Move L1 and L2 table entry helpers, division utilities and related
constants from mod.rs into a dedicated util.rs submodule. Both
mod.rs and metadata.rs import from util.

No functional changes.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Anatol Belski
210514cbf3 block: qcow: Extract QcowHeader and related types into header.rs
Move QcowHeader, associated types, constants and helper functions
into a new header.rs submodule. Public types are re-exported from
mod.rs.

No functional changes.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-09 13:02:07 +00:00
Victor Vieux
7c690ffec0 vmm: config: Expose disk lock granularity option
Add a per-disk lock_granularity parameter that lets users choose
between byte-range OFD locks and whole-file OFD locks:

  --disk path=/foo.img,lock_granularity=byte-range
  --disk path=/bar.img,lock_granularity=full

Byte-range is the default and matches QEMU behavior, working
best with storage backends where whole-file OFD locks are treated
as mandatory. The full option restores the original whole-file
locking for environments that depend on it.

The LockGranularityChoice enum and its FromStr impl live in the
block crate alongside the existing LockGranularity type. The
Block device converts the user-facing choice to the internal
LockGranularity at lock time, keeping device_manager.rs simple.

Closes: #7553

Signed-off-by: Victor Vieux <vieux@repl.it>
2026-03-08 10:07:03 +00:00
Anatol Belski
b7b38df99c block: raw: Use map_or instead of map().unwrap_or()
Do the necessary replacements to satisfy clippy::map_unwrap_or.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-06 12:32:38 +00:00
Anatol Belski
496c89c289 block: Add unit tests for DiskTopology file alignment probing
Test valid power of two alignment, layout compatibility,
direct helper coverage, and O_DIRECT write/read roundtrip.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-02 18:26:55 +00:00
Anatol Belski
15ce890dd3 block: Query actual DIO alignment for file backed images
DiskTopology::probe() returned a hardcoded 512 for regular files,
causing O_DIRECT failures on volumes with larger block sizes
(e.g. 4K).

Use statx(STATX_DIOALIGN) (Linux >= 6.1) to query the real per file
DIO memory and offset alignment. Unlike fstatvfs().f_bsize, which
only returns the filesystem preferred I/O block size,
STATX_DIOALIGN reports the true DIO constraints accounting for the
filesystem, underlying block device, and any stacking (loop, dm,
etc.).

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-03-02 18:26:55 +00:00
Saravanan D
00c05f4761 block: Use logical block size for alignment
O_DIRECT requires buffer addresses to be aligned to the backend
device's logical block size. The existing bounce buffer logic in
execute_async() hardcodes SECTOR_SIZE (512) for the alignment check
and bounce buffer allocation. This is insufficient for devices with
a 4096-byte logical block size, where misaligned buffers cause
-EINVAL from the host kernel.

Add an alignment() method to the AsyncIo trait that returns the
backend's logical block size, defaulting to SECTOR_SIZE. The three
raw I/O backends (io_uring, AIO, synchronous) probe the device
topology via DiskTopology::probe() at creation time and return the
actual logical block size. All image format backends would simply
use the default value of 512 bytes since their underlying are
not block devices.

execute_async() now queries disk_image.alignment() instead of using
the hardcoded SECTOR_SIZE

Fixes: #7720

Signed-off-by: Saravanan D <saravanand@crusoe.ai>
2026-02-26 15:47:17 +00:00