Commit Graph

104 Commits

Author SHA1 Message Date
Anatol Belski
5c5f33050c block: qcow: Refactor pointer table writes to use iterators
Refactor write_pointer_table to accept iterators instead of requiring
materialized vectors, eliminating temporary allocations in L1 table
sync operations.

Changes:
- Modified write_pointer_table() to take Iterator<Item = &T> and
  dereference internally before passing owned values to the callback
- Added write_pointer_table_direct() convenience wrapper for cases
  without value transformation
- Updated sync_caches() to use l1_table.iter() directly instead of
  .get_values().iter().copied()
- Implemented Deref<Target = [T]> for VecCache to enable direct .iter()

Performance impact:
- Eliminates L1 table allocation during sync (~2KB per 100GB disk)
- L2 and refcount table writes already used slices, no change there
- Zero performance overhead: iterator dereferencing is equivalent to
  .copied() and optimizes identically

The L1 sync previously collected entries into a Vec to apply the
OFLAG_COPIED flag. The new iterator+callback pattern computes this
on-the-fly, avoiding the allocation entirely.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-10 23:35:46 +00:00
Anatol Belski
be5b14ef3a block: qcow: Implement Deref for VecCache
Add Deref<Target = [T]> implementation for VecCache<T> to allow direct
slice operations without explicitly calling get_values(). This enables
cleaner code patterns like cache.iter() instead
of cache.get_values().iter().

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-10 23:35:46 +00:00
Connor Brewster
41a8dcd9ba block: allow VIRTIO_BLK_T_GET_ID for read-only devices
https://github.com/cloud-hypervisor/cloud-hypervisor/pull/7294 adjusted
the checks for read-only requests made to virtio-blk devices and started
rejecting VIRTIO_BLK_T_GET_ID requests. These requests do not perform
any writes and are needed in order to access device serials from within
the guest.

Signed-off-by: Connor Brewster <cbrewster@hey.com>
2025-12-09 16:22:46 +00:00
Anatol Belski
562af123d5 block: qcow: Add missing flush in write_refcount_block
The BufWriter must be flushed explicitly to handle errors
properly. Without explicit flush, errors during the implicit
drop flush are ignored.

This is the same issue fixed for write_pointer_table
in commit 85556951a.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-09 14:51:54 +00:00
Anatol Belski
c940f6642f block: qcow: Refactor refcount update into helper method
Add set_cluster_refcount_track_freed() helper to consolidate the
common pattern of setting a cluster refcount and tracking freed
refblocks. This reduces code duplication and improves readability.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-06 17:10:48 +00:00
Anatol Belski
f1ffd795e0 block: qcow: tests: Update combo_write_read for cluster leak fixes
Freed clusters correctly have refcount=0. Remove the assertion that
expected no clusters with zero refcount, as it was validating the
buggy behavior.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-05 15:38:55 +00:00
Anatol Belski
efad6578d1 block: qcow: Fix refcount leak when converting compressed clusters
When converting a compressed cluster to standard during write
operations, the old compressed cluster's refcount was never
decremented, causing leak warnings by `qemu-img check ..`

`Leaked cluster X refcount=N reference=M`

Additionally, compressed data can span multiple physical clusters,
not just one. The compressed cluster address and size are encoded
in the L2 entry, and the data may cross cluster boundaries.

The proper handling is implemented as follows:
- Extract compressed cluster address and size before overwriting
  L2 entry
- Identify all clusters occupied by the compressed data
- Decrement refcount for each cluster in the range

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-05 15:38:55 +00:00
Anatol Belski
9e2e85a48f block: qcow: Fix refcount leak when refcount blocks are replaced
When a refcount block is evicted from cache and replaced with a new
one, the old refcount block cluster was added to unref_clusters but
its refcount was never decremented to 0 on disk. This left the cluster
with refcount=1 while no metadata referenced it, causing errors in
qemu-img check

`Leaked cluster X refcount=1 reference=0`

