From nobody Tue Feb 10 00:22:21 2026 Received: from mail-dy1-f175.google.com (mail-dy1-f175.google.com [74.125.82.175]) (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 0389D369992 for ; Mon, 19 Jan 2026 13:31:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.175 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768829468; cv=none; b=KefGFjAybdTKdFcMjc4wwYUKMlBX6/RL9hHXqxC7vOy6uMqqKwpootPRLpRaGQZmjD7IXjsMdO+QDjIOvMs68Hsb+XzVtNHvw5XJnPiFs9Lat9CBD0eXpJ79NexSiyjgx+6G4wOvagGcLwXsuqpBDuOuprh44TbQ73rRRznYQK0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1768829468; c=relaxed/simple; bh=eXcO94OFOcHR7+hsnfY8B8wyTFSz/c6veamKxvqRoa0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Paa5ZlSI6uyIp+NTiXkgP0fAyzjGsmjahjRWg3LkZbvWEYQneONcuWUYpwQ3eWmdPPryfA5wutOxyG3Y8fYLrkGwMAuL5yIAZjdRaX32ZGO9ru43f4E+0sSuDBE8Cr8UoNRHyCO8QTJwbRpawXcL9oFF0AEr6TziBxyFiBqWI+E= 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=MqLQhoAX; arc=none smtp.client-ip=74.125.82.175 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="MqLQhoAX" Received: by mail-dy1-f175.google.com with SMTP id 5a478bee46e88-2b6bb644e8eso6223103eec.1 for ; Mon, 19 Jan 2026 05:31:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1768829466; x=1769434266; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=QgdJQu8qSrktuaqsrPAanYGNzpWljTQSEn1drXaKpKY=; b=MqLQhoAXAA2G7u6nzQqO8y7JK2Ss7rj3jhk5bOWnD3Qe1Y40gnHTYR0BGiVf3cC28Y 3/wqsclZmpZYmDoYWF+n4iJFF2BnzN5Shm+VPbypq0MKQy52jyINMlHDvZRLbFwf979/ unbnMBtK5ULikHb7JYAFS1TJ62ZW5Bv7HBzi0JkL+I7Plt+pD/alQWIg5f7Jlr7l+67L /Me6GQXtzVSCVojHGUDn6xSLHAsqS4j+r1bhyia8inoi3IJhe31n4B15j5g84gx3Yzky oNKb65z59KH53BOlZmxuRW3NZlxHh7SFt4ubi0x5UcHPwfo5+Hhpat4jfh32+9lqpCa8 0lBg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1768829466; x=1769434266; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=QgdJQu8qSrktuaqsrPAanYGNzpWljTQSEn1drXaKpKY=; b=UG8E0dLBR41oslBW1IQvPyGIUBJBwBNPh52y/+HX/xQvl3H/C+8u1o4gsETGzF0kl8 VUORUW10dX5EZtzeFiXvzW+x4VnkTLF46MiU9cTuvUwpZZRaciEbjnBkwFadMWBgQte9 2hyPv+UARddV5k+Xfrd5H2bq0DbPP6PyQFaJs+5FPyI9dLmZ/uy8jHMPoRj0D2mZx1LA qW0kJyKh6oLddSOtsCYpgcEmopSUYx4hIlOBH9xM4p6Mz/OpyzdepwZYZZiXhQHUju54 5ktHYO2SQsXkwLAWdiaqJPGkLbtVNijIhP1iaIMWrE+FZ2hPvt44cmiC4JKreDhQrUQE J4JA== X-Forwarded-Encrypted: i=1; AJvYcCXtnsBnZx7nVdmlHRzEY5RJnhHKzQzOVAQC2eYGx/PYOn5Aa2UZhZ2eKbZGgcIUMrv7Yl3XZQjKMbgkfXE=@vger.kernel.org X-Gm-Message-State: AOJu0YwD/gyHCOmZqoI+DitvqqTGGmJktUCxbISrX7Nr7i4ZTQGc2rME P3+giQRBzM+9YY/RArdsQXfyGkSujsFX04dijPa5qiK1E4MsUOyf2SOS X-Gm-Gg: AZuq6aJCh2jjSctuQaxY1CCxl20LkX3MW+LbAL6ggmCCEgvLDbESK3sw5LjZL2hjmRU 4Viy7zBxfcf1j9LqhjklgYLpBNfhqRoyLG6920oCD0rwrHJg8di3IgVJTMo2lgO8ykQLspPhbgz WBXzrwN8kSqafYME3DkkzkTmMDo4uf+W46oAIxn2JMlMSU88PXTH6r2ZyY+egyMFPBGFVRmlQS3 y4iEOdNFnnpB7yJFpM8f7thNJk9qto7rj3GbZPSsDK1/8LB8cPkj5nri3tEPT1qhcl284MIOxAd cjckqF2s6SXarYKSQW4EjrJ9t0gAuTQ0WgH9DZgumlvki3lxJ7dNTf8+txw6ZRlheX7PE0clVzG QEDfKmzbjchTmHOIFZe4E6FZ42dR5qNOw1wdAH52RPWprylMS2Mj0JLuV4S/PEpLdYLgt5zhTUB H3HkBufmKosnHY3ywnku34G0ESNAzpEaO5LK4OZYY9QKtdTczti53ixUcWcZ5P/ciooRL+Fvtf X-Received: by 2002:a05:7301:6088:b0:2a7:27d:66e3 with SMTP id 5a478bee46e88-2b6b3f136d6mr9662207eec.2.1768829465811; Mon, 19 Jan 2026 05:31:05 -0800 (PST) Received: from jason-hall-A520-B.. ([2600:8800:41a0:8000:a42d:ec5:48c1:73b9]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-2b6c2de1f29sm11096882eec.15.2026.01.19.05.31.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 19 Jan 2026 05:31:05 -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 Hall Subject: [PATCH v3] rust_binder: refactor context management to use KVVec Date: Mon, 19 Jan 2026 06:31:01 -0700 Message-ID: <20260119133101.23708-1-jason.kei.hall@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260118142623.1188141-1-jason.kei.hall@gmail.com> References: <20260118142623.1188141-1-jason.kei.hall@gmail.com> 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. --- drivers/android/binder/context.rs | 91 ++++++++++++++----------------- drivers/android/binder/process.rs | 5 +- 2 files changed, 44 insertions(+), 52 deletions(-) diff --git a/drivers/android/binder/context.rs b/drivers/android/binder/con= text.rs index 3d135ec03ca7..dedcfd9dfea2 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) } @@ -90,26 +74,35 @@ pub(crate) fn new(name: &CStr) -> Result> { /// /// 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 =3D Arc::as_ptr(c); + let p2 =3D self as *const Context; + p1 !=3D p2 + }); } =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)); + let len =3D manager.all_procs.len(); + let cap =3D manager.all_procs.capacity(); + if len < cap / 2 && cap > 128 { + let _ =3D manager.all_procs.reserve(0, GFP_KERNEL); + } } =20 pub(crate) fn set_manager_node(&self, node_ref: NodeRef) -> Result { @@ -158,23 +151,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