All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Gary Guo" <gary@garyguo.net>
Cc: "Alice Ryhl" <aliceryhl@google.com>,
	"Greg KH" <gregkh@linuxfoundation.org>,
	"Boqun Feng" <boqun.feng@gmail.com>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <benno.lossin@proton.me>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Jens Axboe" <axboe@kernel.dk>, "Will Deacon" <will@kernel.org>,
	"Peter Zijlstra" <peterz@infradead.org>,
	"Mark Rutland" <mark.rutland@arm.com>,
	linux-block@vger.kernel.org, rust-for-linux@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: Re: [PATCH 3/3] rust: block: convert `block::mq` to use `Refcount`
Date: Thu, 10 Oct 2024 11:06:36 +0200	[thread overview]
Message-ID: <87set4min7.fsf@kernel.org> (raw)
In-Reply-To: <871q0onyhf.fsf@kernel.org> (Andreas Hindborg's message of "Thu, 10 Oct 2024 10:39:08 +0200")

Andreas Hindborg <a.hindborg@kernel.org> writes:

> Andreas Hindborg <a.hindborg@kernel.org> writes:
>
>> "Gary Guo" <gary@garyguo.net> writes:
>>
>>> On Sat, 5 Oct 2024 13:59:44 +0200
>>> Alice Ryhl <aliceryhl@google.com> wrote:
>>>
>>>> On Sat, Oct 5, 2024 at 11:49 AM Andreas Hindborg <a.hindborg@kernel.org> wrote:
>>>> >
>>>> > Hi Greg,
>>>> >
>>>> > "Greg KH" <gregkh@linuxfoundation.org> writes:
>>>> >
>>>> > > On Fri, Oct 04, 2024 at 04:52:24PM +0100, Gary Guo wrote:
>>>> > >> There is an operation needed by `block::mq`, atomically decreasing
>>>> > >> refcount from 2 to 0, which is not available through refcount.h, so
>>>> > >> I exposed `Refcount::as_atomic` which allows accessing the refcount
>>>> > >> directly.
>>>> > >
>>>> > > That's scary, and of course feels wrong on many levels, but:
>>>> > >
>>>> > >
>>>> > >> @@ -91,13 +95,17 @@ pub(crate) unsafe fn start_unchecked(this: &ARef<Self>) {
>>>> > >>      /// C `struct request`. If the operation fails, `this` is returned in the
>>>> > >>      /// `Err` variant.
>>>> > >>      fn try_set_end(this: ARef<Self>) -> Result<*mut bindings::request, ARef<Self>> {
>>>> > >> -        // We can race with `TagSet::tag_to_rq`
>>>> > >> -        if let Err(_old) = this.wrapper_ref().refcount().compare_exchange(
>>>> > >> -            2,
>>>> > >> -            0,
>>>> > >> -            Ordering::Relaxed,
>>>> > >> -            Ordering::Relaxed,
>>>> > >> -        ) {
>>>> > >> +        // To hand back the ownership, we need the current refcount to be 2.
>>>> > >> +        // Since we can race with `TagSet::tag_to_rq`, this needs to atomically reduce
>>>> > >> +        // refcount to 0. `Refcount` does not provide a way to do this, so use the underlying
>>>> > >> +        // atomics directly.
>>>> > >> +        if this
>>>> > >> +            .wrapper_ref()
>>>> > >> +            .refcount()
>>>> > >> +            .as_atomic()
>>>> > >> +            .compare_exchange(2, 0, Ordering::Relaxed, Ordering::Relaxed)
>>>> > >> +            .is_err()
>>>> > >
>>>> > > Why not just call rust_helper_refcount_set()?  Or is the issue that you
>>>> > > think you might not be 2 here?  And if you HAVE to be 2, why that magic
>>>> > > value (i.e. why not just always be 1 and rely on normal
>>>> > > increment/decrement?)
>>>> > >
>>>> > > I know some refcounts are odd in the kernel, but I don't see where the
>>>> > > block layer is caring about 2 as a refcount anywhere, what am I missing?
>>>> >
>>>> > It is in the documentation, rendered version available here [1]. Let me
>>>> > know if it is still unclear, then I guess we need to update the docs.
>>>> >
>>>> > Also, my session from Recipes has a little bit of discussion regarding
>>>> > this refcount and it's use [2].
>>>> >
>>>> > Best regards,
>>>> > Andreas
>>>> >
>>>> >
>>>> > [1] https://rust.docs.kernel.org/kernel/block/mq/struct.Request.html#implementation-details
>>>> > [2] https://youtu.be/1LEvgkhU-t4?si=B1XnJhzCCNnUtRsI&t=1685
>>>>
>>>> So it sounds like there is one refcount from the C side, and some
>>>> number of references from the Rust side. The function checks whether
>>>> there's only one Rust reference left, and if so, takes ownership of
>>>> the value, correct?
>>>>
>>>> In that case, the CAS should have an acquire ordering to synchronize
>>>> with dropping the refcount 3->2 on another thread. Otherwise, you
>>>> might have a data race with the operations that happened just before
>>>> the 3->2 refcount drop.
>>>>
>>>> Alice
>>>
>>> The code as is is fine since there's no data protected in
>>> `RequestDataWrapper` yet (in fact it's not even generic yet). I know
>>> Andreas does want to introduce driver-specific data into that, so in
>>> the long term the acquire would be necessary.
>>>
>>> Andreas, please let me know if you want me to make the change now, or
>>> you'd rather change the ordering when you introduce data to
>>> `RequestDataWrapper`.
>>
>> I guess we will have said data dependencies when we are going to run
>> drop for fields in the private data area. Thanks for pointing that out.
>> I will update the ordering when I submit that patch.
>>
>> As I mentioned before, I would rather we do not apply this patch before
>> we get a way to inline helpers.
>
> As discussed offline, the code that suffers the performance regression
> is downstream, and since this change seems to be important, I can apply
> the helper LTO patch downstream as well.
>
> Since the plan for the downstream code _is_ to move upstream, I really
> hope to see the helper LTO patch upstream, so we don't get a performance
> regression because of these refcounts.
>
> If we cannot figure out a way to get the LTO patches (or an alternative
> solution) upstream, we can always revert back to a more performant
> solution in block.

I forgot to report the result of the benchmarks. Over the usual
benchmark workload that I run for `rnull` I see an average 0.8 percent
performance penalty with this patch. For some configurations
I see 95% CI N=40 [-18%;-5%]. So it is not insignificant.


BR Andreas


  reply	other threads:[~2024-10-10  9:06 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-04 15:52 [PATCH 0/3] implement `kernel::sync::Refcount` and convert users Gary Guo
2024-10-04 15:52 ` [PATCH 1/3] rust: implement `kernel::sync::Refcount` Gary Guo
2024-10-04 16:34   ` Dirk Behme
2024-10-04 18:51   ` Andreas Hindborg
2024-10-04 19:08     ` Gary Guo
2024-10-04 19:22       ` Andreas Hindborg
2024-10-05  6:04       ` Dirk Behme
2024-10-05  7:40   ` Greg KH
2024-10-05 13:31     ` Gary Guo
2024-10-05 14:26       ` Gary Guo
2024-10-07 12:30         ` Alice Ryhl
2024-10-04 15:52 ` [PATCH 2/3] rust: convert `Arc` to use `Refcount` Gary Guo
2024-10-05 12:06   ` Alice Ryhl
2024-10-05 13:12     ` Gary Guo
2024-10-04 15:52 ` [PATCH 3/3] rust: block: convert `block::mq` " Gary Guo
2024-10-04 16:43   ` Dirk Behme
2024-10-04 18:05   ` Andreas Hindborg
2024-10-05 15:08     ` Gary Guo
2024-10-05 18:47       ` Andreas Hindborg
2024-10-04 18:34   ` Andreas Hindborg
2024-10-04 18:43     ` Gary Guo
2024-10-04 19:18       ` Andreas Hindborg
2024-10-05  7:47   ` Greg KH
2024-10-05  9:48     ` Andreas Hindborg
2024-10-05 10:09       ` Greg KH
2024-10-05 10:10       ` Peter Zijlstra
2024-10-05 10:57         ` Andreas Hindborg
2024-10-05 11:05         ` Miguel Ojeda
2024-10-05 11:59       ` Alice Ryhl
2024-10-05 13:23         ` Gary Guo
2024-10-05 14:56           ` Andreas Hindborg
2024-10-10  8:39             ` Andreas Hindborg
2024-10-10  9:06               ` Andreas Hindborg [this message]
2024-10-10  9:48                 ` Benno Lossin
2024-10-10 11:13                   ` Andreas Hindborg
2024-10-05 14:51         ` Andreas Hindborg
2024-10-10  8:41   ` Andreas Hindborg

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=87set4min7.fsf@kernel.org \
    --to=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=axboe@kernel.dk \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=ojeda@kernel.org \
    --cc=peterz@infradead.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tmgross@umich.edu \
    --cc=will@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.