This fix recursively calls set_cluster_refcount(freed_cluster, 0) to
properly decrement the freed refcount block's refcount on disk. The
recursion handles cascading replacements where freeing one refcount
block may trigger the replacement of another.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-05 15:38:55 +00:00
Anatol Belski
6897c2a462 block: qcow: Set OFLAG_COPIED bit in L1 entries for spec compliance
The OFLAG_COPIED bit (bit 63) indicates a cluster's refcount is exactly
1 and doesn't need copy-on-write. This bit must be set in L1 entries
when their referenced L2 clusters have refcount=1.

Previously, L1 entries were always written as raw addresses without the
OFLAG_COPIED bit, violating the QCOW2 specification and causing qemu-img
check to report errors like

`ERROR OFLAG_COPIED L2 cluster: l1_index=X .... refcount=1`

The implementation queries each L2 cluster's refcount in sync_caches()
and sets OFLAG_COPIED appropriately when writing the L1 table. This
ensures QCOW2 images are specification compliant and maintain correct
COW semantics to avoid data corruption.

Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
2025-12-01 16:45:55 +00:00
Wei Liu
85556951a6 block: qcow2: Flush the buffer explicitly when writing pointer table
Previously the code relies on the implicit flush when BufWriter is
dropped. That's not safe.

Per BufWriter's document:

```
It is critical to call flush before BufWriter<W> is dropped. Though
dropping will attempt to flush the contents of the buffer, any errors
that happen in the process of dropping will be ignored. Calling flush
ensures that the buffer is empty and thus dropping will not even attempt
file operations.
```

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-11-30 18:39:49 +00:00
Philipp Schuster
6a86c157af misc: clippy: add needless_pass_by_value (partially)
This helps to uncover expensive and needless clones in the code base.
For example, I prevented extensive clones in the snapshot path where
(nested) BTreeMap's have been cloned over and over again. Further,
the lint helps devs to much better reason about the ownership of
parameters.

All of these changes have been done manually with the necessary
caution. A few structs that are cheap to clone are now `copy` so that
this lint won't trigger for them.

I didn't enable the lint so far as it is a massive rabbit hole and
needs much more fixes. Nevertheless, it is very useful.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-25 16:05:46 +00:00
Philipp Schuster
0a07c96d17 misc: clippy: add if_not_else
This removes cognitive load when reading if statements.
All changes were applied by clippy via `--fix`.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-25 16:05:46 +00:00
Philipp Schuster
5f66a26b2e misc: block: drop extern crate, use modern rust
This commit is part of a series of similar commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-24 22:36:46 +00:00
Eugene Korenevsky
aa67250049 block: qcow: support compressed clusters (zlib, zstd)
Add support of reading and writing compressed clusters.
Support zlib and zstd compressions.

L2 cache: store entire L2 entries, not only standard cluster addresses.

Read path. Offsets of compressed clusters cannot be determined,
therefore replace QcowFile.file_offset_read() with QcowFile.file_read().
This method reads the cluster, decompresses it if necessary and returns
the data to the caller.

Write path. QcowFile.file_offset_write(): since writing to compressed
clusters is not generally possible, allocate a new standard
(non-compressed) cluster if compressed L2 entry is encountered; then
decompress compressed cluster into new cluster; then return offset
inside new cluster to the caller. Processing of standard clusters is
not changed.

Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
2025-11-24 08:52:13 +00:00
Philipp Schuster
f5d2973546 block: advisory locks: use byte-range locks to match QEMU behavior
The granularity has significant implications in typical cloud
deployments with network storage. The Linux kernel will sync advisory
locks to network file systems, but these backends may have different
policies and handle locks differently. For example, Netapp speaks a NFS
API but will treat advisory OFD locks for the whole file as mandatory
locks, whereas byte-range locks for the whole file will remain
advisory [0].

As it is a valid use case to prevent multiple CHV instances from
accessing the same disk but disk management software (e.g., Cinder in
OpenStack) should be able to snapshot disks while VMs are running, we
need special control over the lock granularity. Therefore, it is a valid
use case to lock the whole byte range of a disk image without
technically locking the whole file - to get the best of both worlds.

