From: jkhall81 <jason.kei.hall@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Alice Ryhl" <aliceryhl@google.com>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Carlos Llamas" <cmllamas@google.com>,
linux-kernel@vger.kernel.org, jkhall81 <jason.kei.hall@gmail.com>
Subject: [PATCH rust-next] rust: binder: refactor context management to use KVVec
Date: Sat, 17 Jan 2026 09:22:42 -0700 [thread overview]
Message-ID: <20260117162242.950194-1-jason.kei.hall@gmail.com> (raw)
Replace the intrusive linked list management in context.rs with KVVec.
This modernization simplifies the ownership model by using standard
Arc-based tracking and moves away from manual unsafe list removals.
The refactor improves memory safety by leveraging Rust's contiguous
collection types while maintaining proper error propagation for
allocation failures during process registration.
Suggested-by: Alice Ryhl <aliceryhl@google.com>
Link: https://github.com/rust-for-linux/linux/issues/1215
Signed-off-by: jkhall81 <jason.kei.hall@gmail.com>
---
drivers/android/binder/context.rs | 73 ++++++++++++++-----------------
drivers/android/binder/process.rs | 4 +-
2 files changed, 36 insertions(+), 41 deletions(-)
diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/context.rs
index 3d135ec03ca7..83fa8a16662b 100644
--- a/drivers/android/binder/context.rs
+++ b/drivers/android/binder/context.rs
@@ -3,8 +3,8 @@
// Copyright (C) 2025 Google LLC.
use kernel::{
- error::Error,
- list::{List, ListArc, ListLinks},
+ alloc::kvec::{KVVec, KVec},
+ error::code::*,
prelude::*,
security,
str::{CStr, CString},
@@ -17,22 +17,19 @@
kernel::sync::global_lock! {
// SAFETY: We call `init` in the module initializer, so it's initialized before first use.
pub(crate) unsafe(uninit) static CONTEXTS: Mutex<ContextList> = ContextList {
- list: List::new(),
+ contexts: KVVec::new(),
};
}
pub(crate) struct ContextList {
- list: List<Context>,
+ contexts: KVVec<Arc<Context>>,
}
pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> {
let lock = CONTEXTS.lock();
-
- let count = lock.list.iter().count();
-
- let mut ctxs = KVec::with_capacity(count, GFP_KERNEL)?;
- for ctx in &lock.list {
- ctxs.push(Arc::from(ctx), GFP_KERNEL)?;
+ let mut ctxs = KVec::with_capacity(lock.contexts.len(), GFP_KERNEL)?;
+ for ctx in lock.contexts.iter() {
+ ctxs.push(ctx.clone(), GFP_KERNEL)?;
}
Ok(ctxs)
}
@@ -42,7 +39,7 @@ pub(crate) fn get_all_contexts() -> Result<KVec<Arc<Context>>> {
struct Manager {
node: Option<NodeRef>,
uid: Option<Kuid>,
- all_procs: List<Process>,
+ all_procs: KVVec<Arc<Process>>,
}
/// There is one context per binder file (/dev/binder, /dev/hwbinder, etc)
@@ -51,28 +48,16 @@ pub(crate) struct Context {
#[pin]
manager: Mutex<Manager>,
pub(crate) name: CString,
- #[pin]
- links: ListLinks,
-}
-
-kernel::list::impl_list_arc_safe! {
- impl ListArcSafe<0> for Context { untracked; }
-}
-kernel::list::impl_list_item! {
- impl ListItem<0> for Context {
- using ListLinks { self.links };
- }
}
impl Context {
pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> {
let name = CString::try_from(name)?;
- let list_ctx = ListArc::pin_init::<Error>(
+ let ctx = Arc::pin_init(
try_pin_init!(Context {
name,
- links <- ListLinks::new(),
manager <- kernel::new_mutex!(Manager {
- all_procs: List::new(),
+ all_procs: KVVec::new(),
node: None,
uid: None,
}, "Context::manager"),
@@ -80,8 +65,7 @@ pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> {
GFP_KERNEL,
)?;
- let ctx = list_ctx.clone_arc();
- CONTEXTS.lock().list.push_back(list_ctx);
+ CONTEXTS.lock().contexts.push(ctx.clone(), GFP_KERNEL)?;
Ok(ctx)
}
@@ -90,17 +74,24 @@ pub(crate) fn new(name: &CStr) -> Result<Arc<Self>> {
///
/// No-op if called twice.
pub(crate) fn deregister(&self) {
- // SAFETY: We never add the context to any other linked list than this one, so it is either
- // in this list, or not in any list.
- unsafe { CONTEXTS.lock().list.remove(self) };
+ // Safe removal using retain
+ CONTEXTS.lock().contexts.retain(|c| {
+ let p1 = Arc::as_ptr(c);
+ let p2 = self as *const Context;
+ p1 != p2
+ });
}
- pub(crate) fn register_process(self: &Arc<Self>, proc: ListArc<Process>) {
+ pub(crate) fn register_process(self: &Arc<Self>, proc: Arc<Process>) -> Result {
if !Arc::ptr_eq(self, &proc.ctx) {
pr_err!("Context::register_process called on the wrong context.");
- return;
+ return Err(EINVAL);
}
- self.manager.lock().all_procs.push_back(proc);
+ self.manager
+ .lock()
+ .all_procs
+ .push(proc, GFP_KERNEL)
+ .map_err(Error::from)
}
pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Process) {
@@ -108,8 +99,12 @@ pub(crate) fn deregister_process(self: &Arc<Self>, proc: &Process) {
pr_err!("Context::deregister_process called on the wrong context.");
return;
}
- // SAFETY: We just checked that this is the right list.
- unsafe { self.manager.lock().all_procs.remove(proc) };
+ // Safe removal using retain
+ self.manager.lock().all_procs.retain(|p| {
+ let p1 = Arc::as_ptr(p);
+ let p2 = proc as *const Process;
+ p1 != p2
+ });
}
pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result {
@@ -160,11 +155,9 @@ pub(crate) fn for_each_proc<F>(&self, mut func: F)
pub(crate) fn get_all_procs(&self) -> Result<KVec<Arc<Process>>> {
let lock = self.manager.lock();
- let count = lock.all_procs.iter().count();
-
- let mut procs = KVec::with_capacity(count, GFP_KERNEL)?;
- for proc in &lock.all_procs {
- procs.push(Arc::from(proc), GFP_KERNEL)?;
+ let mut procs = KVec::with_capacity(lock.all_procs.len(), GFP_KERNEL)?;
+ for proc in lock.all_procs.iter() {
+ procs.push(Arc::clone(proc), GFP_KERNEL)?;
}
Ok(procs)
}
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 132055b4790f..c3676fc7785d 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -513,7 +513,9 @@ fn new(ctx: Arc<Context>, cred: ARef<Credential>) -> Result<Arc<Self>> {
)?;
let process = list_process.clone_arc();
- process.ctx.register_process(list_process);
+ process
+ .ctx
+ .register_process(Arc::from(list_process.as_arc_borrow()))?;
Ok(process)
}
--
2.43.0
next reply other threads:[~2026-01-17 16:23 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-17 16:22 jkhall81 [this message]
2026-01-18 6:51 ` Greg Kroah-Hartman
2026-01-18 9:36 ` Alice Ryhl
2026-01-18 9:37 ` Alice Ryhl
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=20260117162242.950194-1-jason.kei.hall@gmail.com \
--to=jason.kei.hall@gmail.com \
--cc=aliceryhl@google.com \
--cc=arve@android.com \
--cc=cmllamas@google.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=tkjos@android.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®