qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Kevin Wolf <kwolf@redhat.com>, qemu-block@nongnu.org
Cc: hreitz@redhat.com, manos.pitsidianakis@linaro.org,
	philmd@linaro.org, qemu-devel@nongnu.org, qemu-rust@nongnu.org
Subject: Re: [PATCH v2 09/11] rust/block: Add read support for block drivers
Date: Wed, 19 Feb 2025 07:11:07 +0100	[thread overview]
Message-ID: <0ee134e7-02bf-4b9b-9c9a-83c88386cd57@redhat.com> (raw)
In-Reply-To: <20250218182019.111467-10-kwolf@redhat.com>

On 2/18/25 19:20, Kevin Wolf wrote:
> +    /// The described blocks are stored in a child node.
> +    Data {
> +        /// Child node in which the data is stored
> +        node: Arc<BdrvChild>,

Having Arc<> here shouldn't be necessary, since the BdrvChild is already 
reference counted.  Since the code is called under the bdrv_graph_rdlock 
there's no risk of the BdrvChild going away, and you can just make it a 
&BdrvChild.

Likewise, even BochsImage should not need a standard Rust 
Arc<BdrvChild>.  However you need to add your own block::Arc<BdrvChild> 
and map Clone/Drop to bdrv_ref/bdrv_unref.  Then BochsImage can use 
block::Arc<BdrvChild>; this makes it even clearer that Mapping should 
not use the Arc<> wrapper, because bdrv_ref is GLOBAL_STATE_CODE() and 
would abort if run from a non-main thread.

That said, I'm not sure how to include "block graph lock must be taken" 
into the types, yet.  That has to be taken into account too, sooner or 
later.  You probably have a lot of items like this one so it'd be nice 
to have TODO comments as much as you can.

(This boundary is where you get an unholy mix of C and Rust concepts. 
It takes a while to get used to, and it teaches you a lot of the parts 
of Rust that you usually take for granted.  So while it's not hard, it's 
unusual and it does feel like water and oil in the beginning).

> +) -> std::os::raw::c_int {
> +    let s = unsafe { &mut *((*bs).opaque as *mut D) };

&mut is not safe here (don't worry, we went through the same thing for 
devices :)).  You can only get an & unless you go through an UnsafeCell 
(or something that contains one).  You'll need to split the mutable and 
immutable parts of BochsImage in separate structs, and embed the former 
into the latter.  Long term you there should be a 
qemu_api::coroutine::CoMutex<>, but for the short term you can just use 
a BqlRefCell<> or a standard Rust RefCell<>.  You can see how 
PL011Registers is included into PL011State in 
rust/hw/char/pl011/src/device.rs, and a small intro is also present in 
docs/devel/rust.rst.

Anyway, the BdrvChild needs to remain in BochsImage, so that it is 
accessible outside the CoMutex critical section and can be placed into 
the Mapping.

> +    let mut offset = offset as u64;
> +    let mut bytes = bytes as u64;
> +
> +    while bytes > 0 {
> +        let req = Request::Read { offset, len: bytes };
> +        let mapping = match qemu_co_run_future(s.map(&req)) {
> +            Ok(mapping) => mapping,
> +            Err(e) => return -i32::from(Errno::from(e).0),

This is indeed not great, but it's partly so because you're doing a lot 
(for some definition of "a lot") in the function.  While it would be 
possible to use a trait, I wrote the API thinking of minimal glue code 
that only does the C<->Rust conversion.

In this case, because you have a lot more code than just a call into the 
BlockDriver trait, you'd have something like

fn bdrv_co_preadv_part(
     bs: &dyn BlockDriver,
     offset: i64,
     bytes: i64,
     qiov: &bindings::QEMUIOVector,
     mut qiov_offset: usize,
     flags: bindings::BdrvRequestFlags) -> io::Result<()>

and then a wrapper (e.g. rust_co_preadv_part?) that only does

    let s = unsafe { &mut *((*bs).opaque as *mut D) };
    let qiov = unsafe { &*qiov };
    let result = bdrv_co_preadv_part(s, offset, bytes,
          qiov, qiov_offset, flags);
    errno::into_negative_errno(result)

This by the way has also code size benefits because &dyn, unlike 
generics, does not need to result in duplicated code.

For now, I'd rather keep into_negative_errno() this way, to keep an eye 
on other cases where you have an io::Error<()>.  Since Rust rarely has 
Error objects that aren't part of a Result, it stands to reason that the 
same is true of QEMU code, but if I'm wrong then it can be changed.

Paolo



  reply	other threads:[~2025-02-19  6:12 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-18 18:20 [PATCH v2 00/11] rust/block: Add minimal block driver bindings Kevin Wolf
2025-02-18 18:20 ` [PATCH v2 01/11] rust: Build separate qemu_api_tools and qemu_api_system Kevin Wolf
2025-02-20  7:10   ` Zhao Liu
2025-02-18 18:20 ` [PATCH v2 02/11] meson: Add rust_block_ss and link tools with it Kevin Wolf
2025-02-18 18:20 ` [PATCH v2 03/11] rust: Add some block layer bindings Kevin Wolf
2025-02-18 18:20 ` [PATCH v2 04/11] rust/qemu-api: Add wrappers to run futures in QEMU Kevin Wolf
2025-02-20  6:35   ` Zhao Liu
2025-02-20 14:58     ` Kevin Wolf
2025-03-05  2:15   ` Stefan Hajnoczi
2025-02-18 18:20 ` [PATCH v2 05/11] rust/block: Add empty crate Kevin Wolf
2025-02-19  6:46   ` Zhao Liu
2025-02-18 18:20 ` [PATCH v2 06/11] rust/block: Add I/O buffer traits Kevin Wolf
2025-02-18 18:20 ` [PATCH v2 07/11] block: Add bdrv_open_blockdev_ref_file() Kevin Wolf
2025-02-18 18:20 ` [PATCH v2 08/11] rust/block: Add driver module Kevin Wolf
2025-02-20  6:52   ` Zhao Liu
2025-03-05  2:43   ` Stefan Hajnoczi
2025-02-18 18:20 ` [PATCH v2 09/11] rust/block: Add read support for block drivers Kevin Wolf
2025-02-19  6:11   ` Paolo Bonzini [this message]
2025-02-19 13:02     ` Kevin Wolf
2025-02-19 22:42       ` Paolo Bonzini
2025-03-05  3:04   ` Stefan Hajnoczi
2025-03-05  9:56   ` Stefan Hajnoczi
2025-02-18 18:20 ` [PATCH v2 10/11] bochs-rs: Add bochs block driver reimplementation in Rust Kevin Wolf
2025-02-20  7:02   ` Zhao Liu
2025-03-05 10:21   ` Stefan Hajnoczi
2025-02-18 18:20 ` [PATCH v2 11/11] rust/block: Add format probing Kevin Wolf
2025-03-05 10:23 ` [PATCH v2 00/11] rust/block: Add minimal block driver bindings Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0ee134e7-02bf-4b9b-9c9a-83c88386cd57@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=hreitz@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=manos.pitsidianakis@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-rust@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).