This also brings CHVs behavior in line with QEMU [1].

Whole-file locks remain a valid use case and could be supported later.
This patch only provides the necessary groundwork; making it
configurable is out of scope for now.

[0] https://kb.netapp.com/on-prem/ontap/da/NAS/NAS-KBs/How_is_Mandatory_Locking_supported_for_NFSv4_on_ONTAP_9
[1] <qemu>/util/osdep.c::qemu_lock_fcntl()

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-22 10:38:38 +00:00
Demi Marie Obenour
2be304b392 misc: Check that get_slice() returned a big enough slice
This should be guaranteed by GuestMemory and GuestMemoryRegion, but
those traits are currently safe, so add checks to guard against
incorrect implementations of them.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-11-22 10:24:13 +00:00
Philipp Schuster
b4c62bf159 misc: clippy: add semicolon_if_nothing_returned
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-21 09:32:11 +00:00
Philipp Schuster
ea4f07d3bf misc: clippy: add uninlined_format_args
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-21 09:32:11 +00:00
Philipp Schuster
7cb73e9e56 misc: clippy: add unnecessary_semicolon
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-21 09:32:11 +00:00
Philipp Schuster
d1680b9ff9 tests: streamline module names to unit_tests
This better aligns with the rest of the code and makes it clearer
that these tests can run "as is" in a normal hosted environments
without the special test environment.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-11-20 21:15:03 +00:00
Eugene Korenevsky
3791062b23 block: qcow: refactor: extract method cache_l2_cluster()
There are several copy-pasted code fragments in impl QcowFile. All of
them add L2 entry to the cache and one of them (in file_offset_write())
does also allocating new L2 entry if necessary.

Fold all these code fragments (except of one in l2_table() which does
error handling in special way) into cache_l2_cluster() method without
changing the logic.
This will make the code more compact and clean.

Signed-off-by: Eugene Korenevsky <ekorenevsky@aliyun.com>
2025-11-05 16:58:24 +00:00
Philipp Schuster
7536a95424 misc: cleanup &Arc<dyn T> -> &dyn T
Consuming `&Arc<T>` as argument is almost always an antipattern as it
hides whether the callee is going to take over (shared) ownership
(by .clone()) or not. Instead, it is better to consume `&dyn T` or
`Arc<dyn T>` to be more explicit. This commit cleans up the code.

The change is very mechanic and was very easy to implement across the
code base.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-10-28 17:37:49 +00:00
Philipp Schuster
f1206a19df block: fix error style
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-25 21:17:06 +00:00
Ruoqing He
f2dfa7f6e0 misc: Use variables directly in format! string
Fix clippy warning `uninlined_format_args` reported by rustc rustc
1.89.0 (29483883e 2025-08-04).

```console
warning: variables can be used directly in the `format!` string
   --> block/src/lib.rs:649:17
    |
649 |                 info!("{} failed to create io_uring instance: {}", error_msg, e);
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args
    = note: `#[warn(clippy::uninlined_format_args)]` on by default
help: change this to
    |
649 -                 info!("{} failed to create io_uring instance: {}", error_msg, e);
649 +                 info!("{error_msg} failed to create io_uring instance: {e}");
    |
