Remove the legacy async_io::DiskFile implementation from
RawFileDiskSync now that the new disk_file trait impls are
in place.
Remove unused imports: Seek, SeekFrom, DiskFile, and
DiskFileResult.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::AsyncDiskFile trait implementation for
RawFileDiskSync with try_clone() and new_async_io() methods.
try_clone() duplicates the underlying file descriptor and
wraps it in a new RawFileDiskSync. new_async_io() creates a
RawFileSync (synchronous fallback) backend, wrapping errors
in BlockError instead of DiskFileError.
Add DiskFileError::Clone variant in async_io.rs for the
try_clone() error path.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add empty disk_file::DiskFile impl for RawFileDiskSync.
This marker supertrait requires DiskSize + Geometry + Sync,
all of which are now satisfied.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Resizable trait implementation for
RawFileDiskSync. Calls file.set_len(size) and wraps the
I/O error in BlockError on failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::SparseCapable trait implementation for
RawFileDiskSync. Delegates to probe_sparse_support() to
detect whether the underlying file supports hole-punching.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Geometry trait implementation for
RawFileDiskSync. Probes disk topology from the file,
falling back to defaults on failure. Takes &self instead
of &mut self and uses unwrap_or_else for cleaner error
handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskFd trait implementation for
RawFileDiskSync. Delegates to file.as_raw_fd() via
BorrowedDiskFd, taking &self instead of &mut self.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::PhysicalSize trait implementation for
RawFileDiskSync. Returns metadata().len() wrapped in
BlockError on failure, consistent with the DiskSize impl.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskSize trait implementation for
RawFileDiskSync using BlockError and BlockResult. Uses
metadata().len() instead of seek(SeekFrom::End(0)), taking
&self instead of &mut self.
Add BlockError, BlockErrorKind, BlockResult, and disk_file
imports needed by this and subsequent trait impls.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add #[derive(Debug)] to RawFileDiskSync. This is required
by the new disk_file traits which have Send + Debug bounds.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Update device_manager.rs to construct DiskBackend::Next
instead of DiskBackend::Legacy for the io_uring raw backend.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::AsyncDiskFile trait implementation for
RawFileDisk with try_clone() and new_async_io() methods.
try_clone() duplicates the underlying file descriptor and
wraps it in a new RawFileDisk. new_async_io() creates a
RawFileAsync (io_uring) backend, wrapping errors in
BlockError instead of DiskFileError.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add empty disk_file::DiskFile impl for RawFileDisk. This
marker supertrait requires DiskSize + Geometry + Sync, all
of which are now satisfied.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Resizable trait implementation for
RawFileDisk. Calls file.set_len(size) and wraps the I/O
error in BlockError on failure.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::SparseCapable trait implementation for
RawFileDisk. Delegates to probe_sparse_support() to detect
whether the underlying file supports hole-punching.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::Geometry trait implementation for RawFileDisk.
Probes disk topology from the file, falling back to defaults
on failure. Takes &self instead of &mut self and uses
unwrap_or_else for cleaner error handling.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskFd trait implementation for RawFileDisk.
Delegates to file.as_raw_fd() via BorrowedDiskFd, taking
&self instead of &mut self.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::PhysicalSize trait implementation for
RawFileDisk. Returns metadata().len() wrapped in BlockError
on failure, consistent with the DiskSize impl.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add disk_file::DiskSize trait implementation for RawFileDisk
using BlockError and BlockResult. Uses metadata().len()
instead of seek(SeekFrom::End(0)), taking &self instead of
&mut self.
Add BlockError, BlockErrorKind, BlockResult, and disk_file
imports needed by this and subsequent trait impls.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add #[derive(Debug)] to RawFileDisk. This is required by the
new disk_file traits which have Send + Debug bounds.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Add a Clone variant to DiskFileError for error handling in
the upcoming AsyncDiskFile::try_clone() implementations.
This variant will be used by RawFileDisk and RawFileDiskSync
when cloning the underlying file descriptor fails.
Signed-off-by: Muminul Islam <muislam@microsoft.com>
Use query_device_size() instead of metadata().len() to correctly
handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Use query_device_size() instead of seek(End(0)) and metadata().len()
to correctly handle block device and regular file handles.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add a shared helper that returns the logical size in bytes for both
regular files and block devices using an immutable &File reference.
Regular files use metadata().len(). Block devices use the BLKGETSIZE64
ioctl. Any other file type returns an InvalidInput error.
This avoids seek(SeekFrom::End(0)) which requires &mut self and can
return incorrect results for block devices when the file position is
in an unexpected state.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Include the number of segments found in the request payload in
the TooManySegments error variant so the logged message shows
both the actual and maximum values.
Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Introduce DISCARD_WZ_MAX_PAYLOAD as the precomputed product of
DISCARD_WZ_SEG_SIZE and MAX_DISCARD_WRITE_ZEROES_SEG. Use it in the
DISCARD and WRITE_ZEROES segment count checks instead of repeating
the multiplication inline.
Suggested-by: Philipp Schuster <philipp.schuster@cyberus-technology.de>
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Add range validation for DISCARD and WRITE_ZEROES, matching the
existing check in the read/write path. Per virtio spec section
5.2.6.1, a driver must not submit a request which would cause a
read or write beyond capacity. Use checked_add to guard against
overflow, then compare against disk_nsectors.
Without this, requests beyond device capacity pass through to the
host punch_hole/write_zeroes calls, relying on backend specific
behavior rather than returning VIRTIO_BLK_S_IOERR consistently.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
Split the data length check into two conditions:
- reject descriptors shorter than one
virtio_blk_discard_write_zeroes segment, and
- reject payloads exceeding MAX_DISCARD_WRITE_ZEROES_SEG segments
Previously only the minimum length was checked and extra segments
were silently dropped.
Signed-off-by: Anatol Belski <anbelski@linux.microsoft.com>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>