* [PATCH RFC 1/2] rust: rcu: add RcuBox type
2026-01-16 15:46 [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Alice Ryhl
@ 2026-01-16 15:46 ` Alice Ryhl
2026-01-16 16:23 ` Joel Fernandes
2026-01-16 15:46 ` [PATCH RFC 2/2] rust: maple_tree: add load_rcu() Alice Ryhl
2026-01-17 0:06 ` [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Boqun Feng
2 siblings, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-16 15:46 UTC (permalink / raw)
To: Paul E. McKenney, Boqun Feng, Liam R. Howlett
Cc: Gary Guo, Miguel Ojeda, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes,
Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, Andrew Ballance,
linux-kernel, rust-for-linux, rcu, maple-tree, linux-mm,
Alice Ryhl
This adds an RcuBox container, which is like KBox except that the value
is freed with kfree_rcu.
To allow containers to rely on the rcu properties of RcuBox, an
extension of ForeignOwnable is added.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/bindings/bindings_helper.h | 1 +
rust/kernel/sync/rcu.rs | 31 ++++++++-
rust/kernel/sync/rcu/rcu_box.rs | 145 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 176 insertions(+), 1 deletion(-)
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index a067038b4b422b4256f4a2b75fe644d47e6e82c8..8d4b90383cd8d8ca7692586d13189b71c6dbab3e 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -75,6 +75,7 @@
#include <linux/property.h>
#include <linux/pwm.h>
#include <linux/random.h>
+#include <linux/rcupdate.h>
#include <linux/refcount.h>
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
index a32bef6e490b0eebdb93f2636cf10e177036a6a9..7234fe3e79ee920172c5094d2b0e46147e1d8313 100644
--- a/rust/kernel/sync/rcu.rs
+++ b/rust/kernel/sync/rcu.rs
@@ -4,7 +4,16 @@
//!
//! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
-use crate::{bindings, types::NotThreadSafe};
+use crate::{
+ bindings,
+ types::{
+ ForeignOwnable,
+ NotThreadSafe, //
+ }, //
+};
+
+mod rcu_box;
+pub use self::rcu_box::RcuBox;
/// Evidence that the RCU read side lock is held on the current thread/CPU.
///
@@ -50,3 +59,23 @@ fn drop(&mut self) {
pub fn read_lock() -> Guard {
Guard::new()
}
+
+/// Declares that a pointer type is rcu safe.
+pub trait ForeignOwnableRcu: ForeignOwnable {
+ /// Type used to immutably borrow an rcu-safe value that is currently foreign-owned.
+ type RcuBorrowed<'a>;
+
+ /// Borrows a foreign-owned object immutably for an rcu grace period.
+ ///
+ /// This method provides a way to access a foreign-owned rcu-safe value from Rust immutably.
+ ///
+ /// # Safety
+ ///
+ /// * The provided pointer must have been returned by a previous call to [`into_foreign`].
+ /// * If [`from_foreign`] is called, then `'a` must not end after the call to `from_foreign`
+ /// plus one rcu grace period.
+ ///
+ /// [`into_foreign`]: ForeignOwnable::into_foreign
+ /// [`from_foreign`]: ForeignOwnable::from_foreign
+ unsafe fn rcu_borrow<'a>(ptr: *mut ffi::c_void) -> Self::RcuBorrowed<'a>;
+}
diff --git a/rust/kernel/sync/rcu/rcu_box.rs b/rust/kernel/sync/rcu/rcu_box.rs
new file mode 100644
index 0000000000000000000000000000000000000000..2508fdb609ecc12a85a1830a84f58ddaf962d1ec
--- /dev/null
+++ b/rust/kernel/sync/rcu/rcu_box.rs
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2026 Google LLC.
+
+//! Provides the `RcuBox` type for Rust allocations that live for a grace period.
+
+use core::{ops::Deref, ptr::NonNull};
+
+use kernel::{
+ alloc::{self, AllocError},
+ bindings,
+ ffi::c_void,
+ prelude::*,
+ sync::rcu::{ForeignOwnableRcu, Guard},
+ types::ForeignOwnable,
+};
+
+/// A box that is freed with rcu.
+///
+/// The value must be `Send`, as rcu may drop it on another thread.
+///
+/// # Invariants
+///
+/// * The pointer is valid and references a pinned `RcuBoxInner<T>` allocated with `kmalloc`.
+/// * This `RcuBox` holds exclusive permissions to rcu free the allocation.
+pub struct RcuBox<T: Send>(NonNull<RcuBoxInner<T>>);
+
+struct RcuBoxInner<T> {
+ value: T,
+ rcu_head: bindings::callback_head,
+}
+
+// Note that `T: Sync` is required since when moving an `RcuBox<T>`, the previous owner may still
+// access `&T` for one grace period.
+//
+// SAFETY: Ownership of the `RcuBox<T>` allows for `&T` and dropping the `T`, so `T: Send + Sync`
+// implies `RcuBox<T>: Send`.
+unsafe impl<T: Send + Sync> Send for RcuBox<T> {}
+
+// SAFETY: `&RcuBox<T>` allows for no operations other than those permitted by `&T`, so `T: Sync`
+// implies `RcuBox<T>: Sync`.
+unsafe impl<T: Send + Sync> Sync for RcuBox<T> {}
+
+impl<T: Send> RcuBox<T> {
+ /// Create a new `RcuBox`.
+ pub fn new(x: T, flags: alloc::Flags) -> Result<Self, AllocError> {
+ let b = KBox::new(
+ RcuBoxInner {
+ value: x,
+ rcu_head: Default::default(),
+ },
+ flags,
+ )?;
+
+ // INVARIANT:
+ // * The pointer contains a valid `RcuBoxInner` allocated with `kmalloc`.
+ // * We just allocated it, so we own free permissions.
+ Ok(RcuBox(NonNull::from(KBox::leak(b))))
+ }
+
+ /// Access the value for a grace period.
+ pub fn with_rcu<'rcu>(&self, _read_guard: &'rcu Guard) -> &'rcu T {
+ // SAFETY: The `RcuBox` has not been dropped yet, so the value is valid for at least one
+ // grace period.
+ unsafe { &(*self.0.as_ptr()).value }
+ }
+}
+
+impl<T: Send> Deref for RcuBox<T> {
+ type Target = T;
+ fn deref(&self) -> &T {
+ // SAFETY: While the `RcuBox<T>` exists, the value remains valid.
+ unsafe { &(*self.0.as_ptr()).value }
+ }
+}
+
+// SAFETY:
+// * The `RcuBoxInner<T>` was allocated with `kmalloc`.
+// * `NonNull::as_ptr` returns a non-null pointer.
+unsafe impl<T: Send + 'static> ForeignOwnable for RcuBox<T> {
+ const FOREIGN_ALIGN: usize = <KBox<RcuBoxInner<T>> as ForeignOwnable>::FOREIGN_ALIGN;
+
+ type Borrowed<'a> = &'a T;
+ type BorrowedMut<'a> = &'a T;
+
+ fn into_foreign(self) -> *mut c_void {
+ self.0.as_ptr().cast()
+ }
+
+ unsafe fn from_foreign(ptr: *mut c_void) -> Self {
+ // INVARIANT: Pointer returned by `into_foreign` carries same invariants as `RcuBox<T>`.
+ // SAFETY: `into_foreign` never returns a null pointer.
+ Self(unsafe { NonNull::new_unchecked(ptr.cast()) })
+ }
+
+ unsafe fn borrow<'a>(ptr: *mut c_void) -> &'a T {
+ // SAFETY: Caller ensures that `'a` is short enough.
+ unsafe { &(*ptr.cast::<RcuBoxInner<T>>()).value }
+ }
+
+ unsafe fn borrow_mut<'a>(ptr: *mut c_void) -> &'a T {
+ // SAFETY: `borrow_mut` has strictly stronger preconditions than `borrow`.
+ unsafe { Self::borrow(ptr) }
+ }
+}
+
+impl<T: Send + 'static> ForeignOwnableRcu for RcuBox<T> {
+ type RcuBorrowed<'a> = &'a T;
+
+ unsafe fn rcu_borrow<'a>(ptr: *mut c_void) -> &'a T {
+ // SAFETY: `RcuBox::drop` can only run after `from_foreign` is called, and the value is
+ // valid until `RcuBox::drop` plus one grace period.
+ unsafe { &(*ptr.cast::<RcuBoxInner<T>>()).value }
+ }
+}
+
+impl<T: Send> Drop for RcuBox<T> {
+ fn drop(&mut self) {
+ // SAFETY: The `rcu_head` field is in-bounds of a valid allocation.
+ let rcu_head = unsafe { &raw mut (*self.0.as_ptr()).rcu_head };
+ if core::mem::needs_drop::<T>() {
+ // SAFETY: `rcu_head` is the `rcu_head` field of `RcuBoxInner<T>`. All users will be
+ // gone in an rcu grace period. This is the destructor, so we may pass ownership of the
+ // allocation.
+ unsafe { bindings::call_rcu(rcu_head, Some(drop_rcu_box::<T>)) };
+ } else {
+ // SAFETY: All users will be gone in an rcu grace period.
+ unsafe { bindings::kvfree_call_rcu(rcu_head, self.0.as_ptr().cast()) };
+ }
+ }
+}
+
+/// Free this `RcuBoxInner<T>`.
+///
+/// # Safety
+///
+/// `head` references the `rcu_head` field of an `RcuBoxInner<T>` that has no references to it.
+/// Ownership of the `KBox<RcuBoxInner<T>>` must be passed.
+unsafe extern "C" fn drop_rcu_box<T>(head: *mut bindings::callback_head) {
+ // SAFETY: Caller provides a pointer to the `rcu_head` field of a `RcuBoxInner<T>`.
+ let box_inner = unsafe { crate::container_of!(head, RcuBoxInner<T>, rcu_head) };
+
+ // SAFETY: Caller ensures exclusive access and passed ownership.
+ drop(unsafe { KBox::from_raw(box_inner) });
+}
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 1/2] rust: rcu: add RcuBox type
2026-01-16 15:46 ` [PATCH RFC 1/2] rust: rcu: add RcuBox type Alice Ryhl
@ 2026-01-16 16:23 ` Joel Fernandes
0 siblings, 0 replies; 18+ messages in thread
From: Joel Fernandes @ 2026-01-16 16:23 UTC (permalink / raw)
To: Alice Ryhl, Paul E. McKenney, Boqun Feng, Liam R. Howlett
Cc: Gary Guo, Miguel Ojeda, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Frederic Weisbecker, Neeraj Upadhyay, Josh Triplett,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Zqiang, Andrew Ballance, linux-kernel,
rust-for-linux, rcu, maple-tree, linux-mm
On 1/16/2026 10:46 AM, Alice Ryhl wrote:
> +impl<T: Send> Drop for RcuBox<T> {
> + fn drop(&mut self) {
> + // SAFETY: The `rcu_head` field is in-bounds of a valid allocation.
> + let rcu_head = unsafe { &raw mut (*self.0.as_ptr()).rcu_head };
> + if core::mem::needs_drop::<T>() {
> + // SAFETY: `rcu_head` is the `rcu_head` field of `RcuBoxInner<T>`. All users will be
> + // gone in an rcu grace period. This is the destructor, so we may pass ownership of the
> + // allocation.
> + unsafe { bindings::call_rcu(rcu_head, Some(drop_rcu_box::<T>)) };
> + } else {
> + // SAFETY: All users will be gone in an rcu grace period.
> + unsafe { bindings::kvfree_call_rcu(rcu_head, self.0.as_ptr().cast()) };
> + }
> + }
We should probably add support for asynchronous callbacks for Rust instead of
directly calling the bindings in Rcubox. I know Boqun and me talked about that a
while back, and there was a usecase missing. Perhaps, RcuBox is a good use case
for the same?
- Joel
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH RFC 2/2] rust: maple_tree: add load_rcu()
2026-01-16 15:46 [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Alice Ryhl
2026-01-16 15:46 ` [PATCH RFC 1/2] rust: rcu: add RcuBox type Alice Ryhl
@ 2026-01-16 15:46 ` Alice Ryhl
2026-01-17 0:06 ` [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Boqun Feng
2 siblings, 0 replies; 18+ messages in thread
From: Alice Ryhl @ 2026-01-16 15:46 UTC (permalink / raw)
To: Paul E. McKenney, Boqun Feng, Liam R. Howlett
Cc: Gary Guo, Miguel Ojeda, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes,
Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, Andrew Ballance,
linux-kernel, rust-for-linux, rcu, maple-tree, linux-mm,
Alice Ryhl
Now that we have a concept of rcu-safe containers, we may add a
load_rcu() method to MapleTree that does not take the spinlock.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
rust/kernel/maple_tree.rs | 52 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/rust/kernel/maple_tree.rs b/rust/kernel/maple_tree.rs
index e72eec56bf5772ada09239f47748cd649212d8b0..c466a9fe0a9a059ad5cff131085d610b76050420 100644
--- a/rust/kernel/maple_tree.rs
+++ b/rust/kernel/maple_tree.rs
@@ -16,6 +16,10 @@
alloc::Flags,
error::to_result,
prelude::*,
+ sync::rcu::{
+ self,
+ ForeignOwnableRcu, //
+ },
types::{ForeignOwnable, Opaque},
};
@@ -233,6 +237,54 @@ pub fn erase(&self, index: usize) -> Option<T> {
unsafe { T::try_from_foreign(ret) }
}
+ /// Load the value at the given index with rcu.
+ ///
+ /// # Examples
+ ///
+ /// Read the value under an rcu read lock. Even if the value is removed, it remains accessible
+ /// for one rcu grace period.
+ ///
+ /// ```ignore
+ /// use kernel::{
+ /// maple_tree::MapleTree,
+ /// sync::rcu::{self, RcuBox},
+ /// };
+ ///
+ /// let tree = KBox::pin_init(MapleTree::<RcuBox<i32>>::new(), GFP_KERNEL)?;
+ ///
+ /// let ten = RcuBox::new(10, GFP_KERNEL)?;
+ /// tree.insert(100, ten, GFP_KERNEL)?;
+ ///
+ /// let rcu_read_lock = rcu::Guard::new();
+ /// let ten = tree.load_rcu(100, &rcu_read_lock);
+ /// assert_eq!(ten, Some(&10));
+ ///
+ /// // Even if the value gets removed, we may continue to access it for one rcu grace period.
+ /// tree.erase(100);
+ /// assert_eq!(ten, Some(&10));
+ /// # Ok::<_, Error>(())
+ /// ```
+ #[inline]
+ pub fn load_rcu<'rcu>(
+ &self,
+ index: usize,
+ _rcu: &'rcu rcu::Guard,
+ ) -> Option<T::RcuBorrowed<'rcu>>
+ where
+ T: ForeignOwnableRcu,
+ {
+ // SAFETY: `self.tree` contains a valid maple tree.
+ let ret = unsafe { bindings::mtree_load(self.tree.get(), index) };
+ if ret.is_null() {
+ return None;
+ }
+
+ // SAFETY: If the pointer is not null, then it references a valid instance of `T`. It is
+ // safe to borrow the instance for 'rcu because the signature of this function enforces that
+ // the borrow does not outlive an rcu grace period.
+ Some(unsafe { T::rcu_borrow(ret) })
+ }
+
/// Lock the internal spinlock.
#[inline]
pub fn lock(&self) -> MapleGuard<'_, T> {
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-16 15:46 [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Alice Ryhl
2026-01-16 15:46 ` [PATCH RFC 1/2] rust: rcu: add RcuBox type Alice Ryhl
2026-01-16 15:46 ` [PATCH RFC 2/2] rust: maple_tree: add load_rcu() Alice Ryhl
@ 2026-01-17 0:06 ` Boqun Feng
2026-01-17 11:55 ` Alice Ryhl
2 siblings, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 0:06 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Fri, Jan 16, 2026 at 03:46:35PM +0000, Alice Ryhl wrote:
> I'm sending this RFC to share an experiment I'm looking at. This may let
> us replace the range allocator in Rust Binder with a maple tree.
>
Thank you, Alice.
> An RcuBox is like a Box except that it lets you obtain a &T that
> outlives the box by a grace period. It does not allow mutable access to
I think the `RcuBox` can be folded into the more generic RCU pointer api
[1], e.g. Rcu<Box<RcuBoxInner<T>>> where RcuBoxInner<T>: HasRcuHead. The
benefits are at least 1) we use relaxed atomic read for RCU readers
which guarantees address dependency that RCU needs under LKMM (while in
the RcuBox here, we just use plain reads), 2) we also support mutable
access as well.
As for the progress of that effort, the Rcu atomic pointer is almost
ready [2], I will likely send it early next week. For the `HasRcuHead`
part, as you may be aware, I'm working on a generic `HasField` approach
to avoid duplication of `Has*` trait and macros [3], that requires some
syn adjustments from Gary and Benno, but they should be available next
cycle. I will probably send the patches for reviews before that. Once we
have that `HasRcuHead` should be easily to add.
Given the WIP code I have, I *think* we are not that far from providing
what you need for binder.
> the inner value (Binder would probably use LockedBy for inner values).
>
[1]: https://lore.kernel.org/rust-for-linux/20250421164221.1121805-13-boqun.feng@gmail.com/
[2]: https://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git/log/?h=rust-sync
[3]: https://git.kernel.org/pub/scm/linux/kernel/git/boqun/linux.git/log/?h=rust-field
Regards,
Boqun
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> Alice Ryhl (2):
> rust: rcu: add RcuBox type
> rust: maple_tree: add load_rcu()
>
> rust/bindings/bindings_helper.h | 1 +
> rust/kernel/maple_tree.rs | 52 ++++++++++++++
> rust/kernel/sync/rcu.rs | 31 ++++++++-
> rust/kernel/sync/rcu/rcu_box.rs | 145 ++++++++++++++++++++++++++++++++++++++++
> 4 files changed, 228 insertions(+), 1 deletion(-)
> ---
> base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> change-id: 20260116-rcu-box-7a8e4c9f2180
>
> Best regards,
> --
> Alice Ryhl <aliceryhl@google.com>
>
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 0:06 ` [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu Boqun Feng
@ 2026-01-17 11:55 ` Alice Ryhl
2026-01-17 12:11 ` Boqun Feng
0 siblings, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-17 11:55 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 08:06:40AM +0800, Boqun Feng wrote:
> On Fri, Jan 16, 2026 at 03:46:35PM +0000, Alice Ryhl wrote:
> > I'm sending this RFC to share an experiment I'm looking at. This may let
> > us replace the range allocator in Rust Binder with a maple tree.
> >
>
> Thank you, Alice.
>
> > An RcuBox is like a Box except that it lets you obtain a &T that
> > outlives the box by a grace period. It does not allow mutable access to
>
> I think the `RcuBox` can be folded into the more generic RCU pointer api
> [1], e.g. Rcu<Box<RcuBoxInner<T>>> where RcuBoxInner<T>: HasRcuHead. The
> benefits are at least 1) we use relaxed atomic read for RCU readers
> which guarantees address dependency that RCU needs under LKMM (while in
> the RcuBox here, we just use plain reads), 2) we also support mutable
> access as well.
1) But mtree_load() does use rcu_dereference() to obtain the pointer?
1) "relaxed atomic" does not sound like something that provides an
address dependency to me.
2) How do you intend to provide mutable access? By waiting a grace
period?
> As for the progress of that effort, the Rcu atomic pointer is almost
> ready [2], I will likely send it early next week. For the `HasRcuHead`
> part, as you may be aware, I'm working on a generic `HasField` approach
> to avoid duplication of `Has*` trait and macros [3], that requires some
> syn adjustments from Gary and Benno, but they should be available next
> cycle. I will probably send the patches for reviews before that. Once we
> have that `HasRcuHead` should be easily to add.
>
> Given the WIP code I have, I *think* we are not that far from providing
> what you need for binder.
Hmm, so I looked over [2], and I think my RcuBox is an RcuOld<_> rather
than an Rcu<_> under this model. Though I can't afford to pay
synchronize_rcu() for cleanup - I need kfree_rcu().
Alice
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 11:55 ` Alice Ryhl
@ 2026-01-17 12:11 ` Boqun Feng
2026-01-17 13:11 ` Boqun Feng
2026-01-17 13:12 ` Alice Ryhl
0 siblings, 2 replies; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 12:11 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 11:55:06AM +0000, Alice Ryhl wrote:
> On Sat, Jan 17, 2026 at 08:06:40AM +0800, Boqun Feng wrote:
> > On Fri, Jan 16, 2026 at 03:46:35PM +0000, Alice Ryhl wrote:
> > > I'm sending this RFC to share an experiment I'm looking at. This may let
> > > us replace the range allocator in Rust Binder with a maple tree.
> > >
> >
> > Thank you, Alice.
> >
> > > An RcuBox is like a Box except that it lets you obtain a &T that
> > > outlives the box by a grace period. It does not allow mutable access to
> >
> > I think the `RcuBox` can be folded into the more generic RCU pointer api
> > [1], e.g. Rcu<Box<RcuBoxInner<T>>> where RcuBoxInner<T>: HasRcuHead. The
> > benefits are at least 1) we use relaxed atomic read for RCU readers
> > which guarantees address dependency that RCU needs under LKMM (while in
> > the RcuBox here, we just use plain reads), 2) we also support mutable
> > access as well.
>
> 1) But mtree_load() does use rcu_dereference() to obtain the pointer?
> 1) "relaxed atomic" does not sound like something that provides an
> address dependency to me.
If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
address dependency (Please see the DEPENDENCY part in
tools/memory-model/Documentation/explanation.txt).
> 2) How do you intend to provide mutable access? By waiting a grace
> period?
Please see the {read_}copy_update() in the RCU patches that I linked.
In short, you don't wait a grace for mutable access, since in RCU,
readers don't block updaters, but instead updater will copy the object,
atomically update the pointer and then get an `RcuOld`,
which you can either synchronize_rcu() or {call,kfree}_rcu().
> > As for the progress of that effort, the Rcu atomic pointer is almost
> > ready [2], I will likely send it early next week. For the `HasRcuHead`
> > part, as you may be aware, I'm working on a generic `HasField` approach
> > to avoid duplication of `Has*` trait and macros [3], that requires some
> > syn adjustments from Gary and Benno, but they should be available next
> > cycle. I will probably send the patches for reviews before that. Once we
> > have that `HasRcuHead` should be easily to add.
> >
> > Given the WIP code I have, I *think* we are not that far from providing
> > what you need for binder.
>
> Hmm, so I looked over [2], and I think my RcuBox is an RcuOld<_> rather
> than an Rcu<_> under this model. Though I can't afford to pay
I don't think so, `RcuOld` represents an unpublished object while `Rcu`
represents a published object, you can update an `Rcu` pointer to
another object, which is normally how you update with RCU. But maybe
it's easy to discuss this with updater side code in picture.
> synchronize_rcu() for cleanup - I need kfree_rcu().
>
That's something we can add later, for example, we can give `Rcu` (we
can add the similar thing to `RcuOld`) a generic const like:
struct Rcu<P, const ASYNC: u64 = 0>(..)
where Rcu<P, 0> use synchronize_rcu() and Rcu<P, 1> use kfree_rcu() or
call_rcu() (once we have HasRcuHead support).
Regards,
Boqun
> Alice
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 12:11 ` Boqun Feng
@ 2026-01-17 13:11 ` Boqun Feng
2026-01-17 13:29 ` Alice Ryhl
2026-01-17 13:12 ` Alice Ryhl
1 sibling, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 13:11 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 08:11:17PM +0800, Boqun Feng wrote:
[...]
> > > > An RcuBox is like a Box except that it lets you obtain a &T that
> > > > outlives the box by a grace period. It does not allow mutable access to
> > >
> > > I think the `RcuBox` can be folded into the more generic RCU pointer api
> > > [1], e.g. Rcu<Box<RcuBoxInner<T>>> where RcuBoxInner<T>: HasRcuHead. The
> > > benefits are at least 1) we use relaxed atomic read for RCU readers
> > > which guarantees address dependency that RCU needs under LKMM (while in
> > > the RcuBox here, we just use plain reads), 2) we also support mutable
> > > access as well.
> >
> > 1) But mtree_load() does use rcu_dereference() to obtain the pointer?
I see, I need to change my reply to "RcuOld" below..
[...]
> >
> > Hmm, so I looked over [2], and I think my RcuBox is an RcuOld<_> rather
> > than an Rcu<_> under this model. Though I can't afford to pay
>
> I don't think so, `RcuOld` represents an unpublished object while `Rcu`
> represents a published object, you can update an `Rcu` pointer to
> another object, which is normally how you update with RCU. But maybe
> it's easy to discuss this with updater side code in picture.
>
I think a more accurate reply should be `RcuOld` is still not designed
for the usage of `RcuBox`. You're right that `RcuBox` is not an `Rcu<_>`
since `RcuBox` don't have the atomic pointer part, instead it relies
other atomic pointer operations to work (for example, the
rcu_dereference() in mtree_load()).
`RcuBox` represents an object pointed (and protected) by RCU.
`Rcu<_>` is an atomic pointer that maintains read and update for RCU, in
your usage, you don't need it because maple tree does that for you.
`RcuOld<_>` works with `Rcu<_>` to provide an API for users to decide
how to handle RCU reclaim. In Rcu + RcuOld design, RcuBox is just a Box
because these two pointer types handle reclaim + accesses.
We will need to use `Rcu` and `RcuOld` where the RCU access code is in
Rust.
I think there are similarities between `RcuOld` and `RcuBox`, but they
are sort of designed with different usages in mind, lemme think more..
Regards,
Boqun
> > synchronize_rcu() for cleanup - I need kfree_rcu().
> >
>
> That's something we can add later, for example, we can give `Rcu` (we
> can add the similar thing to `RcuOld`) a generic const like:
>
> struct Rcu<P, const ASYNC: u64 = 0>(..)
>
> where Rcu<P, 0> use synchronize_rcu() and Rcu<P, 1> use kfree_rcu() or
> call_rcu() (once we have HasRcuHead support).
>
> Regards,
> Boqun
>
> > Alice
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 13:11 ` Boqun Feng
@ 2026-01-17 13:29 ` Alice Ryhl
2026-01-17 14:05 ` Boqun Feng
0 siblings, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-17 13:29 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 09:11:49PM +0800, Boqun Feng wrote:
> In Rcu + RcuOld design, RcuBox is just a Box
> because these two pointer types handle reclaim + accesses.
How would that work? Dropping my RcuBox<_> must use kfree_rcu() or
synchronize_rcu() or it is unsound. So it can't just be a Box.
Alice
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 13:29 ` Alice Ryhl
@ 2026-01-17 14:05 ` Boqun Feng
2026-01-17 15:39 ` Boqun Feng
0 siblings, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 14:05 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 01:29:25PM +0000, Alice Ryhl wrote:
> On Sat, Jan 17, 2026 at 09:11:49PM +0800, Boqun Feng wrote:
> > In Rcu + RcuOld design, RcuBox is just a Box
> > because these two pointer types handle reclaim + accesses.
>
> How would that work? Dropping my RcuBox<_> must use kfree_rcu() or
> synchronize_rcu() or it is unsound. So it can't just be a Box.
>
RcuOld<P: ForeignOwnable> will call synchronize_rcu() before dropping
`P`. And I think we can have an asynchronous drop pointer type like
`RcuOld<P, Async>` that requires `P` is a type like `Box<HasRcuHead>`,
and the drop of `RcuOld<Box<HasRcuHead>, Async>` would be `call_rcu()`
or `kfree_rcu()`.
Regards,
Boqun
> Alice
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 14:05 ` Boqun Feng
@ 2026-01-17 15:39 ` Boqun Feng
2026-01-17 16:46 ` Gary Guo
0 siblings, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 15:39 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 10:05:18PM +0800, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 01:29:25PM +0000, Alice Ryhl wrote:
> > On Sat, Jan 17, 2026 at 09:11:49PM +0800, Boqun Feng wrote:
> > > In Rcu + RcuOld design, RcuBox is just a Box
> > > because these two pointer types handle reclaim + accesses.
> >
> > How would that work? Dropping my RcuBox<_> must use kfree_rcu() or
> > synchronize_rcu() or it is unsound. So it can't just be a Box.
> >
>
> RcuOld<P: ForeignOwnable> will call synchronize_rcu() before dropping
> `P`. And I think we can have an asynchronous drop pointer type like
> `RcuOld<P, Async>` that requires `P` is a type like `Box<HasRcuHead>`,
One blocker on that is Drop impls cannot be specialized. We probably
need a different pointer type like RcuOldAsync...
Regards,
Boqun
> and the drop of `RcuOld<Box<HasRcuHead>, Async>` would be `call_rcu()`
> or `kfree_rcu()`.
>
> Regards,
> Boqun
>
> > Alice
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 15:39 ` Boqun Feng
@ 2026-01-17 16:46 ` Gary Guo
0 siblings, 0 replies; 18+ messages in thread
From: Gary Guo @ 2026-01-17 16:46 UTC (permalink / raw)
To: Boqun Feng, Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat Jan 17, 2026 at 3:39 PM GMT, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 10:05:18PM +0800, Boqun Feng wrote:
>> On Sat, Jan 17, 2026 at 01:29:25PM +0000, Alice Ryhl wrote:
>> > On Sat, Jan 17, 2026 at 09:11:49PM +0800, Boqun Feng wrote:
>> > > In Rcu + RcuOld design, RcuBox is just a Box
>> > > because these two pointer types handle reclaim + accesses.
>> >
>> > How would that work? Dropping my RcuBox<_> must use kfree_rcu() or
>> > synchronize_rcu() or it is unsound. So it can't just be a Box.
>> >
>>
>> RcuOld<P: ForeignOwnable> will call synchronize_rcu() before dropping
>> `P`. And I think we can have an asynchronous drop pointer type like
>> `RcuOld<P, Async>` that requires `P` is a type like `Box<HasRcuHead>`,
>
> One blocker on that is Drop impls cannot be specialized. We probably
> need a different pointer type like RcuOldAsync...
I won't be too worried on this apsect, you could just branch on a const in the
drop function.
Alternatively, we can have a method like this
impl<T: HasRcuHead> RcuOld<Box<T>> {
fn drop_async(self) {
// do call_rcu
}
}
Best,
Gary
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 12:11 ` Boqun Feng
2026-01-17 13:11 ` Boqun Feng
@ 2026-01-17 13:12 ` Alice Ryhl
2026-01-17 14:00 ` Boqun Feng
1 sibling, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-17 13:12 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 08:11:17PM +0800, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 11:55:06AM +0000, Alice Ryhl wrote:
> > On Sat, Jan 17, 2026 at 08:06:40AM +0800, Boqun Feng wrote:
> > > On Fri, Jan 16, 2026 at 03:46:35PM +0000, Alice Ryhl wrote:
> > > > I'm sending this RFC to share an experiment I'm looking at. This may let
> > > > us replace the range allocator in Rust Binder with a maple tree.
> > > >
> > >
> > > Thank you, Alice.
> > >
> > > > An RcuBox is like a Box except that it lets you obtain a &T that
> > > > outlives the box by a grace period. It does not allow mutable access to
> > >
> > > I think the `RcuBox` can be folded into the more generic RCU pointer api
> > > [1], e.g. Rcu<Box<RcuBoxInner<T>>> where RcuBoxInner<T>: HasRcuHead. The
> > > benefits are at least 1) we use relaxed atomic read for RCU readers
> > > which guarantees address dependency that RCU needs under LKMM (while in
> > > the RcuBox here, we just use plain reads), 2) we also support mutable
> > > access as well.
> >
> > 1) But mtree_load() does use rcu_dereference() to obtain the pointer?
> > 1) "relaxed atomic" does not sound like something that provides an
> > address dependency to me.
>
> If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> address dependency (Please see the DEPENDENCY part in
> tools/memory-model/Documentation/explanation.txt).
You argued that we should rename READ_ONCE() to atomic load on that
other patch series because "atomic load" naming is better than what LKMM
normally uses. Fine, but relaxed atomic load is a much worse name than
READ_ONCE() if what you want to convey is "has address dependency".
That's not what "relaxed" means!
I suppose you can argue that the word "relaxed" means different things
in LKMM than it does elsewhere, but I looked over the doc you mentioned,
and there the LKMM calls said operation READ_ONCE(). The word "relaxed"
does not appear even once. If we're going to change terminology / use
new terminology, let's at least pick terminology that's not
contradictory with the rest of the world.
> > 2) How do you intend to provide mutable access? By waiting a grace
> > period?
>
> Please see the {read_}copy_update() in the RCU patches that I linked.
> In short, you don't wait a grace for mutable access, since in RCU,
> readers don't block updaters, but instead updater will copy the object,
> atomically update the pointer and then get an `RcuOld`,
> which you can either synchronize_rcu() or {call,kfree}_rcu().
Hm, ok. I don't really need that. What I want rcu for is the internal
maple tree data structure, so mtree_load() doesn't need to block on the
maple tree internal spinlock. The contents of the box would be protected
by a separate lock (probably via LockedBy).
> > > As for the progress of that effort, the Rcu atomic pointer is almost
> > > ready [2], I will likely send it early next week. For the `HasRcuHead`
> > > part, as you may be aware, I'm working on a generic `HasField` approach
> > > to avoid duplication of `Has*` trait and macros [3], that requires some
> > > syn adjustments from Gary and Benno, but they should be available next
> > > cycle. I will probably send the patches for reviews before that. Once we
> > > have that `HasRcuHead` should be easily to add.
> > >
> > > Given the WIP code I have, I *think* we are not that far from providing
> > > what you need for binder.
> >
> > Hmm, so I looked over [2], and I think my RcuBox is an RcuOld<_> rather
> > than an Rcu<_> under this model. Though I can't afford to pay
>
> I don't think so, `RcuOld` represents an unpublished object while `Rcu`
> represents a published object, you can update an `Rcu` pointer to
> another object, which is normally how you update with RCU. But maybe
> it's easy to discuss this with updater side code in picture.
When the RcuBox<_> is an owned value in Rust code, it's unpublished.
It's only published while it's foreign-owned by the maple tree.
Alice
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 13:12 ` Alice Ryhl
@ 2026-01-17 14:00 ` Boqun Feng
2026-01-21 12:10 ` Alice Ryhl
0 siblings, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-17 14:00 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 01:12:08PM +0000, Alice Ryhl wrote:
[...]
> > > 1) "relaxed atomic" does not sound like something that provides an
> > > address dependency to me.
> >
> > If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> > as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> > address dependency (Please see the DEPENDENCY part in
> > tools/memory-model/Documentation/explanation.txt).
>
> You argued that we should rename READ_ONCE() to atomic load on that
> other patch series because "atomic load" naming is better than what LKMM
> normally uses. Fine, but relaxed atomic load is a much worse name than
To be clear, in that series, my argument was not about naming, it's
about READ_ONCE() being more powerful than atomic load (no, not because
of address dependency, they are the same on that, it's because of the
behaviors of them regarding a current access on the same memory
location), and we want user to specify the intention more clearly.
> READ_ONCE() if what you want to convey is "has address dependency".
> That's not what "relaxed" means!
>
Also note that my previous reply was explaining why we don't need to
call rcu_dereference() from Rust, because implementation-wise the
LKMM relaxed atomic load provides the address dependency. Depending on
what we want to do, we can limit this address dependency only to
rcu_dereference() and make it a special case, this means we disallow the
address dependency provided by the "relaxed" in normal cases. Or we can
add a Consume ordering (a type alias to Relaxed) that makes user to
explicitly use it when they rely on the address dependency. I think
either would resolve your concern about the name of "relaxed".
> I suppose you can argue that the word "relaxed" means different things
> in LKMM than it does elsewhere, but I looked over the doc you mentioned,
> and there the LKMM calls said operation READ_ONCE(). The word "relaxed"
> does not appear even once. If we're going to change terminology / use
> new terminology, let's at least pick terminology that's not
> contradictory with the rest of the world.
>
> > > 2) How do you intend to provide mutable access? By waiting a grace
> > > period?
> >
> > Please see the {read_}copy_update() in the RCU patches that I linked.
> > In short, you don't wait a grace for mutable access, since in RCU,
> > readers don't block updaters, but instead updater will copy the object,
> > atomically update the pointer and then get an `RcuOld`,
> > which you can either synchronize_rcu() or {call,kfree}_rcu().
>
> Hm, ok. I don't really need that. What I want rcu for is the internal
> maple tree data structure, so mtree_load() doesn't need to block on the
> maple tree internal spinlock. The contents of the box would be protected
> by a separate lock (probably via LockedBy).
>
You mean after `load_rcu()`, we could access mutably by a lock? You need
to hold that lock and the rcu_read_lock() while mutably accessing the
return of `load_rcu()`, right? That is basically using RCU as a proof
for existence.
Regards,
Boqun
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-17 14:00 ` Boqun Feng
@ 2026-01-21 12:10 ` Alice Ryhl
2026-01-21 13:14 ` Boqun Feng
0 siblings, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-21 12:10 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Sat, Jan 17, 2026 at 10:00:19PM +0800, Boqun Feng wrote:
> On Sat, Jan 17, 2026 at 01:12:08PM +0000, Alice Ryhl wrote:
> [...]
> > > > 1) "relaxed atomic" does not sound like something that provides an
> > > > address dependency to me.
> > >
> > > If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> > > as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> > > address dependency (Please see the DEPENDENCY part in
> > > tools/memory-model/Documentation/explanation.txt).
> >
> > You argued that we should rename READ_ONCE() to atomic load on that
> > other patch series because "atomic load" naming is better than what LKMM
> > normally uses. Fine, but relaxed atomic load is a much worse name than
>
> To be clear, in that series, my argument was not about naming, it's
> about READ_ONCE() being more powerful than atomic load (no, not because
> of address dependency, they are the same on that, it's because of the
> behaviors of them regarding a current access on the same memory
> location), and we want user to specify the intention more clearly.
Expressing intent more clearly is fine with me. I still think it's weird
for us to not have READ_ONCE() when it's a primitive operation of our
memory model, though.
And I also think we should consider using an implementation along the
lines of what I shared for our atomic_load() or READ_ONCE() or whatever
you wish to call it. The perf impact of helpers makes me sad.
> > READ_ONCE() if what you want to convey is "has address dependency".
> > That's not what "relaxed" means!
> >
>
> Also note that my previous reply was explaining why we don't need to
> call rcu_dereference() from Rust, because implementation-wise the
> LKMM relaxed atomic load provides the address dependency. Depending on
> what we want to do, we can limit this address dependency only to
> rcu_dereference() and make it a special case, this means we disallow the
> address dependency provided by the "relaxed" in normal cases. Or we can
> add a Consume ordering (a type alias to Relaxed) that makes user to
> explicitly use it when they rely on the address dependency. I think
> either would resolve your concern about the name of "relaxed".
Yes, I suppose that would resolve my concern about the name.
Well, I do have one partial concern there, which is that the wrong name
will show up in stack traces as long as helpers are used.
> > I suppose you can argue that the word "relaxed" means different things
> > in LKMM than it does elsewhere, but I looked over the doc you mentioned,
> > and there the LKMM calls said operation READ_ONCE(). The word "relaxed"
> > does not appear even once. If we're going to change terminology / use
> > new terminology, let's at least pick terminology that's not
> > contradictory with the rest of the world.
> >
> > > > 2) How do you intend to provide mutable access? By waiting a grace
> > > > period?
> > >
> > > Please see the {read_}copy_update() in the RCU patches that I linked.
> > > In short, you don't wait a grace for mutable access, since in RCU,
> > > readers don't block updaters, but instead updater will copy the object,
> > > atomically update the pointer and then get an `RcuOld`,
> > > which you can either synchronize_rcu() or {call,kfree}_rcu().
> >
> > Hm, ok. I don't really need that. What I want rcu for is the internal
> > maple tree data structure, so mtree_load() doesn't need to block on the
> > maple tree internal spinlock. The contents of the box would be protected
> > by a separate lock (probably via LockedBy).
> >
>
> You mean after `load_rcu()`, we could access mutably by a lock? You need
> to hold that lock and the rcu_read_lock() while mutably accessing the
> return of `load_rcu()`, right? That is basically using RCU as a proof
> for existence.
Yeah, that's right.
Alice
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-21 12:10 ` Alice Ryhl
@ 2026-01-21 13:14 ` Boqun Feng
2026-01-21 13:21 ` Alice Ryhl
0 siblings, 1 reply; 18+ messages in thread
From: Boqun Feng @ 2026-01-21 13:14 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Wed, Jan 21, 2026 at 12:10:54PM +0000, Alice Ryhl wrote:
> On Sat, Jan 17, 2026 at 10:00:19PM +0800, Boqun Feng wrote:
> > On Sat, Jan 17, 2026 at 01:12:08PM +0000, Alice Ryhl wrote:
> > [...]
> > > > > 1) "relaxed atomic" does not sound like something that provides an
> > > > > address dependency to me.
> > > >
> > > > If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> > > > as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> > > > address dependency (Please see the DEPENDENCY part in
> > > > tools/memory-model/Documentation/explanation.txt).
> > >
> > > You argued that we should rename READ_ONCE() to atomic load on that
> > > other patch series because "atomic load" naming is better than what LKMM
> > > normally uses. Fine, but relaxed atomic load is a much worse name than
> >
> > To be clear, in that series, my argument was not about naming, it's
> > about READ_ONCE() being more powerful than atomic load (no, not because
> > of address dependency, they are the same on that, it's because of the
> > behaviors of them regarding a current access on the same memory
> > location), and we want user to specify the intention more clearly.
>
> Expressing intent more clearly is fine with me. I still think it's weird
> for us to not have READ_ONCE() when it's a primitive operation of our
> memory model, though.
>
But in our memory model, it's exact the same as atomic_read() (see
tools/memory-model/linux-kernel.def and search for "atomic_read"), so
why do we want to have both? ;-)
> And I also think we should consider using an implementation along the
> lines of what I shared for our atomic_load() or READ_ONCE() or whatever
> you wish to call it. The perf impact of helpers makes me sad.
>
I'm not totally against that, it'll actually help Atomic as well, I also
hope that we can use `asm!()` to implement the cases where
`{read,write}_volatile()` cannot cover. However currently I would rely
on helper inlining to resolve this to avoid duplicate implementations.
> > > READ_ONCE() if what you want to convey is "has address dependency".
> > > That's not what "relaxed" means!
> > >
> >
> > Also note that my previous reply was explaining why we don't need to
> > call rcu_dereference() from Rust, because implementation-wise the
> > LKMM relaxed atomic load provides the address dependency. Depending on
> > what we want to do, we can limit this address dependency only to
> > rcu_dereference() and make it a special case, this means we disallow the
> > address dependency provided by the "relaxed" in normal cases. Or we can
> > add a Consume ordering (a type alias to Relaxed) that makes user to
> > explicitly use it when they rely on the address dependency. I think
> > either would resolve your concern about the name of "relaxed".
>
> Yes, I suppose that would resolve my concern about the name.
>
> Well, I do have one partial concern there, which is that the wrong name
> will show up in stack traces as long as helpers are used.
>
I think it won't be a problem since in LKMM, atomic_read() and
READ_ONCE() are identical.
Regards,
Boqun
> > > I suppose you can argue that the word "relaxed" means different things
> > > in LKMM than it does elsewhere, but I looked over the doc you mentioned,
> > > and there the LKMM calls said operation READ_ONCE(). The word "relaxed"
> > > does not appear even once. If we're going to change terminology / use
> > > new terminology, let's at least pick terminology that's not
> > > contradictory with the rest of the world.
> > >
[...]
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-21 13:14 ` Boqun Feng
@ 2026-01-21 13:21 ` Alice Ryhl
2026-01-21 18:38 ` Paul E. McKenney
0 siblings, 1 reply; 18+ messages in thread
From: Alice Ryhl @ 2026-01-21 13:21 UTC (permalink / raw)
To: Boqun Feng
Cc: Paul E. McKenney, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Wed, Jan 21, 2026 at 09:14:05PM +0800, Boqun Feng wrote:
> On Wed, Jan 21, 2026 at 12:10:54PM +0000, Alice Ryhl wrote:
> > On Sat, Jan 17, 2026 at 10:00:19PM +0800, Boqun Feng wrote:
> > > On Sat, Jan 17, 2026 at 01:12:08PM +0000, Alice Ryhl wrote:
> > > [...]
> > > > > > 1) "relaxed atomic" does not sound like something that provides an
> > > > > > address dependency to me.
> > > > >
> > > > > If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> > > > > as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> > > > > address dependency (Please see the DEPENDENCY part in
> > > > > tools/memory-model/Documentation/explanation.txt).
> > > >
> > > > You argued that we should rename READ_ONCE() to atomic load on that
> > > > other patch series because "atomic load" naming is better than what LKMM
> > > > normally uses. Fine, but relaxed atomic load is a much worse name than
> > >
> > > To be clear, in that series, my argument was not about naming, it's
> > > about READ_ONCE() being more powerful than atomic load (no, not because
> > > of address dependency, they are the same on that, it's because of the
> > > behaviors of them regarding a current access on the same memory
> > > location), and we want user to specify the intention more clearly.
> >
> > Expressing intent more clearly is fine with me. I still think it's weird
> > for us to not have READ_ONCE() when it's a primitive operation of our
> > memory model, though.
> >
>
> But in our memory model, it's exact the same as atomic_read() (see
> tools/memory-model/linux-kernel.def and search for "atomic_read"), so
> why do we want to have both? ;-)
I've been saying Rust should have both because I've been repeatedly told
that they are different. If READ_ONCE() and atomic_load() are the same,
then I retract my concern.
> > And I also think we should consider using an implementation along the
> > lines of what I shared for our atomic_load() or READ_ONCE() or whatever
> > you wish to call it. The perf impact of helpers makes me sad.
> >
>
> I'm not totally against that, it'll actually help Atomic as well, I also
> hope that we can use `asm!()` to implement the cases where
> `{read,write}_volatile()` cannot cover. However currently I would rely
> on helper inlining to resolve this to avoid duplicate implementations.
I'm in favor of using helpers to begin with. I think it's probably worth
to do atomic_load() before we do the other ops, since it's so much
simpler to implement that particular operation than the ones using asm.
Alice
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH RFC 0/2] rcu box container for Rust + maple tree load_rcu
2026-01-21 13:21 ` Alice Ryhl
@ 2026-01-21 18:38 ` Paul E. McKenney
0 siblings, 0 replies; 18+ messages in thread
From: Paul E. McKenney @ 2026-01-21 18:38 UTC (permalink / raw)
To: Alice Ryhl
Cc: Boqun Feng, Liam R. Howlett, Gary Guo, Miguel Ojeda,
Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Frederic Weisbecker,
Neeraj Upadhyay, Joel Fernandes, Josh Triplett, Uladzislau Rezki,
Steven Rostedt, Mathieu Desnoyers, Lai Jiangshan, Zqiang,
Andrew Ballance, linux-kernel, rust-for-linux, rcu, maple-tree,
linux-mm
On Wed, Jan 21, 2026 at 01:21:46PM +0000, Alice Ryhl wrote:
> On Wed, Jan 21, 2026 at 09:14:05PM +0800, Boqun Feng wrote:
> > On Wed, Jan 21, 2026 at 12:10:54PM +0000, Alice Ryhl wrote:
> > > On Sat, Jan 17, 2026 at 10:00:19PM +0800, Boqun Feng wrote:
> > > > On Sat, Jan 17, 2026 at 01:12:08PM +0000, Alice Ryhl wrote:
> > > > [...]
> > > > > > > 1) "relaxed atomic" does not sound like something that provides an
> > > > > > > address dependency to me.
> > > > > >
> > > > > > If you look at rcu_dereference(), it's a READ_ONCE(), which is the same
> > > > > > as a relaxed atomic load, and yes in LKMM, relaxed atomic load provides
> > > > > > address dependency (Please see the DEPENDENCY part in
> > > > > > tools/memory-model/Documentation/explanation.txt).
> > > > >
> > > > > You argued that we should rename READ_ONCE() to atomic load on that
> > > > > other patch series because "atomic load" naming is better than what LKMM
> > > > > normally uses. Fine, but relaxed atomic load is a much worse name than
> > > >
> > > > To be clear, in that series, my argument was not about naming, it's
> > > > about READ_ONCE() being more powerful than atomic load (no, not because
> > > > of address dependency, they are the same on that, it's because of the
> > > > behaviors of them regarding a current access on the same memory
> > > > location), and we want user to specify the intention more clearly.
> > >
> > > Expressing intent more clearly is fine with me. I still think it's weird
> > > for us to not have READ_ONCE() when it's a primitive operation of our
> > > memory model, though.
> > >
> >
> > But in our memory model, it's exact the same as atomic_read() (see
> > tools/memory-model/linux-kernel.def and search for "atomic_read"), so
> > why do we want to have both? ;-)
>
> I've been saying Rust should have both because I've been repeatedly told
> that they are different. If READ_ONCE() and atomic_load() are the same,
> then I retract my concern.
I confess some bemusement on the allergy to READ_ONCE() and WRITE_ONCE().
However, we have a similar thing within the Linux kernel. READ_ONCE()
is the same as atomic_read() from am memory-ordering perspective,
and WRITE_ONCE() is the same as atomic_set() from a memory-ordering
perspective. The difference is typing. READ_ONCE() and WRITE_ONCE()
will eat anything, but atomic_read() and atomic_set() insist on pointers
to atomic_t. There is also atomic_long_t and atomic64_t, just in case
you want more API members. ;-)
Thanx, Paul
> > > And I also think we should consider using an implementation along the
> > > lines of what I shared for our atomic_load() or READ_ONCE() or whatever
> > > you wish to call it. The perf impact of helpers makes me sad.
> > >
> >
> > I'm not totally against that, it'll actually help Atomic as well, I also
> > hope that we can use `asm!()` to implement the cases where
> > `{read,write}_volatile()` cannot cover. However currently I would rely
> > on helper inlining to resolve this to avoid duplicate implementations.
>
> I'm in favor of using helpers to begin with. I think it's probably worth
> to do atomic_load() before we do the other ops, since it's so much
> simpler to implement that particular operation than the ones using asm.
>
> Alice
^ permalink raw reply [flat|nested] 18+ messages in thread