public inbox for rust-for-linux@vger.kernel.org
 help / color / mirror / Atom feed
From: Alice Ryhl <aliceryhl@google.com>
To: Mohamad Alsadhan <mo@sdhn.cc>, '@google.com
Cc: "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>,
	"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>,
	linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org
Subject: Re: [PATCH v2 3/3] rust_binder: add in the new tracepoint calls
Date: Mon, 16 Mar 2026 14:12:10 +0000	[thread overview]
Message-ID: <abgPugGZKSCvLjFX@google.com> (raw)
In-Reply-To: <20260308-rust-binder-trace-v2-3-9e38637a2193@sdhn.cc>

On Sun, Mar 08, 2026 at 04:24:36AM +0300, Mohamad Alsadhan wrote:
> Wire the new Rust Binder tracepoints into live execution paths.
> 
> Hook trace calls into:
> 
> - ioctl entry/exit (`binder_ioctl`, `binder_ioctl_done`)
> - command parsing and return writes (`binder_command`,
>   `binder_return`)
> - read/write completion (`binder_read_done`, `binder_write_done`)
> - wait (`binder_wait_for_work`)
> - transaction (`binder_transaction_received`)
> - fd translation (`binder_transaction_fd_{send,recv}`)
> - buffer/page lifecycle (`binder_alloc_*`, `binder_free_*`,
>   `binder_unmap_*`)
> 
> Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>

Thanks for your series.

Instead of having one commit declaring *all* the tracepoints, and
another commit calling *all* the tracepoints, this needs to be one
commit per tracepoint category. Declaring the tracepoint and adding its
caller can happen in the same commit.

Also, I'm not sure we need the buffer/page lifecycle ones, so I think we
can just drop those.

Alice

