Block devices (LVM volumes, loop devices, RBD, etc.) cannot be resized
via ftruncate - they are resized externally. When vm.resize-disk is
called for a block device backend, verify the device size matches the
requested size instead of attempting ftruncate.
This enables the resize-disk API to work with block device backends by
validating the externally-resized device matches the expected size.
Signed-off-by: Vincent Thomas <vincent@v-thomas.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 QcowAsync. Use
aligned_pread in scatter_read_sync and aligned_pwrite with
gather_from_iovecs_into in cow_write_sync, matching the
QcowSync approach.
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>
When the data file is opened with O_DIRECT, buffer address, length,
and file offset must satisfy the device alignment.
Add AlignedBuf RAII wrapper and aligned_pread/aligned_pwrite helpers
in qcow_common that use bounce buffers when alignment constraints
are not met. For writes with misaligned offset, a read modify write
is performed on the aligned region.
gather_from_iovecs_into gathers iovec data directly into a caller
provided buffer, avoiding an intermediate Vec allocation.
Fixes: #8007
Signed-off-by: CMGS <ilskdw@gmail.com>
Co-authored-by: Anatol Belski <anbelski@linux.microsoft.com>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add pub fn alignment() to RawFile so that callers can
query the O_DIRECT buffer alignment requirement probed
at file open time.
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>
The address that is passed from the guest should be treated as
untrusted. Currently an invalid address will panic the VMM. This only
allows the guest to hurt itself, but we shouldn't have the VMM crashing.
Instead let's return an error if possible or invalidate the queue if it
happen during setup.
The data flow from guest to translate_gva/translate_gpa is:
1. Guest writes a raw u64 address into a virtio descriptor in the
shared descriptor table (guest memory).
2. The virtio-queue crate reads this descriptor via read_obj() and
returns the addr field as-is in a GuestAddress — no validation.
3. Device code calls .translate_gva(access_platform, len) on the
GuestAddress.
4. With IOMMU (access_platform is Some): the address is an IOVA that
must be translated to a GPA via the IOMMU mapping table. If the
guest provides an unmapped IOVA, translation returns Err.
Previously, .unwrap() here panicked the VMM.
5. Without IOMMU (access_platform is None): translate_gva is a no-op
(returns self). The raw address flows to GuestMemory::read_obj()
which validates it — out-of-range addresses return
Err(InvalidGuestAddress), so no host memory corruption is possible.
Signed-off-by: Dylan Reid <dgreid@fb.com>
Write a distinct byte pattern into each of eight consecutive
clusters in a single operation, then read the full range back
and verify per cluster contents.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Write data, punch hole to deallocate, then rewrite the same
range and verify the new contents read back correctly.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes 4K into the middle of a
cluster, then reads the entire cluster back. Verifies that the
written region matches and surrounding bytes remain zero. This
exercises the COW path where unwritten parts of a newly allocated
cluster must be zero filled.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that reads from a range that was never
written. Verifies the fundamental QCOW contract that unallocated
clusters return zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that submits a batch of interleaved
write and read requests via submit_batch_requests. Verifies that
all completions arrive with the correct user_data and that the
read back data matches the written data.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes distinct patterns into two
adjacent clusters, then issues a single read spanning the cluster
boundary. Verifies that multi mapping read resolution returns the
correct data from both clusters.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test that writes a byte pattern through
write_vectored, reads it back through read_vectored, and verifies
the data matches. This exercises the core async write and read
paths end to end.
Also add an async_write helper for future tests.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test for write zeroes completion. The test
verifies that a write zeroes request reports successful completion
and that the zeroed range reads back as zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a QcowAsync unit test for punch hole completion. The test
verifies that a punch hole request reports successful completion
and that the deallocated range reads back as zeroes.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Implement batch_requests_enabled() and submit_batch_requests() for
QcowAsync. Without batching, each read_vectored call performs its own
io_uring submit() syscall. With batching, the virtio queue handler
collects all pending requests and submits them in a single call,
pushing multiple SQEs before one submit() syscall.
Each request in the batch is classified through the metadata layer.
Requests that hit the fast path (single allocated cluster mapping)
are pushed to the io_uring submission queue. Requests that require
the slow path (compressed, backing, zero fill, or mixed mappings)
are completed synchronously and queued as synthetic completions.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
try_clone shares the Arc wrapped metadata and backing file.
new_async_io creates a QcowAsync worker with its own io_uring
instance for the given ring depth.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Deallocate clusters through QcowMetadata::deallocate_bytes, then
apply the resulting DeallocAction list (punch hole or write zeroes
at host offsets). write_zeroes delegates to punch_hole since
unallocated QCOW2 clusters inherently read as zero.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Flush dirty metadata caches and sync the underlying file via
QcowMetadata::flush, then signal synthetic completion.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Synchronous per cluster write path - gather guest data from iovecs,
map each cluster through QcowMetadata, and pwrite to the allocated
host offset. Partial cluster writes with a backing file read the
backing data first so map_cluster_for_write can perform COW.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Single allocated cluster reads are submitted to io_uring for true
async completion. Mixed mapping reads (zero, compressed, backing,
multi cluster) fall back to synchronous pread64 with synthetic
completions.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add the AsyncIo trait impl with notifier and next_completed_request
filled in. The remaining methods are stubbed with unimplemented
and will be filled in by subsequent commits.
next_completed_request drains io_uring completions first, then
falls back to the synthetic completion list.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Per queue I/O worker that uses io_uring for asynchronous reads
against fully allocated clusters. The struct holds the shared
metadata, data file, optional backing reader, the io_uring
instance and a synthetic completion list.
Feature gated on io_uring in lib.rs.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Marker supertrait combining all composable capability traits.
QcowDiskAsync now satisfies the full DiskFile contract.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Delegates to QcowMetadata::resize. Rejects resize when a backing
file is present, same as the sync backend.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce the device level handle for the async QCOW2 backend.
QcowDiskAsync mirrors QcowDiskSync. It parses the image, resolves
the backing chain and wraps QcowMetadata in an Arc for sharing
across virtio queues. No trait impls yet, just the struct,
constructor, Drop and Debug.
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>
Change the return type of RawFileAsyncAio::new() from
std::io::Result<Self> to BlockResult<Self>, wrapping
internal errors from EventFd::new() and IoContext::new()
in BlockError with DiskFileError::NewAsyncIo.
This simplifies the caller in AsyncDiskFile::new_async_io()
which no longer needs its own error mapping.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Remove the old async_io::DiskFile trait implementation from
RawFileDiskAio, now that the new disk_file trait hierarchy
is fully implemented.
Clean up unused imports: DiskFile and DiskFileResult from
crate::async_io.
Signed-off-by: Muminul Islam <muislam@microsoft.com>