Skip to content

Replace unwrap panics with proper error propagation#10

Open
kirgene wants to merge 2 commits intoublk-org:mainfrom
kirgene:fix/error-handling
Open

Replace unwrap panics with proper error propagation#10
kirgene wants to merge 2 commits intoublk-org:mainfrom
kirgene:fix/error-handling

Conversation

@kirgene
Copy link
Copy Markdown

@kirgene kirgene commented Apr 15, 2026

I'm using qcow2-rs as a library via rublk to expose qcow2 images as ublk block devices. When rublk hits a corrupt or malformed image, the unwrap() in the IO backend's new() panics and kills the daemon. Since the kernel-side ublk device is already registered at that point, the orphaned device causes unkillable D-state processes — only a reboot fixes it.

This patch replaces unwrap() with proper error propagation across all IO backends and the setup macros, so callers get a clean error instead of a process crash.

Also fixes rqcow2 check — it was printing "non-allocated cluster" warnings but still returning exit 0, which made it useless for scripted pre-validation. Now it returns exit 1 on integrity errors.

Changes:

  • Qcow2IoSync::new(), Qcow2IoTokio::new(), Qcow2IoUring::new() return Qcow2Result instead of panicking on file open
  • qcow2_setup_dev_fn_sync! and qcow2_setup_dev_fn! macros propagate the error with ?
  • check_cluster() returns Err when a cluster is non-allocated (was Ok(()))
  • main() prints the error and exits 1 instead of panicking

Tested against a mix of valid and corrupt qcow2 images.

All IO backend new() functions (sync, tokio, uring) now return
Qcow2Result instead of panicking on file open failures. Both setup
macros propagate these errors with ?.

check_cluster now returns Err on non-allocated clusters instead of
silently printing a warning and returning Ok. main() exits with
code 1 on error instead of panicking via unwrap.
@ming1
Copy link
Copy Markdown
Collaborator

ming1 commented Apr 19, 2026

Hello,

The build is failed:

error[E0599]: no method named `read_to` found for enum `Result` in the current scope
    --> src/dev.rs:2957:24
     |
2957 |             let _ = io.read_to(0, &mut buf).await;
     |                        ^^^^^^^ method not found in `Result<Qcow2IoTokio, Qcow2Error>`
     |
note: the method `read_to` exists on the type `Qcow2IoTokio`
    --> src/ops.rs:19:5
     |
19   |     async fn read_to(&self, offset: u64, buf: &mut [u8]) -> Qcow2Result<usize>;
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
     = help: items from traits can only be used if the trait is implemented and in scope
note: `ops::Qcow2IoOps` defines an item `read_to`, perhaps you need to implement it
    --> src/ops.rs:18:1
     |
18   | pub trait Qcow2IoOps {
     | ^^^^^^^^^^^^^^^^^^^^
help: consider using `Result::expect` to unwrap the `Qcow2IoTokio` value, panicking if the value is a `Result::Err`
     |
2957 |             let _ = io.expect("REASON").read_to(0, &mut buf).await;
     |                       +++++++++++++++++

For more information about this error, try `rustc --explain E0599`.
error: could not compile `qcow2-rs` (lib test) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Thanks,

@kirgene
Copy link
Copy Markdown
Author

kirgene commented Apr 19, 2026

Fixed, added unwrap() to the test.

@kirgene kirgene force-pushed the fix/error-handling branch from e2a2196 to f5ccaa6 Compare April 19, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants