From: Alice Ryhl <aliceryhl@google.com>
To: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Arve Hjønnevåg" <arve@android.com>,
"Todd Kjos" <tkjos@android.com>,
"Martijn Coenen" <maco@android.com>,
"Joel Fernandes" <joel@joelfernandes.org>,
"Christian Brauner" <brauner@kernel.org>,
"Carlos Llamas" <cmllamas@google.com>,
"Suren Baghdasaryan" <surenb@google.com>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@samsung.com>,
"Matt Gilbride" <mattgilbride@google.com>,
"Jeffrey Vander Stoep" <jeffv@google.com>,
"Matthew Maurer" <mmaurer@google.com>,
"Alice Ryhl" <aliceryhl@google.com>
Subject: [PATCH RFC 18/20] rust_binder: add binder_logs/state
Date: Wed, 01 Nov 2023 18:01:48 +0000 [thread overview]
Message-ID: <20231101-rust-binder-v1-18-08ba9197f637@google.com> (raw)
In-Reply-To: <20231101-rust-binder-v1-0-08ba9197f637@google.com>
The binderfs directory has four files intended for debugging the driver.
This patch implements the state file so that you can use it to view the
current state of the driver.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
drivers/android/node.rs | 37 ++++++++++++++++++++
drivers/android/process.rs | 75 +++++++++++++++++++++++++++++++++++++++++
drivers/android/rust_binder.rs | 23 ++++++++++++-
drivers/android/thread.rs | 68 +++++++++++++++++++++++++++++++++++++
drivers/android/transaction.rs | 25 ++++++++++++++
rust/bindings/bindings_helper.h | 1 +
rust/kernel/lib.rs | 1 +
rust/kernel/seq_file.rs | 47 ++++++++++++++++++++++++++
8 files changed, 276 insertions(+), 1 deletion(-)
diff --git a/drivers/android/node.rs b/drivers/android/node.rs
index 2c056bd7582e..3acad1c2b963 100644
--- a/drivers/android/node.rs
+++ b/drivers/android/node.rs
@@ -7,6 +7,8 @@
TryNewListArc,
},
prelude::*,
+ seq_file::SeqFile,
+ seq_print,
sync::lock::{spinlock::SpinLockBackend, Guard},
sync::{Arc, LockedBy, SpinLock},
user_ptr::UserSlicePtrWriter,
@@ -111,6 +113,41 @@ pub(crate) fn new(
})
}
+ #[inline(never)]
+ pub(crate) fn debug_print(&self, m: &mut SeqFile) -> Result<()> {
+ let weak;
+ let strong;
+ let has_weak;
+ let has_strong;
+ let active_inc_refs;
+ {
+ let mut guard = self.owner.inner.lock();
+ let inner = self.inner.access_mut(&mut guard);
+ weak = inner.weak.count;
+ has_weak = inner.weak.has_count;
+ strong = inner.strong.count;
+ has_strong = inner.strong.has_count;
+ active_inc_refs = inner.active_inc_refs;
+ }
+
+ let has_weak = if has_weak { "Y" } else { "N" };
+ let has_strong = if has_strong { "Y" } else { "N" };
+
+ seq_print!(
+ m,
+ "node gid:{},ptr:{:#x},cookie:{:#x}: strong{}{} weak{}{} active{}\n",
+ self.global_id,
+ self.ptr,
+ self.cookie,
+ strong,
+ has_strong,
+ weak,
+ has_weak,
+ active_inc_refs
+ );
+ Ok(())
+ }
+
pub(crate) fn get_id(&self) -> (usize, usize) {
(self.ptr, self.cookie)
}
diff --git a/drivers/android/process.rs b/drivers/android/process.rs
index 4ac5d09041a4..b5e44f9f2a14 100644
--- a/drivers/android/process.rs
+++ b/drivers/android/process.rs
@@ -20,6 +20,8 @@
pages::Pages,
prelude::*,
rbtree::RBTree,
+ seq_file::SeqFile,
+ seq_print,
sync::{
lock::Guard, Arc, ArcBorrow, CondVar, CondVarTimeoutResult, Mutex, SpinLock, UniqueArc,
},
@@ -405,6 +407,79 @@ fn new(ctx: Arc<Context>, cred: ARef<Credential>) -> Result<Arc<Self>> {
Ok(process)
}
+ #[inline(never)]
+ pub(crate) fn debug_print(&self, m: &mut SeqFile) -> Result<()> {
+ seq_print!(m, "pid: {}\n", self.task.pid_in_current_ns());
+
+ let is_manager;
+ let started_threads;
+ let has_proc_work;
+ let mut ready_threads = Vec::new();
+ let mut all_threads = Vec::new();
+ let mut all_nodes = Vec::new();
+ loop {
+ let inner = self.inner.lock();
+ let ready_threads_len = inner.ready_threads.iter().count();
+ let all_threads_len = inner.threads.values().count();
+ let all_nodes_len = inner.nodes.values().count();
+
+ let resize_ready_threads = ready_threads_len > ready_threads.capacity();
+ let resize_all_threads = all_threads_len > all_threads.capacity();
+ let resize_all_nodes = all_nodes_len > all_nodes.capacity();
+ if resize_ready_threads || resize_all_threads || resize_all_nodes {
+ drop(inner);
+ ready_threads.try_reserve(ready_threads_len)?;
+ all_threads.try_reserve(all_threads_len)?;
+ all_nodes.try_reserve(all_nodes_len)?;
+ continue;
+ }
+
+ is_manager = inner.is_manager;
+ started_threads = inner.started_thread_count;
+ has_proc_work = !inner.work.is_empty();
+
+ for thread in &inner.ready_threads {
+ assert!(ready_threads.len() < ready_threads.capacity());
+ ready_threads.try_push(thread.id)?;
+ }
+
+ for thread in inner.threads.values() {
+ assert!(all_threads.len() < all_threads.capacity());
+ all_threads.try_push(thread.clone())?;
+ }
+
+ for node in inner.nodes.values() {
+ assert!(all_nodes.len() < all_nodes.capacity());
+ all_nodes.try_push(node.clone())?;
+ }
+
+ break;
+ }
+
+ seq_print!(m, "is_manager: {}\n", is_manager);
+ seq_print!(m, "started_threads: {}\n", started_threads);
+ seq_print!(m, "has_proc_work: {}\n", has_proc_work);
+ if ready_threads.is_empty() {
+ seq_print!(m, "ready_thread_ids: none\n");
+ } else {
+ seq_print!(m, "ready_thread_ids:");
+ for thread_id in ready_threads {
+ seq_print!(m, " {}", thread_id);
+ }
+ seq_print!(m, "\n");
+ }
+
+ for node in all_nodes {
+ node.debug_print(m)?;
+ }
+
+ seq_print!(m, "all threads:\n");
+ for thread in all_threads {
+ thread.debug_print(m);
+ }
+ Ok(())
+ }
+
/// Attempts to fetch a work item from the process queue.
pub(crate) fn get_work(&self) -> Option<DLArc<dyn DeliverToRead>> {
self.inner.lock().work.pop_front()
diff --git a/drivers/android/rust_binder.rs b/drivers/android/rust_binder.rs
index adf542872f36..a1c95a1609d5 100644
--- a/drivers/android/rust_binder.rs
+++ b/drivers/android/rust_binder.rs
@@ -10,6 +10,8 @@
HasListLinks, ListArc, ListArcSafe, ListItem, ListLinks, ListLinksSelfPtr, TryNewListArc,
},
prelude::*,
+ seq_file::SeqFile,
+ seq_print,
sync::Arc,
types::ForeignOwnable,
user_ptr::UserSlicePtrWriter,
@@ -347,7 +349,13 @@ unsafe impl<T> Sync for AssertSync<T> {}
}
#[no_mangle]
-unsafe extern "C" fn rust_binder_state_show(_: *mut seq_file) -> core::ffi::c_int {
+unsafe extern "C" fn rust_binder_state_show(ptr: *mut seq_file) -> core::ffi::c_int {
+ // SAFETY: The caller ensures that the pointer is valid and exclusive for the duration in which
+ // this method is called.
+ let m = unsafe { SeqFile::from_raw(ptr) };
+ if let Err(err) = rust_binder_state_show_impl(m) {
+ seq_print!(m, "failed to generate state: {:?}\n", err);
+ }
0
}
@@ -360,3 +368,16 @@ unsafe impl<T> Sync for AssertSync<T> {}
unsafe extern "C" fn rust_binder_transaction_log_show(_: *mut seq_file) -> core::ffi::c_int {
0
}
+
+fn rust_binder_state_show_impl(m: &mut SeqFile) -> Result<()> {
+ let contexts = context::get_all_contexts()?;
+ for ctx in contexts {
+ let procs = ctx.get_all_procs()?;
+ seq_print!(m, "context {}: ({} processes)\n", &*ctx.name, procs.len());
+ for proc in procs {
+ proc.debug_print(m)?;
+ seq_print!(m, "\n");
+ }
+ }
+ Ok(())
+}
diff --git a/drivers/android/thread.rs b/drivers/android/thread.rs
index 414ffb1387a0..d5a56119cc19 100644
--- a/drivers/android/thread.rs
+++ b/drivers/android/thread.rs
@@ -15,6 +15,8 @@
},
prelude::*,
security,
+ seq_file::SeqFile,
+ seq_print,
sync::{Arc, SpinLock},
types::Either,
user_ptr::{UserSlicePtr, UserSlicePtrWriter},
@@ -447,6 +449,72 @@ pub(crate) fn new(id: i32, process: Arc<Process>) -> Result<Arc<Self>> {
}))
}
+ #[inline(never)]
+ pub(crate) fn debug_print(&self, m: &mut SeqFile) {
+ let looper_flags;
+ let looper_need_return;
+ let is_dead;
+ let has_work;
+ let process_work_list;
+ let current_transaction;
+ {
+ let inner = self.inner.lock();
+ looper_flags = inner.looper_flags;
+ looper_need_return = inner.looper_need_return;
+ is_dead = inner.is_dead;
+ has_work = !inner.work_list.is_empty();
+ process_work_list = inner.process_work_list;
+ current_transaction = inner.current_transaction.clone();
+ }
+ seq_print!(m, " tid: {}\n", self.id);
+ seq_print!(m, " state:");
+ if is_dead {
+ seq_print!(m, " dead");
+ }
+ if looper_need_return {
+ seq_print!(m, " pending_flush_wakeup");
+ }
+ if has_work && process_work_list {
+ seq_print!(m, " has_work");
+ }
+ if has_work && !process_work_list {
+ seq_print!(m, " has_deferred_work");
+ }
+ if looper_flags & LOOPER_REGISTERED != 0 {
+ seq_print!(m, " registered");
+ }
+ if looper_flags & LOOPER_ENTERED != 0 {
+ seq_print!(m, " entered");
+ }
+ if looper_flags & LOOPER_EXITED != 0 {
+ seq_print!(m, " exited");
+ }
+ if looper_flags & LOOPER_INVALID != 0 {
+ seq_print!(m, " invalid");
+ }
+ if looper_flags & LOOPER_WAITING != 0 {
+ if looper_flags & LOOPER_WAITING_PROC != 0 {
+ seq_print!(m, " in_get_work");
+ } else {
+ seq_print!(m, " in_get_work_local");
+ }
+ }
+ if looper_flags & LOOPER_POLL != 0 {
+ seq_print!(m, " poll_is_initialized");
+ }
+ seq_print!(m, "\n");
+ if current_transaction.is_some() {
+ seq_print!(m, " tstack:");
+ let mut t = current_transaction;
+ while let Some(tt) = t.as_ref() {
+ seq_print!(m, " ");
+ tt.debug_print(m);
+ t = tt.clone_next();
+ }
+ seq_print!(m, "\n");
+ }
+ }
+
pub(crate) fn get_extended_error(&self, data: UserSlicePtr) -> Result {
let mut writer = data.writer();
let ee = self.inner.lock().extended_error;
diff --git a/drivers/android/transaction.rs b/drivers/android/transaction.rs
index 84b9fe58fe3e..30c411ab0778 100644
--- a/drivers/android/transaction.rs
+++ b/drivers/android/transaction.rs
@@ -5,6 +5,8 @@
io_buffer::IoBufferWriter,
list::ListArcSafe,
prelude::*,
+ seq_file::SeqFile,
+ seq_print,
sync::{Arc, SpinLock},
task::Kuid,
types::{Either, ScopeGuard},
@@ -140,6 +142,29 @@ pub(crate) fn new_reply(
}))?)
}
+ #[inline(never)]
+ pub(crate) fn debug_print(&self, m: &mut SeqFile) {
+ let from_pid = self.from.process.task.pid_in_current_ns();
+ let to_pid = self.to.task.pid_in_current_ns();
+ let from_tid = self.from.id;
+ match self.target_node.as_ref() {
+ Some(target_node) => {
+ let node_id = target_node.global_id;
+ seq_print!(
+ m,
+ "{}(tid:{})->{}(nid:{})",
+ from_pid,
+ from_tid,
+ to_pid,
+ node_id
+ );
+ }
+ None => {
+ seq_print!(m, "{}(tid:{})->{}(nid:_)", from_pid, from_tid, to_pid);
+ }
+ }
+ }
+
/// Determines if the transaction is stacked on top of the given transaction.
pub(crate) fn is_stacked_on(&self, onext: &Option<DArc<Self>>) -> bool {
match (&self.stack_next, onext) {
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index ffeea312f2fd..b2d60b4a9df6 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -15,6 +15,7 @@
#include <linux/pid_namespace.h>
#include <linux/poll.h>
#include <linux/security.h>
+#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/refcount.h>
#include <linux/rust_binder.h>
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f4d58da9202e..d46187783464 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -48,6 +48,7 @@
pub mod print;
pub mod rbtree;
pub mod security;
+pub mod seq_file;
mod static_assert;
#[doc(hidden)]
pub mod std_vendor;
diff --git a/rust/kernel/seq_file.rs b/rust/kernel/seq_file.rs
new file mode 100644
index 000000000000..997d527b2e9e
--- /dev/null
+++ b/rust/kernel/seq_file.rs
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Seq file bindings.
+//!
+//! C header: [`include/linux/seq_file.h`](../../../../include/linux/seq_file.h)
+
+use crate::{bindings, c_str, types::Opaque};
+
+/// A helper for implementing special files, where the complete contents can be generated on each
+/// access.
+pub struct SeqFile(Opaque<bindings::seq_file>);
+
+impl SeqFile {
+ /// Creates a new [`SeqFile`] from a raw pointer.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that, for the duration of 'a, the pointer must point at a valid
+ /// `seq_file` and that it will not be accessed via anything other than the returned reference.
+ pub unsafe fn from_raw<'a>(ptr: *mut bindings::seq_file) -> &'a mut SeqFile {
+ // SAFETY: The safety requirements guarantee the validity of the dereference, while the
+ // `Credential` type being transparent makes the cast ok.
+ unsafe { &mut *ptr.cast() }
+ }
+
+ /// Used by the [`seq_print`] macro.
+ ///
+ /// [`seq_print`]: crate::seq_print
+ pub fn call_printf(&mut self, args: core::fmt::Arguments<'_>) {
+ // SAFETY: Passing a void pointer to `Arguments` is valid for `%pA`.
+ unsafe {
+ bindings::seq_printf(
+ self.0.get(),
+ c_str!("%pA").as_char_ptr(),
+ &args as *const _ as *const core::ffi::c_void,
+ );
+ }
+ }
+}
+
+/// Use for writing to a [`SeqFile`] with the ordinary Rust formatting syntax.
+#[macro_export]
+macro_rules! seq_print {
+ ($m:expr, $($arg:tt)+) => (
+ $m.call_printf(format_args!($($arg)+))
+ );
+}
--
2.42.0.820.g83a721a137-goog
next prev parent reply other threads:[~2023-11-01 18:22 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-01 18:01 [PATCH RFC 00/20] Setting up Binder for the future Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 01/20] rust_binder: define a Rust binder driver Alice Ryhl
2023-11-01 18:09 ` Greg Kroah-Hartman
2023-11-08 10:38 ` Alice Ryhl
2023-11-01 18:25 ` Boqun Feng
2023-11-02 10:27 ` Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 02/20] rust_binder: add binderfs support to Rust binder Alice Ryhl
2023-11-01 18:10 ` Greg Kroah-Hartman
2023-11-08 10:42 ` Alice Ryhl
2023-11-03 10:11 ` Finn Behrens
2023-11-08 10:31 ` Alice Ryhl
2023-11-03 16:30 ` Benno Lossin
2023-11-03 17:34 ` Boqun Feng
2023-11-08 10:25 ` Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 03/20] rust_binder: add threading support Alice Ryhl
2023-11-03 10:51 ` Finn Behrens
2023-11-08 10:27 ` Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 04/20] rust_binder: add work lists Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 05/20] rust_binder: add nodes and context managers Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 06/20] rust_binder: add oneway transactions Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 07/20] rust_binder: add epoll support Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 08/20] rust_binder: add non-oneway transactions Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 09/20] rust_binder: serialize oneway transactions Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 10/20] rust_binder: add death notifications Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 11/20] rust_binder: send nodes in transactions Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 12/20] rust_binder: add BINDER_TYPE_PTR support Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 13/20] rust_binder: add BINDER_TYPE_FD support Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 14/20] rust_binder: add BINDER_TYPE_FDA support Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 15/20] rust_binder: add process freezing Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 16/20] rust_binder: add TF_UPDATE_TXN support Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 17/20] rust_binder: add oneway spam detection Alice Ryhl
2023-11-01 18:01 ` Alice Ryhl [this message]
2023-11-01 18:01 ` [PATCH RFC 19/20] rust_binder: add vma shrinker Alice Ryhl
2023-11-01 18:01 ` [PATCH RFC 20/20] binder: delete the C implementation Alice Ryhl
2023-11-01 18:15 ` Greg Kroah-Hartman
2023-11-01 18:39 ` Carlos Llamas
2023-11-01 18:34 ` [PATCH RFC 00/20] Setting up Binder for the future Carlos Llamas
2023-11-02 13:33 ` 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=20231101-rust-binder-v1-18-08ba9197f637@google.com \
--to=aliceryhl@google.com \
--cc=a.hindborg@samsung.com \
--cc=alex.gaynor@gmail.com \
--cc=arve@android.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=brauner@kernel.org \
--cc=cmllamas@google.com \
--cc=gary@garyguo.net \
--cc=gregkh@linuxfoundation.org \
--cc=jeffv@google.com \
--cc=joel@joelfernandes.org \
--cc=linux-kernel@vger.kernel.org \
--cc=maco@android.com \
--cc=mattgilbride@google.com \
--cc=mmaurer@google.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=surenb@google.com \
--cc=tkjos@android.com \
--cc=wedsonaf@gmail.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®