```

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-09-24 02:28:12 +00:00
Philipp Schuster
c995b72384 build: treewide: clippy: collapse nested ifs, use let chains
This bumps the MSRV to 1.88 (also, Rust edition 2024 is mandatory).

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Philipp Schuster
363273111a build: treewide: fmt for edition 2024
`cargo +nightly fmt`

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-09-10 18:35:38 +00:00
Muminul Islam
a9d6807522 block: batch submit requests for fixed VHD
Updated VHD async implementation to call the batch submit
method via the raw async IO layer.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
c4bab33020 block: Enable request submission in batch when using io_uring
Implement the batch submission function for raw disk, default it is
enabled. After parsing the requests this method is
called for better IO latency and bandwidth.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
245bce23fa block, virtio-devices: Support request submission in batch
Cache and batch IO requests after parsing all
items in the queue, improving performance—especially
for small block sizes—by reducing per-request overhead.

Introduced two methods in the AsyncIo trait for batch
submission, with implementation in the raw disk backend.
This method should be called during/after parsing all block IO requests
in the available queue. If the batch submission is not enabled, by
default it does the old way of submitting requests.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Muminul Islam
67ab81874a block: virtio-devices: block: Clarify the return of execute_async()
Instead of returning boolean return an struct of completion status
so that it can be cached for batch submission.

Signed-off-by: Bo Chen <bchen@crusoe.ai>
Signed-off-by: Muminul Islam <muislam@microsoft.com>
2025-09-02 16:29:25 +00:00
Songqian Li
92370e8ff1 block: Using feature bits to check the read-only flag
This patch changes the read-only check using acked features bit, which
will help to check more features.

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-26 15:45:45 +00:00
Songqian Li
cd2c43b489 misc: Fix beta clippy errors
Fix clippy error: "error: manual implementation of `.is_multiple_of()
`" from rustc 1.90.0-beta.1 (788da80fc 2025-08-04).

Signed-off-by: Songqian Li <sionli@tencent.com>
2025-08-07 16:53:59 +00:00
Wei Liu
930a911862 block: Simplify AsyncAdaptor
It shouldn't be necessary to lock the file for the adaptor. This removes
two layers of indirection for QcowDiskSync and VhdxDiskSync.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-07-22 22:00:35 +00:00
Jinank Jain
190d90196f build: Bump vfio and all the dependent crates to latest version
Recently vfio crates have moved to crates.io, thus we should start
consuming the crate from crates.io instead git url.

This results in better versioning instead of tracking some git commit
sha.

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-07-07 03:05:38 +00:00
Demi Marie Obenour
269976c7b3 block: Remove unnecessary pointer indirection
No functional change intended.

Signed-off-by: Demi Marie Obenour <demiobenour@gmail.com>
2025-06-20 10:21:04 +00:00
Yi Wang
80f4bfac00 block: keep lifetime consistent from input to output
Cargo fuzz build report an error:
error: lifetime flowing from input to output with different syntax can be confusing
   --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/lib.rs:747:13
    |
747 |     fn file(&mut self) -> MutexGuard<F>;
    |             ^^^^^^^^^     ------------- the lifetime gets resolved as `'_`
    |             |
    |             this lifetime flows to the output

error: lifetime flowing from input to output with different syntax can be confusing
  --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/block/src/async_io.rs:68:11
   |
68 |     fn fd(&mut self) -> BorrowedDiskFd;
   |           ^^^^^^^^^     -------------- the lifetime gets resolved as `'_`
   |           |
   |           this lifetime flows to the output

Signed-off-by: Yi Wang <foxywang@tencent.com>
2025-06-16 06:25:57 +00:00
Philipp Schuster
aebbd1aecd misc: block: streamline error Display::fmt()
The changes were mostly automatically applied using the Python
script mentioned in the first commit of this series.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-13 19:55:54 +00:00
Philipp Schuster
12b72ba3c1 ci: bump typos
Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-06-10 15:52:12 +00:00
Jinank Jain
2bc8d51a60 misc: Fix missing lifetime syntax clippy warning
This was caught by the nightly compiler during cargo fuzz build.

error: lifetime flowing from input to output with different syntax can be confusing
   --> /home/runner/work/cloud-hypervisor/cloud-hypervisor/hypervisor/src/arch/x86/emulator/mod.rs:493:26
    |