> ---
>  drivers/android/binder/allocation.rs       |  1 +
>  drivers/android/binder/page_range.rs       | 17 +++++++++++++++++
>  drivers/android/binder/process.rs          |  7 +++++--
>  drivers/android/binder/rust_binder_main.rs |  1 +
>  drivers/android/binder/thread.rs           | 15 +++++++++++++--
>  drivers/android/binder/transaction.rs      |  2 ++
>  6 files changed, 39 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/android/binder/allocation.rs b/drivers/android/binder/allocation.rs
> index 7f65a9c3a..8c0f94463 100644
> --- a/drivers/android/binder/allocation.rs
> +++ b/drivers/android/binder/allocation.rs
> @@ -208,6 +208,7 @@ pub(crate) fn translate_fds(&mut self) -> Result<TranslatedFds> {
>              let res = FileDescriptorReservation::get_unused_fd_flags(bindings::O_CLOEXEC)?;
>              let fd = res.reserved_fd();
>              self.write::<u32>(file_info.buffer_offset, &fd)?;
> +            crate::trace::trace_transaction_fd_recv(self.debug_id, fd, file_info.buffer_offset);
>  
>              reservations.push(
>                  Reservation {
> diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs
> index fdd97112e..43fe23907 100644
> --- a/drivers/android/binder/page_range.rs
> +++ b/drivers/android/binder/page_range.rs
> @@ -327,6 +327,8 @@ pub(crate) fn use_range(&self, start: usize, end: usize) -> Result<()> {
>  
>              // SAFETY: The pointer is valid, and we hold the lock so reading from the page is okay.
>              if let Some(page) = unsafe { PageInfo::get_page(page_info) } {
> +                crate::trace::trace_alloc_lru_start(self.pid, i);
> +
>                  // Since we're going to use the page, we should remove it from the lru list so that
>                  // the shrinker will not free it.
>                  //
> @@ -335,9 +337,12 @@ pub(crate) fn use_range(&self, start: usize, end: usize) -> Result<()> {
>                  // The shrinker can't free the page between the check and this call to
>                  // `list_lru_del` because we hold the lock.
>                  unsafe { PageInfo::list_lru_del(page_info, page.nid(), self.shrinker) };
> +
> +                crate::trace::trace_alloc_lru_end(self.pid, i);
>              } else {
>                  // We have to allocate a new page. Use the slow path.
>                  drop(inner);
> +                crate::trace::trace_alloc_page_start(self.pid, i);
>                  // SAFETY: `i < end <= inner.size` so `i` is in bounds.
>                  match unsafe { self.use_page_slow(i) } {
>                      Ok(()) => {}
> @@ -346,6 +351,7 @@ pub(crate) fn use_range(&self, start: usize, end: usize) -> Result<()> {
>                          return Err(err);
>                      }
>                  }
> +                crate::trace::trace_alloc_page_end(self.pid, i);
>                  inner = self.lock.lock();
>              }
>          }
> @@ -448,8 +454,12 @@ pub(crate) fn stop_using_range(&self, start: usize, end: usize) {
>  
>              // SAFETY: Okay for reading since we have the lock.
>              if let Some(page) = unsafe { PageInfo::get_page(page_info) } {
> +                crate::trace::trace_free_lru_start(self.pid, i);
> +
>                  // SAFETY: The pointer is valid, and it's the right shrinker.
>                  unsafe { PageInfo::list_lru_add(page_info, page.nid(), self.shrinker) };
> +
> +                crate::trace::trace_free_lru_end(self.pid, i);
>              }
>          }
>      }
> @@ -667,6 +677,7 @@ fn drop(self: Pin<&mut Self>) {
>      let mmap_read;
>      let mm_mutex;
>      let vma_addr;
> +    let pid;
>  
>      {
>          // CAST: The `list_head` field is first in `PageInfo`.
> @@ -700,7 +711,9 @@ fn drop(self: Pin<&mut Self>) {
>  
>          // SAFETY: Both pointers are in bounds of the same allocation.
>          page_index = unsafe { info.offset_from(inner.pages) } as usize;
> +        pid = range.pid;
>  
> +        crate::trace::trace_unmap_kernel_start(pid, page_index);
>          // SAFETY: We hold the spinlock, so we can take the page.
>          //
>          // This sets the page pointer to zero before we unmap it from the vma. However, we call
> @@ -709,6 +722,8 @@ fn drop(self: Pin<&mut Self>) {
>          page = unsafe { PageInfo::take_page(info) };
>          vma_addr = inner.vma_addr;
>  
> +        crate::trace::trace_unmap_kernel_end(pid, page_index);
> +
>          // From this point on, we don't access this PageInfo or ShrinkablePageRange again, because
>          // they can be freed at any point after we unlock `lru_lock`. This is with the exception of
>          // `mm_mutex` which is kept alive by holding the lock.
> @@ -719,7 +734,9 @@ fn drop(self: Pin<&mut Self>) {
>  
>      if let Some(vma) = mmap_read.vma_lookup(vma_addr) {
>          let user_page_addr = vma_addr + (page_index << PAGE_SHIFT);
> +        crate::trace::trace_unmap_user_start(pid, page_index);
>          vma.zap_page_range_single(user_page_addr, PAGE_SIZE);
> +        crate::trace::trace_unmap_user_end(pid, page_index);
>      }
>  
>      drop(mmap_read);
> diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
> index 41de55931..4d7b165e7 100644
> --- a/drivers/android/binder/process.rs
> +++ b/drivers/android/binder/process.rs
> @@ -1656,11 +1656,14 @@ pub(crate) fn ioctl(this: ArcBorrow<'_, Process>, file: &File, cmd: u32, arg: us
>  
>          const _IOC_READ_WRITE: u32 = _IOC_READ | _IOC_WRITE;
>  
> -        match _IOC_DIR(cmd) {
> +        let res = match _IOC_DIR(cmd) {
>              _IOC_WRITE => Self::ioctl_write_only(this, file, cmd, &mut user_slice.reader()),
>              _IOC_READ_WRITE => Self::ioctl_write_read(this, file, cmd, user_slice),
>              _ => Err(EINVAL),
> -        }
> +        };
> +
> +        crate::trace::trace_ioctl_done(res);
> +        res
>      }
>  
>      pub(crate) fn mmap(
> diff --git a/drivers/android/binder/rust_binder_main.rs b/drivers/android/binder/rust_binder_main.rs
> index aa5f2a75a..1028e0a8a 100644
> --- a/drivers/android/binder/rust_binder_main.rs
> +++ b/drivers/android/binder/rust_binder_main.rs
> @@ -116,6 +116,7 @@ fn new(writer: UserSliceWriter, thread: &'a Thread) -> Self {
>      /// Write a return code back to user space.
>      /// Should be a `BR_` constant from [`defs`] e.g. [`defs::BR_TRANSACTION_COMPLETE`].
>      fn write_code(&mut self, code: u32) -> Result {
> +        crate::trace::trace_return(code);
>          stats::GLOBAL_STATS.inc_br(code);
>          self.thread.process.stats.inc_br(code);
>          self.writer.write(&code)
> diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
> index 0b62d24b2..ef7fba700 100644
> --- a/drivers/android/binder/thread.rs
> +++ b/drivers/android/binder/thread.rs
> @@ -706,6 +706,7 @@ fn translate_object(
>                      core::mem::offset_of!(uapi::binder_fd_object, __bindgen_anon_1.fd);
>  
>                  let field_offset = offset + FD_FIELD_OFFSET;
> +                crate::trace::trace_transaction_fd_send(view.alloc.debug_id, fd, field_offset);
>  
>                  view.alloc.info_add_fd(file, field_offset, false)?;
>              }
> @@ -1323,6 +1324,7 @@ fn write(self: &Arc<Self>, req: &mut BinderWriteRead) -> Result {
>          while reader.len() >= size_of::<u32>() && self.inner.lock().return_work.is_unused() {
>              let before = reader.len();
>              let cmd = reader.read::<u32>()?;
> +            crate::trace::trace_command(cmd);
>              GLOBAL_STATS.inc_bc(cmd);
>              self.process.stats.inc_bc(cmd);
>              match cmd {
> @@ -1412,11 +1414,18 @@ fn read(self: &Arc<Self>, req: &mut BinderWriteRead, wait: bool) -> Result {
>              UserSlice::new(UserPtr::from_addr(read_start as _), read_len as _).writer(),
>              self,
>          );
> -        let (in_pool, use_proc_queue) = {
> +        let (in_pool, has_transaction, thread_todo, use_proc_queue) = {
>              let inner = self.inner.lock();
> -            (inner.is_looper(), inner.should_use_process_work_queue())
> +            (
> +                inner.is_looper(),
> +                inner.current_transaction.is_some(),
> +                !inner.work_list.is_empty(),
> +                inner.should_use_process_work_queue(),
> +            )
>          };
>  
> +        crate::trace::trace_wait_for_work(use_proc_queue, has_transaction, thread_todo);
> +
>          let getter = if use_proc_queue {
>              Self::get_work
>          } else {
> @@ -1482,6 +1491,7 @@ pub(crate) fn write_read(self: &Arc<Self>, data: UserSlice, wait: bool) -> Resul
>          let mut ret = Ok(());
>          if req.write_size > 0 {
>              ret = self.write(&mut req);
> +            crate::trace::trace_write_done(ret);
>              if let Err(err) = ret {
>                  pr_warn!(
>                      "Write failure {:?} in pid:{}",
> @@ -1498,6 +1508,7 @@ pub(crate) fn write_read(self: &Arc<Self>, data: UserSlice, wait: bool) -> Resul
>          // Go through the work queue.
>          if req.read_size > 0 {
>              ret = self.read(&mut req, wait);
> +            crate::trace::trace_read_done(ret);
>              if ret.is_err() && ret != Err(EINTR) {
>                  pr_warn!(
>                      "Read failure {:?} in pid:{}",
> diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
> index 75e6f5fba..c43846bb7 100644
> --- a/drivers/android/binder/transaction.rs
> +++ b/drivers/android/binder/transaction.rs
> @@ -430,6 +430,8 @@ fn do_work(
>  
>          self.drop_outstanding_txn();
>  
> +        crate::trace::trace_transaction_received(&self);
> +
>          // When this is not a reply and not a oneway transaction, update `current_transaction`. If
>          // it's a reply, `current_transaction` has already been updated appropriately.
>          if self.target_node.is_some() && tr_sec.transaction_data.flags & TF_ONE_WAY == 0 {
> 
> -- 
> 2.52.0
> 

      reply	other threads:[~2026-03-16 14:12 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-08  1:24 [PATCH v2 0/3] rust_binder: add and wire Binder tracepoints Mohamad Alsadhan
2026-03-08  1:24 ` [PATCH v2 1/3] rust_binder: remove "rust_" prefix from tracepoints Mohamad Alsadhan
2026-03-16 14:10   ` Alice Ryhl
2026-03-08  1:24 ` [PATCH v2 2/3] rust_binder: add Rust binder tracepoints Mohamad Alsadhan
2026-03-08  1:24 ` [PATCH v2 3/3] rust_binder: add in the new tracepoint calls Mohamad Alsadhan
2026-03-16 14:12   ` Alice Ryhl [this message]

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=abgPugGZKSCvLjFX@google.com \
    --to=aliceryhl@google.com \
    --cc='@google.com \
    --cc=a.hindborg@kernel.org \
    --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=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=mo@sdhn.cc \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tkjos@android.com \
    --cc=tmgross@umich.edu \
    /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