From 55504177cbd4519e1a43a534508adbad177f3eb5 Mon Sep 17 00:00:00 2001 From: Anatol Belski Date: Wed, 4 Mar 2026 22:28:52 +0100 Subject: [PATCH] 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 --- block/src/error.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/block/src/error.rs b/block/src/error.rs index 3b7ae1f29..b94ddda06 100644 --- a/block/src/error.rs +++ b/block/src/error.rs @@ -17,6 +17,7 @@ //! ``` use std::fmt::{self, Display, Formatter}; +use std::path::PathBuf; /// Small, stable classification of block errors. /// @@ -54,3 +55,57 @@ impl Display for BlockErrorKind { } } } + +/// Classification of the operation that was in progress when an error occurred. +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +#[non_exhaustive] +pub enum ErrorOp { + /// Opening a disk image file. + Open, + /// Detecting the image format. + DetectImageType, + /// Duplicating a backing-file descriptor. + DupBackingFd, +} + +impl Display for ErrorOp { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + Self::Open => write!(f, "open"), + Self::DetectImageType => write!(f, "detect_image_type"), + Self::DupBackingFd => write!(f, "dup_backing_fd"), + } + } +} + +/// Optional diagnostic context attached to a [`BlockError`]. +#[derive(Debug, Default, Clone)] +pub struct ErrorContext { + pub path: Option, + pub offset: Option, + pub op: Option, +} + +impl Display for ErrorContext { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let mut first = true; + if let Some(path) = &self.path { + write!(f, "path={}", path.display())?; + first = false; + } + if let Some(offset) = self.offset { + if !first { + write!(f, " ")?; + } + write!(f, "offset={offset:#x}")?; + first = false; + } + if let Some(op) = self.op { + if !first { + write!(f, " ")?; + } + write!(f, "op={op}")?; + } + Ok(()) + } +}