Re: [PATCH v5 4/5] rust: block: convert `block::mq` to use `Refcount`
From: Boqun Feng <hidden>
Date: 2025-08-11 14:13:03
Also in:
lkml, rust-for-linux
On Sat, Aug 09, 2025 at 05:21:49PM +0900, Alexandre Courbot wrote:
On Thu Jul 24, 2025 at 8:32 AM JST, Gary Guo wrote:quoted
From: Gary Guo <gary@garyguo.net> Currently there's a custom reference counting in `block::mq`, which uses `AtomicU64` Rust atomics, and this type doesn't exist on some 32-bit architectures. We cannot just change it to use 32-bit atomics, because doing so will make it vulnerable to refcount overflow. So switch it to use the kernel refcount `kernel::sync::Refcount` instead. 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. Tested-by: David Gow <redacted> Acked-by: Andreas Hindborg <a.hindborg@kernel.org> Signed-off-by: Gary Guo <gary@garyguo.net> --- rust/kernel/block/mq/operations.rs | 7 ++-- rust/kernel/block/mq/request.rs | 63 ++++++++---------------------- rust/kernel/sync/refcount.rs | 14 +++++++ 3 files changed, 34 insertions(+), 50 deletions(-)diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs index c2b98f507bcbd..c0f95a9419c4e 100644 --- a/rust/kernel/block/mq/operations.rs +++ b/rust/kernel/block/mq/operations.rs@@ -10,9 +10,10 @@ block::mq::Request, error::{from_result, Result}, prelude::*, + sync::Refcount, types::ARef, }; -use core::{marker::PhantomData, sync::atomic::AtomicU64, sync::atomic::Ordering}; +use core::marker::PhantomData; /// Implement this trait to interface blk-mq as block devices. ///@@ -78,7 +79,7 @@ impl<T: Operations> OperationsVTable<T> { let request = unsafe { &*(*bd).rq.cast::<Request<T>>() }; // One refcount for the ARef, one for being in flight - request.wrapper_ref().refcount().store(2, Ordering::Relaxed); + request.wrapper_ref().refcount().set(2); // SAFETY: // - We own a refcount that we took above. We pass that to `ARef`.@@ -187,7 +188,7 @@ impl<T: Operations> OperationsVTable<T> { // SAFETY: The refcount field is allocated but not initialized, so // it is valid for writes. - unsafe { RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(AtomicU64::new(0)) }; + unsafe { RequestDataWrapper::refcount_ptr(pdu.as_ptr()).write(Refcount::new(0)) };Ah, so that's why `0` is allowed as a valid value for `Refcount::new`. Seeing the use that is made of atomics here, I wonder if `Refcount` is a good choice, or if we could adapt the code to use them as expected. I am not familiar enough with this part of the code to give informed advice unfortunately. But at the very least, I think the constructor should not be made unsafe due to account for one particular user. How about doing a
Hmm.. a refcount being 0 is not unsafe I would say, it means no one references the object (usually in a particular type of referencing). In general, one should use `Arc` and be done with that, but if you were to have different types of referencing to a same object, then one of the refcounts may end up being 0.
`Refcount::new(1)` immediately followed by a `set(0)` so other users are not tricked into creating an invalid Refcount?
This I will call bad code, as it would introduce further confusion because the `new(1)` is pretty pointless imo. Regards, Boqun