rust: helpers: add SRCU helpers
Subsystems (4)
Onur Özkan
maintainerv8 cover rust: helpers: add SRCU helpers
The immediate motivation is the Tyr reset infrastructure [1] which needs to serialize reset sensitive hardware access against reset and teardown paths. That reset series started to require many independent dependencies so this SRCU support is split out as a standalone Rust API to keep the reset series focused on the reset logic and easier to review, rebase and land.
Changes since v7:
- Moved synchronize_srcu() call inside "if srcu_readers_active()" condition in "impl PinnedDrop for Srcu".
- Improved comments on the synchronize_srcu() call in "impl PinnedDrop for Srcu".
v7: https://lore.kernel.org/all/[email protected]
Changes since v6:
- Removed "CONFIG_DEBUG_LOCK_ALLOC" condition from "rust/helpers/srcu.c" and created a simple wrapper inside "include/linux/srcu.h" for it.
v6: https://lore.kernel.org/all/[email protected]
Changes since v5:
- Created separate srcu_readers_active() variants for "srcutiny.h" and "srcutree.h".
v5: https://lore.kernel.org/all/[email protected]
Changes since v4:
- Exposed srcu_readers_active from C side and wired it to the Rust helpers.
- Used srcu_readers_active() in SRCU drop and logged with pr_warn if there are leaked guards during the drop.
v4: https://lore.kernel.org/all/[email protected]
Changes since v3 (which are for Sashiko notes [2]):
- Added rust helpers for srcu_barrier() and synchronize_srcu_expedited() so the abstraction builds with CONFIG_TINY_SRCU, where these are static inline functions.
- Added missing INVARIANT comment in Srcu::new() about why the type invariants hold after successful initialization.
v3: https://lore.kernel.org/all/[email protected]
Changes since v2:
- Removed closure-based API.
- Added #[doc(hidden)] on new_srcu macro.
- Added #[must_use..] on srcu::Guard.
- Improved the clean-up path (PinnedDrop implementation) which eventually made read_lock safe with leaked guards.
v2: https://lore.kernel.org/all/[email protected]
Changes since v1:
- Made the owned SRCU read-side guard API unsafe and added a safe closure based helper for callers that do not need to keep the guard. This is to avoid UB on the C side cleanup_srcu_struct where the SRCU struct is freed while there are still active guards, which can happen if the caller leaks the guard e.g., with mem::forget().
- Improved doc comments.
v1: https://lore.kernel.org/all/[email protected]
[1]: https://lore.kernel.org/all/[email protected]
[2]: https://sashiko.dev/#/patchset/[email protected]?part=2
Onur Özkan (4):
rust: helpers: add SRCU helpers
srcu: expose srcu_readers_active()
rust: sync: add SRCU abstraction
MAINTAINERS: add Rust SRCU files to SRCU entry
MAINTAINERS | 3 + include/linux/srcu.h | 5 ++ include/linux/srcutiny.h | 13 +++ include/linux/srcutree.h | 24 ++++++ kernel/rcu/srcutiny.c | 2 +- kernel/rcu/srcutree.c | 25 ------ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 35 ++++++++ rust/kernel/sync.rs | 2 + rust/kernel/sync/srcu.rs | 173 +++++++++++++++++++++++++++++++++++++++ 10 files changed, 257 insertions(+), 26 deletions(-) create mode 100644 rust/helpers/srcu.c create mode 100644 rust/kernel/sync/srcu.rs
Signature · 1 line
2.51.2
Onur Özkan
maintainerPATCH v8 1/4 rust: helpers: add SRCU helpers
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.c
include/linux/srcu.h +5 -0
@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}#ifndef CONFIG_TINY_SRCU int init_srcu_struct_fast (struct srcu_struct *ssp);int init_srcu_struct_fast_updown (struct srcu_struct *ssp);
rust/helpers/helpers.c +1 -0
@@ -88,6 +88,7 @@#include "signal.c" #include "slab.c" #include "spinlock.c" +#include "srcu.c" #include "sync.c" #include "task.c" #include "time.c"
rust/helpers/srcu.c new file +30 -0
@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/srcu.h> + +__rust_helper int rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp, +const char *name, +struct lock_class_key *key) +{ +return __init_srcu_struct (ssp, name, key); +} + +__rust_helper int rust_helper_srcu_read_lock(struct srcu_struct *ssp) +{ +return srcu_read_lock (ssp); +} + +__rust_helper void rust_helper_srcu_read_unlock(struct srcu_struct *ssp, int idx) +{ +srcu_read_unlock (ssp, idx); +} + +__rust_helper void rust_helper_srcu_barrier(struct srcu_struct *ssp) +{ +srcu_barrier (ssp); +} + +__rust_helper void rust_helper_synchronize_srcu_expedited(struct srcu_struct *ssp) +{ +synchronize_srcu_expedited (ssp); +}
Signature · 1 line
2.51.2
Gary Guo
maintainerQuoted 17 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 8 lines
include/linux/srcu.h +5
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}
This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
If we follow the way mutex is handles this, the init_srcu_struct would always create lock class key and forward to __init_srcu_struct, and __init_srcu_struct is an inline function that either calls init_srcu_struct_lockdep with all args, or discard name/key and forward to init_srcu_struct_mutex.
This is beneficial because the usage flows one way. You don't have in one config init_srcu_struct call __init_srcu_struct and have the opposite in another config, which I think can be quite confusing.
Best,
Gary
Quoted 51 lines
include/linux/srcu.h +0
-0#ifndef CONFIG_TINY_SRCU int init_srcu_struct_fast (struct srcu_struct *ssp);int init_srcu_struct_fast_updown (struct srcu_struct *ssp);rust/helpers/helpers.c +1
-0@@ -88,6 +88,7 @@#include "signal.c" #include "slab.c" #include "spinlock.c" +#include "srcu.c" #include "sync.c" #include "task.c" #include "time.c" rust/helpers/srcu.c new file +30
-0@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/srcu.h> + +__rust_helper int rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp, +const char *name, +struct lock_class_key *key) +{ +return __init_srcu_struct (ssp, name, key); +} + +__rust_helper int rust_helper_srcu_read_lock(struct srcu_struct *ssp) +{ +return srcu_read_lock (ssp); +} + +__rust_helper void rust_helper_srcu_read_unlock(struct srcu_struct *ssp, int idx) +{ +srcu_read_unlock (ssp, idx); +} + +__rust_helper void rust_helper_srcu_barrier(struct srcu_struct *ssp) +{ +srcu_barrier (ssp); +} + +__rust_helper void rust_helper_synchronize_srcu_expedited(struct srcu_struct *ssp) +{ +synchronize_srcu_expedited (ssp); +}
Onur Özkan
maintainerQuoted 20 lines · On Fri, 29 May 2026 12:58:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 19 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
Quoted 10 lines
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 6 lines
include/linux/srcu.h +5
-0int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
Initially it was the same strategy, this one was suggested by Paul [1] and it didn't sound like a bad idea to me. Also, in previous revisions, Boqun once said:
"Having a "#ifdef" in a function body is generally considered as bad code (I know we have some of these in rust helpers, but helpers are a bit special and maybe we should clean them up). So could you move this function into include/linux/srcutiny.h and include/linux/srcutree.h?"
So putting them together, I decided to follow Paul's suggestion.
[1]: https://lore.kernel.org/all/05906890-cf06-414c-a625-02f9d7150d57@paulmck-laptop
Quoted 67 lines
If we follow the way mutex is handles this, the
init_srcu_structwould always create lock class key and forward to__init_srcu_struct, and__init_srcu_structis an inline function that either callsinit_srcu_struct_lockdepwith all args, or discard name/key and forward toinit_srcu_struct_mutex.This is beneficial because the usage flows one way. You don't have in one config
init_srcu_structcall__init_srcu_structand have the opposite in another config, which I think can be quite confusing.Best,
GaryQuoted 51 lines
include/linux/srcu.h +0
-0#ifndef CONFIG_TINY_SRCU int init_srcu_struct_fast (struct srcu_struct *ssp);int init_srcu_struct_fast_updown (struct srcu_struct *ssp);rust/helpers/helpers.c +1
-0@@ -88,6 +88,7 @@#include "signal.c" #include "slab.c" #include "spinlock.c" +#include "srcu.c" #include "sync.c" #include "task.c" #include "time.c" rust/helpers/srcu.c new file +30
-0@@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/srcu.h> + +__rust_helper int rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp, +const char *name, +struct lock_class_key *key) +{ +return __init_srcu_struct (ssp, name, key); +} + +__rust_helper int rust_helper_srcu_read_lock(struct srcu_struct *ssp) +{ +return srcu_read_lock (ssp); +} + +__rust_helper void rust_helper_srcu_read_unlock(struct srcu_struct *ssp, int idx) +{ +srcu_read_unlock (ssp, idx); +} + +__rust_helper void rust_helper_srcu_barrier(struct srcu_struct *ssp) +{ +srcu_barrier (ssp); +} + +__rust_helper void rust_helper_synchronize_srcu_expedited(struct srcu_struct *ssp) +{ +synchronize_srcu_expedited (ssp); +}
Gary Guo
maintainerQuoted 34 lines · Onur Özkan
Quoted 20 lines · On Fri, 29 May 2026 12:58:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 19 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ Quoted 10 lines
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 6 lines
include/linux/srcu.h +5
-0int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
Quoted 3 lines
Initially it was the same strategy, this one was suggested by Paul [1] and it didn't sound like a bad idea to me. Also, in previous revisions, Boqun once said:
I'm talking about changing how this is handled in SRCU side, not helper side.
Quoted 5 lines
"Having a "#ifdef" in a function body is generally considered as bad code (I know we have some of these in rust helpers, but helpers are a bit special and maybe we should clean them up). So could you move this function into
include/linux/srcutiny.handinclude/linux/srcutree.h?"
mutex.h doesn't use ifdef inside function body, it just define two static inline functions with the same signature in different ifdef branches.
Best,
Gary
Quoted 15 lines
So putting them together, I decided to follow Paul's suggestion.
[1]: https://lore.kernel.org/all/05906890-cf06-414c-a625-02f9d7150d57@paulmck-laptop
Quoted 10 lines
If we follow the way mutex is handles this, the
init_srcu_structwould always create lock class key and forward to__init_srcu_struct, and__init_srcu_structis an inline function that either callsinit_srcu_struct_lockdepwith all args, or discard name/key and forward toinit_srcu_struct_mutex.This is beneficial because the usage flows one way. You don't have in one config
init_srcu_structcall__init_srcu_structand have the opposite in another config, which I think can be quite confusing.
Onur Özkan
maintainerQuoted 42 lines · On Fri, 29 May 2026 13:16:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 34 lines · Onur Özkan
Quoted 20 lines · On Fri, 29 May 2026 12:58:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 19 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ Quoted 10 lines
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 6 lines
include/linux/srcu.h +5
-0int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
Quoted 3 lines
Initially it was the same strategy, this one was suggested by Paul [1] and it didn't sound like a bad idea to me. Also, in previous revisions, Boqun once said:
I'm talking about changing how this is handled in SRCU side, not helper side.
Quoted 1 line
Quoted 8 lines
Quoted 4 lines
"Having a "#ifdef" in a function body is generally considered as bad code (I know we have some of these in rust helpers, but helpers are a bit special and maybe we should clean them up). So could you move this function into
include/linux/srcutiny.handinclude/linux/srcutree.h?"
mutex.hdoesn't use ifdef inside function body, it just define two static inline functions with the same signature in different ifdef branches.
I might have confused them, let me check them again.
Thanks,
Onur
Quoted 18 lines
Best,
GaryQuoted 15 lines
So putting them together, I decided to follow Paul's suggestion.
[1]: https://lore.kernel.org/all/05906890-cf06-414c-a625-02f9d7150d57@paulmck-laptop
Quoted 10 lines
If we follow the way mutex is handles this, the
init_srcu_structwould always create lock class key and forward to__init_srcu_struct, and__init_srcu_structis an inline function that either callsinit_srcu_struct_lockdepwith all args, or discard name/key and forward toinit_srcu_struct_mutex.This is beneficial because the usage flows one way. You don't have in one config
init_srcu_structcall__init_srcu_structand have the opposite in another config, which I think can be quite confusing.
Paul E. McKenney
maintainerQuoted 42 lines · Gary Guo
Quoted 34 lines · Onur Özkan
Quoted 20 lines · On Fri, 29 May 2026 12:58:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 19 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ Quoted 10 lines
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 6 lines
include/linux/srcu.h +5
-0int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
Quoted 3 lines
Initially it was the same strategy, this one was suggested by Paul [1] and it didn't sound like a bad idea to me. Also, in previous revisions, Boqun once said:
I'm talking about changing how this is handled in SRCU side, not helper side.
Quoted 1 line
Quoted 7 lines
Quoted 4 lines
"Having a "#ifdef" in a function body is generally considered as bad code (I know we have some of these in rust helpers, but helpers are a bit special and maybe we should clean them up). So could you move this function into
include/linux/srcutiny.handinclude/linux/srcutree.h?"
mutex.hdoesn't use ifdef inside function body, it just define two static inline functions with the same signature in different ifdef branches.
True, but SRCU has the added complication of having different !SMP (Tiny) and SMP (Tree) implementations. On the other hand, it is quite possible that I missed a trick when setting up this part of SRCU. Please feel free to send a patch that simplifies it.
Thanx, Paul
Quoted 19 lines
Best,
GaryQuoted 15 lines
So putting them together, I decided to follow Paul's suggestion.
[1]: https://lore.kernel.org/all/05906890-cf06-414c-a625-02f9d7150d57@paulmck-laptop
Quoted 10 lines
If we follow the way mutex is handles this, the
init_srcu_structwould always create lock class key and forward to__init_srcu_struct, and__init_srcu_structis an inline function that either callsinit_srcu_struct_lockdepwith all args, or discard name/key and forward toinit_srcu_struct_mutex.This is beneficial because the usage flows one way. You don't have in one config
init_srcu_structcall__init_srcu_structand have the opposite in another config, which I think can be quite confusing.
Onur Özkan
maintainerQuoted 48 lines · On Sat, 30 May 2026 12:01:21 -0700 "Paul E. McKenney" <[email protected]>…
Quoted 47 lines · Gary Guo
Quoted 34 lines · Onur Özkan
Quoted 20 lines · On Fri, 29 May 2026 12:58:17 +0100 Gary Guo <[email protected]> wrote:
Quoted 19 lines · Onur Özkan
Add helper wrappers for SRCU functions that are exposed to Rust through generated bindings.
Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>--- include/linux/srcu.h | 5 +++++ rust/helpers/helpers.c | 1 + rust/helpers/srcu.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 rust/helpers/srcu.cinclude/linux/srcu.h +0
-0@@ -57,6 +57,11 @@ int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name,#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */ Quoted 10 lines
include/linux/srcu.h int __init_srcu_struct_fast_updown(struct srcu_struct *ssp, const char *name, · line 64
Quoted 6 lines
include/linux/srcu.h +5
-0int init_srcu_struct (struct srcu_struct *ssp); +static inline int __init_srcu_struct (struct srcu_struct *ssp,const char *name, +struct lock_class_key *key) +{ +return init_srcu_struct (ssp); +}This looks like a different strategy than, say, how mutex handles lockdep. IMO the way that mutex handles this is more clear.
Quoted 3 lines
Initially it was the same strategy, this one was suggested by Paul [1] and it didn't sound like a bad idea to me. Also, in previous revisions, Boqun once said:
I'm talking about changing how this is handled in SRCU side, not helper side.
Quoted 5 lines
"Having a "#ifdef" in a function body is generally considered as bad code (I know we have some of these in rust helpers, but helpers are a bit special and maybe we should clean them up). So could you move this function into
include/linux/srcutiny.handinclude/linux/srcutree.h?"
Quoted 7 lines
Quoted 2 lines
mutex.hdoesn't use ifdef inside function body, it just define two static inline functions with the same signature in different ifdef branches.True, but SRCU has the added complication of having different !SMP (Tiny) and SMP (Tree) implementations. On the other hand, it is quite possible that I missed a trick when setting up this part of SRCU. Please feel free to send a patch that simplifies it.
It's on the list [1].
Thanks,
Onur
[1]: https://lore.kernel.org/all/[email protected]
Quoted 22 lines
Thanx, Paul
Quoted 19 lines
Best,
GaryQuoted 15 lines
So putting them together, I decided to follow Paul's suggestion.
[1]: https://lore.kernel.org/all/05906890-cf06-414c-a625-02f9d7150d57@paulmck-laptop
Quoted 10 lines
If we follow the way mutex is handles this, the
init_srcu_structwould always create lock class key and forward to__init_srcu_struct, and__init_srcu_structis an inline function that either callsinit_srcu_struct_lockdepwith all args, or discard name/key and forward toinit_srcu_struct_mutex.This is beneficial because the usage flows one way. You don't have in one config
init_srcu_structcall__init_srcu_structand have the opposite in another config, which I think can be quite confusing.
Onur Özkan
maintainerPATCH v8 2/4 srcu: expose srcu_readers_active()
In reply to Onur ÖzkanThis is needed by rust/helpers/srcu.c which now adds rust_helper_srcu_readers_active() as a wrapper around the SRCU helper for Rust callers.
To achive this:
1- Move the srcu_readers_active() implementation from
"kernel/rcu/srcutree.c" to "include/linux/srcutree.h".
2- Implement a matching srcu_readers_active() in
"include/linux/srcutiny.h" and use it on the existing open-coded WARN_ON() check in cleanup_srcu_struct().
--- include/linux/srcutiny.h | 13 +++++++++++++ include/linux/srcutree.h | 24 ++++++++++++++++++++++++ kernel/rcu/srcutiny.c | 2 +- kernel/rcu/srcutree.c | 25 ------------------------- rust/helpers/srcu.c | 5 +++++ 5 files changed, 43 insertions(+), 26 deletions(-)
include/linux/srcutiny.h +13 -0
@@ -154,4 +154,17 @@ static inline void srcu_torture_stats_print(struct srcu_struct *ssp, data_race(READ_ONCE(ssp->srcu_idx_max))); } +/** +* srcu_readers_active - returns true if there are readers. and false otherwise. +* @ssp: which srcu_struct to count active readers (holding srcu_read_lock). +* +* Note that this is not an atomic primitive, and can therefore suffer +* severe errors when invoked on an active srcu_struct. That said, it +* can be useful as an error check at cleanup time. +*/ +static inline bool srcu_readers_active (struct srcu_struct *ssp) +{ +return READ_ONCE (ssp->srcu_lock_nesting[0 ]) ||READ_ONCE (ssp->srcu_lock_nesting[1 ]); +} +#endif
include/linux/srcutree.h +24 -0
@@ -374,4 +374,28 @@ static inline void srcu_check_read_flavor(struct srcu_struct *ssp, int read_flav __srcu_check_read_flavor(ssp, read_flavor); } +/** +* srcu_readers_active - returns true if there are readers. and false otherwise. +* @ssp: which srcu_struct to count active readers (holding srcu_read_lock). +* +* Note that this is not an atomic primitive, and can therefore suffer +* severe errors when invoked on an active srcu_struct. That said, it +* can be useful as an error check at cleanup time. +*/ +static inline bool srcu_readers_active (struct srcu_struct *ssp) +{ +int cpu; +unsigned long sum =0 ; + +for_each_possible_cpu (cpu) { +struct srcu_data *sdp =per_cpu_ptr (ssp->sda, cpu); + + sum +=atomic_long_read (&sdp->srcu_ctrs[0 ].srcu_locks); + sum +=atomic_long_read (&sdp->srcu_ctrs[1 ].srcu_locks); + sum -=atomic_long_read (&sdp->srcu_ctrs[0 ].srcu_unlocks); + sum -=atomic_long_read (&sdp->srcu_ctrs[1 ].srcu_unlocks); + } +return sum; +} +#endif
kernel/rcu/srcutiny.c +1 -1
@@ -85,7 +85,7 @@ EXPORT_SYMBOL_GPL(init_srcu_struct);*/ void cleanup_srcu_struct (struct srcu_struct *ssp) { -WARN_ON (ssp->srcu_lock_nesting[0 ] || ssp->srcu_lock_nesting[1 ]); +WARN_ON (srcu_readers_active (ssp));irq_work_sync (&ssp->srcu_irq_work);flush_work (&ssp->srcu_work);WARN_ON (ssp->srcu_gp_running);
kernel/rcu/srcutree.c +0 -25
@@ -598,31 +598,6 @@ static bool srcu_readers_active_idx_check(struct srcu_struct *ssp, int idx)return srcu_readers_lock_idx (ssp, idx, did_gp, unlocks); } -/** -* srcu_readers_active - returns true if there are readers. and false -* otherwise -* @ssp: which srcu_struct to count active readers (holding srcu_read_lock). -* -* Note that this is not an atomic primitive, and can therefore suffer -* severe errors when invoked on an active srcu_struct. That said, it -* can be useful as an error check at cleanup time. -*/ -static bool srcu_readers_active (struct srcu_struct *ssp) -{ -int cpu; -unsigned long sum =0 ; - -for_each_possible_cpu (cpu) { -struct srcu_data *sdp =per_cpu_ptr (ssp->sda, cpu); - - sum +=atomic_long_read (&sdp->srcu_ctrs[0 ].srcu_locks); - sum +=atomic_long_read (&sdp->srcu_ctrs[1 ].srcu_locks); - sum -=atomic_long_read (&sdp->srcu_ctrs[0 ].srcu_unlocks); - sum -=atomic_long_read (&sdp->srcu_ctrs[1 ].srcu_unlocks); - } -return sum; -} -/* * We use an adaptive strategy for synchronize_srcu() and especially for * synchronize_srcu_expedited(). We spin for a fixed time period
rust/helpers/srcu.c +5 -0
@@ -9,6 +9,11 @@ __rust_helper int rust_helper_init_srcu_struct_with_key(struct srcu_struct *ssp,return __init_srcu_struct (ssp, name, key); } +__rust_helper bool rust_helper_srcu_readers_active(struct srcu_struct *ssp) +{ +return srcu_readers_active (ssp); +} + __rust_helper int rust_helper_srcu_read_lock(struct srcu_struct *ssp) {return srcu_read_lock (ssp);
Signature · 1 line
2.51.2
Re: [PATCH v8 2/4] srcu: expose srcu_readers_active()
Quoted 9 lines · Onur Özkan
This is needed by
rust/helpers/srcu.cwhich now addsrust_helper_srcu_readers_active()as a wrapper around the SRCU helper for Rust callers.To achive this:
1- Move the
srcu_readers_active()implementation from
"kernel/rcu/srcutree.c" to "include/linux/srcutree.h".
Quoted 6 lines
2- Implement a matching
srcu_readers_active()in
"include/linux/srcutiny.h" and use it on the existing open-codedWARN_ON()check incleanup_srcu_struct().Reviewed-by Paul E. McKenney <[email protected]>Signed-off-by Onur Özkan <[email protected]>
Quoted 7 lines
--- include/linux/srcutiny.h | 13 +++++++++++++ include/linux/srcutree.h | 24 ++++++++++++++++++++++++ kernel/rcu/srcutiny.c | 2 +- kernel/rcu/srcutree.c | 25 ------------------------- rust/helpers/srcu.c | 5 +++++ 5 files changed, 43 insertions(+), 26 deletions(-)
Onur Özkan
maintainerPATCH v8 3/4 rust: sync: add SRCU abstraction
In reply to Onur ÖzkanAdd a Rust abstraction for sleepable RCU (SRCU), backed by C srcu_struct. Provide FFI helpers and a safe wrapper with a guard-based API for read-side critical sections.
Cleanup is handled via PinnedDrop. It first checks for active read-side sections and emits a warning if any guards were leaked. In that case, it waits in synchronize_srcu() rather than risking a UAF by freeing the srcu_struct that is still reachable from the C side. It then uses srcu_barrier() to drain pending callbacks before finally calling cleanup_srcu_struct().
--- rust/kernel/sync.rs | 2 + rust/kernel/sync/srcu.rs | 173 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 175 insertions(+) create mode 100644 rust/kernel/sync/srcu.rs
rust/kernel/sync.rs +2 -0
@@ -21,6 +21,7 @@pub mod rcu;mod refcount;mod set_once; +pub mod srcu;pub use arc::{Arc ,ArcBorrow ,UniqueArc };pub use completion::Completion ;
@@ -31,6 +32,7 @@pub use locked_by::LockedBy ;pub use refcount::Refcount ;pub use set_once::SetOnce ; +pub use srcu::Srcu ;/// Represents a lockdep class. ///
rust/kernel/sync/srcu.rs new file +173 -0
173 lines not on this page · raw message
Signature · 1 line
2.51.2
Onur Özkan
maintainerPATCH v8 4/4 MAINTAINERS: add Rust SRCU files to SRCU entry
In reply to Onur ÖzkanInclude Rust side implementation files to the SRCU maintainer entry.
--- MAINTAINERS | 3 +++ 1 file changed, 3 insertions(+)
MAINTAINERS +3 -0
@@ -24624,6 +24624,7 @@ SLEEPABLE READ-COPY UPDATE (SRCU) M: Lai Jiangshan <[email protected]> M: "Paul E. McKenney" <[email protected]> M: Josh Triplett <[email protected]> +M: Onur Özkan <[email protected]> (RUST) R: Steven Rostedt <[email protected]> R: Mathieu Desnoyers <[email protected]> L: [email protected]
@@ -24632,6 +24633,8 @@ W: http://www.rdrop.com/users/paulmck/RCU/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rcu/linux.git rcu/dev F: include/linux/srcu*.h F: kernel/rcu/srcu*.c +F: rust/helpers/srcu.c +F: rust/kernel/sync/srcu.rs SMACK SECURITY MODULE M: Casey Schaufler <[email protected]>
Signature · 1 line
2.51.2