493 |     pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<T> {
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ----------- the lifetime gets resolved as `'_`
    |                          |
    |                          this lifetime flows to the output
    |
    = note: `-D mismatched-lifetime-syntaxes` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(mismatched_lifetime_syntaxes)]`
help: one option is to remove the lifetime for references and use the anonymous lifetime for paths
    |
493 |     pub fn new(platform: &mut dyn PlatformEmulator<CpuState = T>) -> Emulator<'_, T> {

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-06-09 11:19:11 +00:00
Philipp Schuster
dd9bce31e8 misc: block: streamline #[source] and Error impl
This streamlines the Error implementation in the Cloud Hypervisor code
base to match the remaining parts so that everything follows the agreed
conventions. These are leftovers missed in the previous commits.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-22 12:17:13 +00:00
Philipp Schuster
01761c2596 misc: block: streamline #[source] and Error
This streamlines the code base to follow best practices for
error handling in Rust: Each error struct implements
std::error::Error (most due via thiserror::Error derive macro)
and sets its source accordingly.

This allows future work that nicely prints the error chains,
for example.

So far, the convention is that each error prints its
sub error as part of its Display::fmt() impl.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-21 09:09:30 +00:00
Philipp Schuster
71a36e0c69 block: add fcntl module for locking
This is a prerequisite for the next steps.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
2da5e10689 block: bind FD lifetime of DiskFile
As we can't use BorrowedFd, we should at least create a similar
safe alternative.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Philipp Schuster
a647d7863c block: enable to get a raw FD of each block device's DiskFile
This is a prerequisite for the next steps.

Signed-off-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
On-behalf-of: SAP philipp.schuster@sap.com
2025-05-16 08:07:32 +00:00
Bo Chen
10ee003d66 misc: Fix beta clippy issues
Fixing the following clippy issue using `cargo clippy --fix`:

error: variables can be used directly in the `format!` string
  --> build.rs:25:27
   |
25 |         version.push_str(&format!("-{}", extra_version));
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#uninlined_format_args

Signed-off-by: Bo Chen <bchen@crusoe.ai>
2025-05-14 03:44:12 +00:00
Jinank Jain
ea4693a091 misc: Fix clippy error from beta compiler
Rust has a new way of constructing other error and clippy complains if
we are still using the older way to construct error message. Thus,
migrate to the new approach suggested by the clippy.

Warning from beta compiler:

error: this can be `std::io::Error::other(_)`
--> block/src/vhdx/mod.rs:142:17
 |
 | /                 std::io::Error::new(
 | |                     std::io::ErrorKind::Other,
 | |                     format!("Failed to update VHDx header: {e}"),
 | |                 )
 | |_________________^
 |
 = help: for further information visit
https://rust-lang.github.io/rust-clippy/master/index.html#io_other_error
help: use `std::io::Error::other`

                 std::io::Error::other(
                     format!("Failed to update VHDx header: {e}"),

Signed-off-by: Jinank Jain <jinankjain@microsoft.com>
2025-04-03 13:11:49 +00:00
Ruoqing He
4de422ad69 misc: Fix clippy - manually reimplementing div_ceil
Reported by 1.86.0-beta.1 (f0cb41030 2025-02-17).

Signed-off-by: Ruoqing He <heruoqing@iscas.ac.cn>
2025-03-01 01:02:17 +00:00
Wei Liu
5b29eba636 block: vhdx: use C ABI-qualification for packed structures
This fixes the following issue from beta Clippy:

error: item uses `packed` representation without ABI-qualification
Error:    --> block/src/vhdx/vhdx_header.rs:333:1
    |
331 |   #[repr(packed)]
    |          ------ `packed` representation set here
332 |   #[derive(Clone, Copy, Debug)]
333 | / pub struct RegionTableEntry {
334 | |     pub guid: Uuid,
335 | |     pub file_offset: u64,
336 | |     pub length: u32,
337 | |     pub required: u32,
338 | | }
    | |_^
    |
    = warning: unqualified `#[repr(packed)]` defaults to `#[repr(Rust, packed)]`, which has no stable ABI
    = help: qualify the desired ABI explicity via `#[repr(C, packed)]` or `#[repr(Rust, packed)]`
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#repr_packed_without_abi

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-01-09 13:51:42 +00:00
Wei Liu
e6e78e5986 block: vhdx: reject zero size virtual disk
Some calculation down the road depends on that value not being zero.

Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-01-08 22:45:58 +00:00
Wei Liu
bc4a1fd16c block: vhdx: use checked_add in read and write functions
Signed-off-by: Wei Liu <liuwe@microsoft.com>
2025-01-08 22:45:58 +00:00