From nobody Sun Feb 8 00:49:31 2026 Received: from mail-dl1-f44.google.com (mail-dl1-f44.google.com [74.125.82.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2A06366566 for ; Tue, 20 Jan 2026 13:41:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768916486; cv=none; b=hIjD1YZ+wt4R7WDySW+Xx+1ahK5lyzofqIi/nzn4iy4I94oQdJ8bl8WeIZdB2YMEZf+xMRBdv6c6uwwJRfa2q1CsZyRCCbqq9mIgqRZlUCOI/D8whcyIyPJJxJh7B8yLUE+LsJISKHOLIw+dmNvdyCX69yKJy5b3+Vo5qE79Fyk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768916486; c=relaxed/simple; bh=p0f6I5EZzmpKZxY4Id2U+rvJA+3l7CP6ompDuOSZcF8=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=HdCSTODxd1ZTQ/wpgbQWlOngWLGY4tMUm78M7OgE4C+ZeXhcUqm+NhKOTGkRVA8qLU0lvFBhwBT63Z8JxUcpeQLQgxawYDSNEy4TAUS1d4BrtoJKvbgTkx0fV1JLjFSVGpkqrqTyonJBKhVpZHI2X8VoaoIOyOGhb5nfxSVaFBY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=QdGooRq1; arc=none smtp.client-ip=74.125.82.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="QdGooRq1" Received: by mail-dl1-f44.google.com with SMTP id a92af1059eb24-1233b953bebso933897c88.1 for ; Tue, 20 Jan 2026 05:41:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768916484; x=1769521284; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=QxNMUvcFDRDyo819s9ijKBWJ2/BhKTnu9hq6sC458h0=; b=QdGooRq1tHefNghKkzVx4wGAiZc0yT/uLcImlkJdvKSrZLb3PkMF2gxUcWsO7Q5S/c 2BLO9hMcPa/AD77+crcxSQrasF46D24AkqOW0mtDSoYGl4SYTM5CpHuVZTGYhUkib4jY T2lecqjWOzLNZOnAF2xF7y49gMHOItOW7JiEu1J38AeUQ6S08GsX1dFgHUbbCz7amQx3 7SVEGu+76Yc4NPOYDyaP0/QxTm/irt6OJ/wyar+543MPGGqefn2Of2GS6Gzc2sPzj9dZ fISsmBEa4nYYHPdYm3IpFukqH0nqzjgRwg17X4nJ7QQEv8uk0tyWl5YVxv5nUGzNk6tT JAZQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768916484; x=1769521284; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=QxNMUvcFDRDyo819s9ijKBWJ2/BhKTnu9hq6sC458h0=; b=lreHJKJoWEsNJIpwXNNI0+4JAuPiYikipppzzncZJf31okdu92PV8AywobRpO8u/2N Ujl/+yOzMZA0KM1mjTZuDY/PQMqBH1pASnmE0ryrwq3+ufD+S+j/nZTcqUHC/tlGlj4M CgiaI7ypfica/kOlTTRMb1AODaShozUGBJZMCbd6zV35T0mrgMaqIR2Y7hHlKGkl9UfY LOVltfsbbmr2SE9nRiMfGLIAKT4qtZg/7IcXgNXlwzMTdbuLAaoA2XJc1MJxRp1u4XQp rwLf9LpaODDktQHwuT6mLIcfwm0fMJ9Sb70oaiNzSOS1pZuG6AMlKCcTLCyTt/crYijR FbbA== X-Forwarded-Encrypted: i=1; AJvYcCXJhArzwv/L1n/HkOAzeiCkaQdr8GEgIwb6Xzd8LLra1Z5a02YHlhp2l8tWU60jwjoWer34xniNvzcwWlM=@vger.kernel.org X-Gm-Message-State: AOJu0YwmvGCK6QNP0G1KZWpId66tdtKyad1+/J4h9VfbXIyUDoOIc7al T0bGYp2drFHiFU2bOM1gcXOYjrsHYLoZDdqAdm5BCM3vk3II5SS6cSHk X-Gm-Gg: AY/fxX68Rrxh4X/jd6R5aMQcNt5RnVCUcbzLQ/TZ/ZjNKrjWV2GsWiScW28xBdQD0t0 acv+RfyUnOEtQUUY2xNGaTxrZMJg/ktwCzMVw0qzFU1RHUrgpXIs9idSlvrUR4/RzjewDm7Nv15 x2VupKrKVRATAqTweyhzpmJDNBbhBKzsoxKRuGO1ChBlrnREgwgmjKYwMcbzSQTAj/DcJhR8dCT W2L6Qv30aQBdab2PEg72v0RwZV1vlYLyKY4KdQWSNPq6n4Q6q4KBuujxJ9F2IKfbme1qssRJlIn haeLKI1YPZMjY18vBLbEQrGHvw+n8fIah4TkTuaHs+0NGy1jiVrE9p7qZ1nInoUN4/8qS2qWKKa fqHFBr8mGsRypPKkURDAFUUlDEAG68CE8Xcg1rO8gzBe5xJt3E0Qh8J3BWpoqFvhzT9mBikSnlU wBDZv5D7jLdJ3xXwXdnY3lq5S7ausZDCOchbQhrOeFwN6Wa6tU72ClC9hBcU1FdNM= X-Received: by 2002:a05:7022:6b92:b0:123:348b:979c with SMTP id a92af1059eb24-1246a970575mr1504440c88.6.1768916483488; Tue, 20 Jan 2026 05:41:23 -0800 (PST) Received: from jason-hall-A520-B.. ([2600:8800:41a0:8000:3a7a:7bcc:1dce:2822]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-1244af10736sm20752470c88.14.2026.01.20.05.41.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Jan 2026 05:41:22 -0800 (PST) From: Jason Hall To: Alice Ryhl Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org, Greg Kroah-Hartman , =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= , Todd Kjos , Carlos Llamas , jason.kei.hall@gmail.com Subject: [PATCH v4] rust_binder: refactor context management to use KVVec Date: Tue, 20 Jan 2026 06:41:19 -0700 Message-ID: <20260120134119.98048-1-jason.kei.hall@gmail.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace the linked list management in context.rs with KVVec. This 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 Link: https://github.com/rust-for-linux/linux/issues/1215 Signed-off-by: Jason Hall --- v3: - Simplified register_process using ?. - Used Arc::ptr_eq for comparisons in deregister_process. - Changed deregister_process to take &Arc. - Added capacity shrinking logic to Context's process list. - Optimized get_procs_with_pid to iterate directly under the lock. - Removed ListArc usage in process.rs. v4: - Added Arc::ptr_eq to deregister. - Removed dead code from deregister_process. --- drivers/android/binder/context.rs | 84 +++++++++++++------------------ drivers/android/binder/process.rs | 5 +- 2 files changed, 36 insertions(+), 53 deletions(-) diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/con= text.rs index 3d135ec03ca7..c7b75efef217 100644 --- a/drivers/android/binder/context.rs +++ b/drivers/android/binder/context.rs @@ -3,8 +3,8 @@ // Copyright (C) 2025 Google LLC. =20 use kernel::{ - error::Error, - list::{List, ListArc, ListLinks}, + alloc::kvec::KVVec, + 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 initializ= ed before first use. pub(crate) unsafe(uninit) static CONTEXTS: Mutex =3D Cont= extList { - list: List::new(), + contexts: KVVec::new(), }; } =20 pub(crate) struct ContextList { - list: List, + contexts: KVVec>, } =20 -pub(crate) fn get_all_contexts() -> Result>> { +pub(crate) fn get_all_contexts() -> Result>> { let lock =3D CONTEXTS.lock(); - - let count =3D lock.list.iter().count(); - - let mut ctxs =3D KVec::with_capacity(count, GFP_KERNEL)?; - for ctx in &lock.list { - ctxs.push(Arc::from(ctx), GFP_KERNEL)?; + let mut ctxs =3D KVVec::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>> { struct Manager { node: Option, uid: Option, - all_procs: List, + all_procs: KVVec>, } =20 /// There is one context per binder file (/dev/binder, /dev/hwbinder, etc) @@ -51,28 +48,16 @@ pub(crate) struct Context { #[pin] manager: Mutex, 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 }; - } } =20 impl Context { pub(crate) fn new(name: &CStr) -> Result> { let name =3D CString::try_from(name)?; - let list_ctx =3D ListArc::pin_init::( + let ctx =3D 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> { GFP_KERNEL, )?; =20 - let ctx =3D list_ctx.clone_arc(); - CONTEXTS.lock().list.push_back(list_ctx); + CONTEXTS.lock().contexts.push(ctx.clone(), GFP_KERNEL)?; =20 Ok(ctx) } @@ -89,27 +73,27 @@ pub(crate) fn new(name: &CStr) -> Result> { /// Called when the file for this context is unlinked. /// /// 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) }; + pub(crate) fn deregister(self: &Arc) { + // Safe removal using retain + CONTEXTS.lock().contexts.retain(|c| !Arc::ptr_eq(c, self)); } =20 - pub(crate) fn register_process(self: &Arc, proc: ListArc) { + pub(crate) fn register_process(self: &Arc, proc: Arc) -= > 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)?; + Ok(()) } =20 - pub(crate) fn deregister_process(self: &Arc, proc: &Process) { + pub(crate) fn deregister_process(self: &Arc, proc: &Arc= ) { if !Arc::ptr_eq(self, &proc.ctx) { pr_err!("Context::deregister_process called on the wrong conte= xt."); return; } - // SAFETY: We just checked that this is the right list. - unsafe { self.manager.lock().all_procs.remove(proc) }; + let mut manager =3D self.manager.lock(); + manager.all_procs.retain(|p| !Arc::ptr_eq(p, proc)); } =20 pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result { @@ -158,23 +142,23 @@ pub(crate) fn for_each_proc(&self, mut func: F) } } =20 - pub(crate) fn get_all_procs(&self) -> Result>> { + pub(crate) fn get_all_procs(&self) -> Result>> { let lock =3D self.manager.lock(); - let count =3D lock.all_procs.iter().count(); - - let mut procs =3D KVec::with_capacity(count, GFP_KERNEL)?; - for proc in &lock.all_procs { - procs.push(Arc::from(proc), GFP_KERNEL)?; + let mut procs =3D KVVec::with_capacity(lock.all_procs.len(), GFP_K= ERNEL)?; + for proc in lock.all_procs.iter() { + procs.push(Arc::clone(proc), GFP_KERNEL)?; } Ok(procs) } =20 - pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result>> { - let orig =3D self.get_all_procs()?; - let mut backing =3D KVec::with_capacity(orig.len(), GFP_KERNEL)?; - for proc in orig.into_iter().filter(|proc| proc.task.pid() =3D=3D = pid) { - backing.push(proc, GFP_KERNEL)?; + pub(crate) fn get_procs_with_pid(&self, pid: i32) -> Result>> { + let lock =3D self.manager.lock(); + let mut matching_procs =3D KVVec::new(); + for proc in lock.all_procs.iter() { + if proc.task.pid() =3D=3D pid { + matching_procs.push(Arc::clone(proc), GFP_KERNEL)?; + } } - Ok(backing) + Ok(matching_procs) } } diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/pro= cess.rs index 132055b4790f..286d1badf19b 100644 --- a/drivers/android/binder/process.rs +++ b/drivers/android/binder/process.rs @@ -496,7 +496,7 @@ fn run(me: Arc) { impl Process { fn new(ctx: Arc, cred: ARef) -> Result>= { let current =3D kernel::current!(); - let list_process =3D ListArc::pin_init::( + let process =3D Arc::pin_init::( try_pin_init!(Process { ctx, cred, @@ -512,8 +512,7 @@ fn new(ctx: Arc, cred: ARef) -> Re= sult> { GFP_KERNEL, )?; =20 - let process =3D list_process.clone_arc(); - process.ctx.register_process(list_process); + process.ctx.register_process(process.clone())?; =20 Ok(process) } --=20 2.43.0