]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rust_binder: add ioctl/read/write done tracepoints
authorMohamad Alsadhan <mo@sdhn.cc>
Tue, 17 Mar 2026 14:49:43 +0000 (17:49 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 1 Apr 2026 10:18:22 +0000 (12:18 +0200)
Add Rust Binder tracepoints declarations for `ioctl_done`,
`read_done` and `write_done`.

Additionally, wire in the new tracepoints into the corresponding
Binder call sites.

Note that the new tracepoints report final errno-style return values,
matching the existing C model for operation completion.

Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Link: https://patch.msgid.link/20260317-rust-binder-trace-v3-2-6fae4fbcf637@sdhn.cc
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/android/binder/process.rs
drivers/android/binder/rust_binder_events.h
drivers/android/binder/thread.rs
drivers/android/binder/trace.rs

index 312e5c3f14cd5df3881e2732bab49d02ce1bf94a..820cbd5414351d69fd967439b59c4324d1f0792e 100644 (file)
@@ -1659,11 +1659,14 @@ impl Process {
 
         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(
index e3adfb93170d20fe85137678d2b820d675d4fbe4..4fda8576c01f5b3398ff74b8ce843c138d5cd04e 100644 (file)
@@ -30,6 +30,27 @@ TRACE_EVENT(binder_ioctl,
        TP_printk("cmd=0x%x arg=0x%lx", __entry->cmd, __entry->arg)
 );
 
+DECLARE_EVENT_CLASS(binder_function_return_class,
+       TP_PROTO(int ret),
+       TP_ARGS(ret),
+       TP_STRUCT__entry(
+               __field(int, ret)
+       ),
+       TP_fast_assign(
+               __entry->ret = ret;
+       ),
+       TP_printk("ret=%d", __entry->ret)
+);
+
+#define DEFINE_RBINDER_FUNCTION_RETURN_EVENT(name)     \
+DEFINE_EVENT(binder_function_return_class, name,       \
+       TP_PROTO(int ret), \
+       TP_ARGS(ret))
+
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_ioctl_done);
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_read_done);
+DEFINE_RBINDER_FUNCTION_RETURN_EVENT(binder_write_done);
+
 TRACE_EVENT(binder_transaction,
        TP_PROTO(bool reply, rust_binder_transaction t, struct task_struct *thread),
        TP_ARGS(reply, t, thread),
index 97a5e4acf64cd3e71fa3b099184528023a77438e..138c45cecfa0ff280487e86884df601813222379 100644 (file)
@@ -1507,6 +1507,7 @@ impl Thread {
         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:{}",
@@ -1523,6 +1524,7 @@ impl Thread {
         // 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:{}",
index d54b18ab71a89e49e5c720af651c69fda79299f5..3b0458e2738cd0f64ff19ac4a50029ec942fd63c 100644 (file)
@@ -5,12 +5,16 @@
 use crate::transaction::Transaction;
 
 use kernel::bindings::{rust_binder_transaction, task_struct};
-use kernel::ffi::{c_uint, c_ulong};
+use kernel::error::Result;
+use kernel::ffi::{c_int, c_uint, c_ulong};
 use kernel::task::Task;
 use kernel::tracepoint::declare_trace;
 
 declare_trace! {
     unsafe fn binder_ioctl(cmd: c_uint, arg: c_ulong);
+    unsafe fn binder_ioctl_done(ret: c_int);
+    unsafe fn binder_read_done(ret: c_int);
+    unsafe fn binder_write_done(ret: c_int);
     unsafe fn binder_transaction(reply: bool, t: rust_binder_transaction, thread: *mut task_struct);
 }
 
@@ -19,12 +23,36 @@ fn raw_transaction(t: &Transaction) -> rust_binder_transaction {
     t as *const Transaction as rust_binder_transaction
 }
 
+#[inline]
+fn to_errno(ret: Result) -> i32 {
+    match ret {
+        Ok(()) => 0,
+        Err(err) => err.to_errno(),
+    }
+}
+
 #[inline]
 pub(crate) fn trace_ioctl(cmd: u32, arg: usize) {
     // SAFETY: Always safe to call.
     unsafe { binder_ioctl(cmd, arg as c_ulong) }
 }
 
+#[inline]
+pub(crate) fn trace_ioctl_done(ret: Result) {
+    // SAFETY: Always safe to call.
+    unsafe { binder_ioctl_done(to_errno(ret)) }
+}
+#[inline]
+pub(crate) fn trace_read_done(ret: Result) {
+    // SAFETY: Always safe to call.
+    unsafe { binder_read_done(to_errno(ret)) }
+}
+#[inline]
+pub(crate) fn trace_write_done(ret: Result) {
+    // SAFETY: Always safe to call.
+    unsafe { binder_write_done(to_errno(ret)) }
+}
+
 #[inline]
 pub(crate) fn trace_transaction(reply: bool, t: &Transaction, thread: Option<&Task>) {
     let thread = match thread {