Commit Graph

229 Commits

Author SHA1 Message Date
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
Anatol Belski
6404d2d513 block: Assume sparse support for block devices
There is no non destructive readonly ioctl to query block device
discard or write zeroes capabilities. BLKZEROOUT is guaranteed to
succeed via kernel software fallback. BLKDISCARD may fail at runtime
with EOPNOTSUPP on devices that lack trim support, but the error
propagates to the guest as VIRTIO_BLK_S_IOERR and well behaved
guests handle it gracefully.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-26 00:43:20 +00:00
Anatol Belski
6f19d0071d block: vhdx: Fix multiqueue data corruption
Wrap the Vhdx instance in Arc<Mutex<>> so that all queues share
a single mutex-protected backend, matching the approach already
used for QCOW2.

Vhdx::clone() uses dup() which shares the kernel file description
including the file offset. With multiple queues performing
concurrent seek+read/write on the shared offset, I/O operations
race and corrupt data.

Fixes: #7665

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-23 18:25:21 +00:00
Rob Bradford
a63315df54 virtio-devices, block: Reject sector 0 discard/"write zeroes" requests
As well as rejecting writes to sector 0 in the case of raw files where
the user hasn't specified the image_type also reject virtio requests of
type discard and write_zeroes.

Signed-off-by: Rob Bradford <rbradford@meta.com>
2026-02-19 22:43:15 +00:00
Rob Bradford
6f2357c14e vmm: Improve resiliency of image type handling
Add an image_type to DiskConfig to specify the image type. If none is
specified autodetect the image type but disable potentially unsafe
behaviour in the QCOW2 backend by disabling the backing file support.

If the image type is autodetected then fix it in the config so that it
will be persistant across reboots and migrations/snapshot & restores.
This also handles the case where the image type was not specified as
part of the disk configuration.

Signed-off-by: Rob Bradford <rbradford@meta.com>
2026-02-19 22:43:15 +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
45b115aeb0 block: raw: Implement punch_hole and write_zeroes
Implement punch_hole() and write_zeroes() for raw file backends using
io_uring and fallocate.

punch_hole() uses FALLOC_FL_PUNCH_HOLE to deallocate storage.
write_zeroes() uses FALLOC_FL_ZERO_RANGE to write zeros efficiently.

Both use FALLOC_FL_KEEP_SIZE to maintain file size.

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
81c075b317 block: Add virtio-blk DISCARD and WRITE_ZEROES support
Add VIRTIO_BLK_T_DISCARD and VIRTIO_BLK_T_WRITE_ZEROES request types.
Parse discard/write_zeroes descriptors (sector, num_sectors, flags),
convert to byte offsets, and call punch_hole/write_zeroes on the disk
backend. Mark as unsupported in sync mode.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
e913d0d9cb block: qcow: Implement DISCARD with sparse aware deallocation
Implement DISCARD using QCOW2 zero flag (bit 0 of L2 entries) with
sparse aware behavior.

When sparse=true - fully deallocate clusters by decrementing
refcount, clearing L2 entry, and reclaiming storage via punch_hole
when refcount reaches zero.

When sparse=false - use zero flag to keep storage allocated while
marking as reading zeros. Only works when cluster is not shared.
Shared clusters are fully deallocated.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2026-02-13 18:44:30 +00:00
Anatol Belski
49a30cbbaf block: raw: Implement disk preallocation for sparse=false
When sparse=false is configured, preallocate the entire raw disk file
at startup using fallocate(). This provides space reservation and
reduces fragmentation.

Only applies to raw disks. QCOW2/VHD/VHDX formats manage their own
allocation.

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
d5dad48618 block: Add sparse capability detection
Add functions to probe whether a file or block device actually
supports PUNCH_HOLE and ZERO_RANGE operations at runtime. The
probe is performed at file open time by testing the operations
at EOF with a zero-length range, which is a safe no-op.

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
99493c728e block: qcow: Add resize unit tests
- No-op resize when size unchanged
- Growing with L1 table expansion
- Shrink attempts return error
- Resize with backing file returns error

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