From: Jahnavi MN via B4 Relay <devnull+jahnavimn.google.com@kernel.org>
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Christian Brauner" <brauner@kernel.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
Jahnavi MN <jahnavimn@google.com>
Subject: [PATCH 1/7] rust_binder: Add dynamic debug logging mask
Date: Fri, 03 Jul 2026 15:29:22 +0000 [thread overview]
Message-ID: <20260703-rust_binder_debug_mask-v1-1-9bdf12b5325c@google.com> (raw)
In-Reply-To: <20260703-rust_binder_debug_mask-v1-0-9bdf12b5325c@google.com>
From: Jahnavi MN <jahnavimn@google.com>
Implement a dynamic debug logging mask (`debug_mask`) for the
`rust_binder` module to allow dynamic runtime configuration of log
levels. This enables parity with the legacy C driver's debug mask.
Since the Rust `module!` macro in the current kernel build does not yet
support declaring module parameters directly in Rust, we define the
`debug_mask` variable in a C companion file to expose it to the kernel
runtime and import it using FFI with volatile reads.
To verify the setup, instrument process lifecycle events (open, flush,
and release) in `process.rs` under the new `BINDER_DEBUG_OPEN_CLOSE`
logging mask. These entry-point events are chosen for initial validation
because they represent the start of the Binder lifecycle and occur
at low frequency, allowing simple runtime verification of the dynamic
toggle without log noise.
Signed-off-by: Jahnavi MN <jahnavimn@google.com>
---
drivers/android/binder/debug.rs | 49 ++++++++++++++++++++++++++++++
drivers/android/binder/process.rs | 15 +++++++--
drivers/android/binder/rust_binder_main.rs | 2 ++
drivers/android/binder/rust_binderfs.c | 3 ++
drivers/android/binder/thread.rs | 1 +
drivers/android/binder/transaction.rs | 5 +--
6 files changed, 71 insertions(+), 4 deletions(-)
diff --git a/drivers/android/binder/debug.rs b/drivers/android/binder/debug.rs
new file mode 100644
index 000000000000..5e4daa823377
--- /dev/null
+++ b/drivers/android/binder/debug.rs
@@ -0,0 +1,49 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2026 Google LLC.
+
+//! Binder debugging helpers.
+
+#![allow(dead_code)]
+
+pub(crate) const BINDER_DEBUG_USER_ERROR: u32 = 1 << 0;
+pub(crate) const BINDER_DEBUG_FAILED_TRANSACTION: u32 = 1 << 1;
+pub(crate) const BINDER_DEBUG_DEAD_TRANSACTION: u32 = 1 << 2;
+pub(crate) const BINDER_DEBUG_OPEN_CLOSE: u32 = 1 << 3;
+pub(crate) const BINDER_DEBUG_DEAD_BINDER: u32 = 1 << 4;
+pub(crate) const BINDER_DEBUG_DEATH_NOTIFICATION: u32 = 1 << 5;
+pub(crate) const BINDER_DEBUG_READ_WRITE: u32 = 1 << 6;
+pub(crate) const BINDER_DEBUG_USER_REFS: u32 = 1 << 7;
+pub(crate) const BINDER_DEBUG_THREADS: u32 = 1 << 8;
+pub(crate) const BINDER_DEBUG_TRANSACTION: u32 = 1 << 9;
+pub(crate) const BINDER_DEBUG_TRANSACTION_COMPLETE: u32 = 1 << 10;
+pub(crate) const BINDER_DEBUG_FREE_BUFFER: u32 = 1 << 11;
+pub(crate) const BINDER_DEBUG_INTERNAL_REFS: u32 = 1 << 12;
+pub(crate) const BINDER_DEBUG_PRIORITY_CAP: u32 = 1 << 13;
+pub(crate) const BINDER_DEBUG_SPINLOCKS: u32 = 1 << 14;
+
+extern "C" {
+ static rust_binder_debug_mask: u32;
+}
+
+/// Checks if the given debug logging category is enabled in the mask.
+pub(crate) fn debug_mask_enabled(mask: u32) -> bool {
+ let ptr = &raw const rust_binder_debug_mask;
+ // SAFETY: `rust_binder_debug_mask` is defined in the companion C code linked in the module.
+ let current_mask = unsafe { core::ptr::read_volatile(ptr) };
+ (current_mask & mask) != 0
+}
+
+/// Prints a debug log if the specified mask category is enabled.
+#[macro_export]
+macro_rules! binder_debug {
+ ($mask:expr, $fmt:literal $(, $($arg:tt)*)?) => {
+ if $crate::debug::debug_mask_enabled($mask) {
+ kernel::pr_info!(
+ "{}: {}\n",
+ kernel::current!().pid(),
+ format_args!($fmt $(, $($arg)*)?)
+ );
+ }
+ };
+}
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 96b8440ceac6..c13a04a3afcb 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -898,7 +898,6 @@ pub(crate) fn insert_or_update_handle(
}
pub(crate) fn get_transaction_node(&self, handle: u32) -> BinderResult<NodeRef> {
- // When handle is zero, try to get the context manager.
if handle == 0 {
Ok(self.ctx.get_manager_node(true)?)
} else {
@@ -1314,6 +1313,11 @@ pub(crate) fn lock_with_nodes(&self) -> WithNodes<'_> {
}
fn deferred_flush(&self) {
+ binder_debug!(
+ crate::debug::BINDER_DEBUG_OPEN_CLOSE,
+ "binder_flush: process {}",
+ self.pid_in_current_ns()
+ );
let inner = self.inner.lock();
for thread in inner.threads.values() {
thread.exit_looper();
@@ -1321,6 +1325,11 @@ fn deferred_flush(&self) {
}
fn deferred_release(self: Arc<Self>) {
+ binder_debug!(
+ crate::debug::BINDER_DEBUG_OPEN_CLOSE,
+ "binder_deferred_release: process {}",
+ self.pid_in_current_ns()
+ );
let is_manager = {
let mut inner = self.inner.lock();
inner.is_dead = true;
@@ -1616,7 +1625,9 @@ fn ioctl_write_read(
/// The file operations supported by `Process`.
impl Process {
pub(crate) fn open(ctx: ArcBorrow<'_, Context>, file: &File) -> Result<Arc<Process>> {
- Self::new(ctx.into(), ARef::from(file.cred()))
+ let proc = Self::new(ctx.into(), ARef::from(file.cred()))?;
+ binder_debug!(crate::debug::BINDER_DEBUG_OPEN_CLOSE, "opened process");
+ Ok(proc)
}
pub(crate) fn release(this: Arc<Process>, _file: &File) {
diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
index dc1941cd2407..bf15021524a4 100644
--- a/drivers/android/binder/rust_binder_main.rs
+++ b/drivers/android/binder/rust_binder_main.rs
@@ -37,6 +37,8 @@
mod context;
mod deferred_close;
mod defs;
+#[macro_use]
+mod debug;
mod error;
mod node;
mod page_range;
diff --git a/drivers/android/binder/rust_binderfs.c b/drivers/android/binder/rust_binderfs.c
index ade1c4d92499..fa8b38465550 100644
--- a/drivers/android/binder/rust_binderfs.c
+++ b/drivers/android/binder/rust_binderfs.c
@@ -51,6 +51,9 @@ DEFINE_SHOW_ATTRIBUTE(rust_binder_proc);
char *rust_binder_devices_param = CONFIG_ANDROID_BINDER_DEVICES;
module_param_named(rust_devices, rust_binder_devices_param, charp, 0444);
+u32 rust_binder_debug_mask = 7;
+module_param_named(debug_mask, rust_binder_debug_mask, uint, 0644);
+
static dev_t binderfs_dev;
static DEFINE_MUTEX(binderfs_minors_mutex);
static DEFINE_IDA(binderfs_minors);
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 97d5f31e8fe3..c908dde5796a 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1222,6 +1222,7 @@ fn read_transaction_info(
info.buffers_size = td.buffers_size as usize;
// SAFETY: Above `read` call initializes all bytes, so this union read is ok.
info.target_handle = unsafe { td.transaction_data.target.handle };
+ info.debug_id = super::next_debug_id();
Ok(())
}
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index 1d9b66920a21..f9285eb93fc0 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -42,6 +42,7 @@ pub(crate) struct TransactionInfo {
pub(crate) reply: u32,
pub(crate) oneway_spam_suspect: bool,
pub(crate) is_reply: bool,
+ pub(crate) debug_id: usize,
}
impl TransactionInfo {
@@ -93,7 +94,7 @@ pub(crate) fn new(
from: &Arc<Thread>,
info: &mut TransactionInfo,
) -> BinderResult<DLArc<Self>> {
- let debug_id = super::next_debug_id();
+ let debug_id = info.debug_id;
let allow_fds = node_ref.node.flags & FLAT_BINDER_FLAG_ACCEPTS_FDS != 0;
let txn_security_ctx = node_ref.node.flags & FLAT_BINDER_FLAG_TXN_SECURITY_CTX != 0;
let mut txn_security_ctx_off = if txn_security_ctx { Some(0) } else { None };
@@ -152,7 +153,7 @@ pub(crate) fn new_reply(
info: &mut TransactionInfo,
allow_fds: bool,
) -> BinderResult<DLArc<Self>> {
- let debug_id = super::next_debug_id();
+ let debug_id = info.debug_id;
let mut alloc =
match from.copy_transaction_data(to.clone(), info, debug_id, allow_fds, None) {
Ok(alloc) => alloc,
--
2.55.0.rc0.799.gd6f94ed593-goog
next prev parent reply other threads:[~2026-07-03 15:29 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-03 15:29 [PATCH 0/7] rust_binder : Implement dynamic debug logging mask Jahnavi MN via B4 Relay
2026-07-03 15:29 ` Jahnavi MN via B4 Relay [this message]
2026-07-03 16:23 ` [PATCH 1/7] rust_binder: Add " Gary Guo
2026-07-04 21:03 ` Alice Ryhl
2026-07-03 15:29 ` [PATCH 2/7] rust_binder: Implement the BINDER_DEBUG_USER_ERROR logging mask for freezer-related operation Jahnavi MN via B4 Relay
2026-07-03 15:29 ` [PATCH 3/7] rust_binder: Implement the BINDER_DEBUG_USER_ERROR logging mask for reference counting and death notification operations Jahnavi MN via B4 Relay
2026-07-04 21:14 ` Alice Ryhl
2026-07-03 15:29 ` [PATCH 4/7] rust_binder: Implement the BINDER_DEBUG_USER_ERROR logging mask for transaction parsing and protocol validation failures Jahnavi MN via B4 Relay
2026-07-03 15:29 ` [PATCH 5/7] rust_binder: Implement the BINDER_DEBUG_FAILED_TRANSACTION logging mask for transaction parsing and routing failures Jahnavi MN via B4 Relay
2026-07-03 15:29 ` [PATCH 6/7] rust_binder: Implement BINDER_DEBUG_FAILED_TRANSACTION logging for death notification allocation failures Jahnavi MN via B4 Relay
2026-07-04 21:17 ` Alice Ryhl
2026-07-03 15:29 ` [PATCH 7/7] rust_binder: Implement the BINDER_DEBUG_DEAD_TRANSACTION logging mask to trace in-flight cancellations during teardown Jahnavi MN via B4 Relay
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=20260703-rust_binder_debug_mask-v1-1-9bdf12b5325c@google.com \
--to=devnull+jahnavimn.google.com@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=arve@android.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=jahnavimn@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tamird@kernel.org \
--cc=tkjos@android.com \
--cc=tmgross@umich.edu \
--cc=work@onurozkan.dev \
/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