[PATCH 3/3] rust_binder: consolidate transaction failure prints
From: Alice Ryhl
Date: Wed Oct 07 2026 - 10:34:34 EST
When a transaction fails, it currently hits multiple print statements
meaning that a single failure can result in several lines in the kernel
log. This is unnecessary, so consolidate them into one print used for
all transaction failures.
Acked-by: Carlos Llamas <cmllamas@xxxxxxxxxx>
Signed-off-by: Alice Ryhl <aliceryhl@xxxxxxxxxx>
---
drivers/android/binder/error.rs | 4 --
drivers/android/binder/thread.rs | 72 +++++++++++++++--------------------
drivers/android/binder/transaction.rs | 20 ++--------
3 files changed, 34 insertions(+), 62 deletions(-)
diff --git a/drivers/android/binder/error.rs b/drivers/android/binder/error.rs
index 41b07d687b30..89077c5baeaf 100644
--- a/drivers/android/binder/error.rs
+++ b/drivers/android/binder/error.rs
@@ -71,10 +71,6 @@ pub(crate) fn new_frozen_oneway() -> Self {
line: ErrorLocation::caller(),
}
}
-
- pub(crate) fn is_dead(&self) -> bool {
- self.reply == BR_DEAD_REPLY
- }
}
/// Convert an errno into a `BinderError` and store the errno used to construct it. The errno
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 5bb7ae2f7920..bcb2038b7550 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -1065,17 +1065,7 @@ pub(crate) fn copy_transaction_data(
size_of::<u64>(),
);
let secctx_off = aligned_data_size + offsets_size + buffers_size;
- let mut alloc = match to_process.buffer_alloc(debug_id, len, info) {
- Ok(alloc) => alloc,
- Err(err) => {
- pr_warn!(
- "Failed to allocate buffer. len:{}, is_oneway:{}",
- len,
- info.is_oneway(),
- );
- return Err(err);
- }
- };
+ let mut alloc = to_process.buffer_alloc(debug_id, len, info)?;
trace_transaction_alloc_buf(debug_id, data_size, offsets_size, buffers_size);
@@ -1328,6 +1318,9 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
self.transaction_inner(&mut info)
};
+ // This runs when return work is passed to the caller. This is not
+ // always the same as the transaction failing, as reply errors are
+ // delivered to the remote process.
if let Err(err) = ret {
self.push_return_work(err.reply);
if err.reply != BR_TRANSACTION_COMPLETE {
@@ -1336,30 +1329,8 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
if let Some(source) = err.source {
info.errno = Some(source);
- {
- let mut inner = self.inner.lock();
- inner.extended_error =
- ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
- }
-
- binder_debug!(
- FailedTransaction,
- "transaction {} to {}:{} failed {:?}, code {} size {}-{} line {}",
- if info.is_reply {
- "reply"
- } else if info.is_oneway() {
- "async"
- } else {
- "call"
- },
- info.to_pid,
- info.to_tid,
- err,
- info.code,
- info.data_size,
- info.offsets_size,
- err.line
- );
+ self.inner.lock().extended_error =
+ ExtendedError::new(info.debug_id as u32, err.reply, source.to_errno());
}
}
}
@@ -1371,8 +1342,33 @@ fn transaction(self: &Arc<Self>, cmd: u32, reader: &mut UserSliceReader) -> Resu
// useful in case the transaction failed with BR_TRANSACTION_PENDING_FROZEN.
info.report_netlink(BR_ONEWAY_SPAM_SUSPECT, &self.process.ctx);
}
+ // This runs when the transaction failed.
if info.reply != 0 {
info.report_netlink(info.reply, &self.process.ctx);
+ if let Some(errno) = info.errno {
+ let error_line: &dyn kernel::fmt::Display = match &info.error_line {
+ Some(line) => line,
+ None => &0,
+ };
+ binder_debug!(
+ FailedTransaction,
+ "transaction {} to {}:{} failed {:?}, code {} size {}-{} line {}",
+ if info.is_reply {
+ "reply"
+ } else if info.is_oneway() {
+ "async"
+ } else {
+ "call"
+ },
+ info.to_pid,
+ info.to_tid,
+ errno,
+ info.code,
+ info.data_size,
+ info.offsets_size,
+ error_line
+ );
+ }
}
Ok(())
@@ -1465,12 +1461,6 @@ fn reply_inner(self: &Arc<Self>, info: &mut TransactionInfo) -> BinderResult {
// At this point we only return `BR_TRANSACTION_COMPLETE` to the caller, and we must let
// the sender know that the transaction has completed (with an error in this case).
- pr_warn!(
- "{}:{} reply to {} failed: {err:?}",
- info.from_pid,
- info.from_tid,
- info.to_pid
- );
let param = err.source.as_ref().map_or(0, |e| e.to_errno());
let ee = ExtendedError::new(info.debug_id as u32, err.reply, param);
orig.from
diff --git a/drivers/android/binder/transaction.rs b/drivers/android/binder/transaction.rs
index d934c6821b15..22558bdeef16 100644
--- a/drivers/android/binder/transaction.rs
+++ b/drivers/android/binder/transaction.rs
@@ -365,21 +365,13 @@ pub(crate) fn new(
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 };
let to = node_ref.node.owner.clone();
- let mut alloc = match from.copy_transaction_data(
+ let mut alloc = from.copy_transaction_data(
to.clone(),
info,
info.debug_id,
allow_fds,
txn_security_ctx_off.as_mut(),
- ) {
- Ok(alloc) => alloc,
- Err(err) => {
- if !err.is_dead() {
- pr_warn!("Failure in copy_transaction_data: {:?}", err);
- }
- return Err(err);
- }
- };
+ )?;
if info.is_oneway() {
if from_parent.is_some() {
pr_warn!("Oneway transaction should not be in a transaction stack.");
@@ -420,13 +412,7 @@ pub(crate) fn new_reply(
allow_fds: bool,
) -> BinderResult<DLArc<Self>> {
let mut alloc =
- match from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None) {
- Ok(alloc) => alloc,
- Err(err) => {
- pr_warn!("Failure in copy_transaction_data: {:?}", err);
- return Err(err);
- }
- };
+ from.copy_transaction_data(to.clone(), info, info.debug_id, allow_fds, None)?;
if info.flags.contains(TransactionFlag::ClearBuf) {
alloc.set_info_clear_on_drop();
}
--
2.56.0.rc1.315.gc6ed9934b7-goog