mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-05 19:31:57 -04:00
Merge android11-5.4 into android11-5.4-lts
This merges the android11-5.4 branch into the -lts branch, catching it up with the latest changes in there. It contains the following commits: *3d01868604Merge tag 'android11-5.4.294_r00' into android11-5.4 *45cc71553dBACKPORT: binder: Create safe versions of binder log files *e85fa50159UPSTREAM: binder: Refactor binder_node print synchronization Change-Id: I1407c91e71752fcd23d93aff6b5f68a45dc11a25 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
commit
b3fbf76488
3 changed files with 153 additions and 69 deletions
|
|
@ -6337,10 +6337,10 @@ static void print_binder_transaction_ilocked(struct seq_file *m,
|
|||
}
|
||||
|
||||
static void print_binder_work_ilocked(struct seq_file *m,
|
||||
struct binder_proc *proc,
|
||||
const char *prefix,
|
||||
const char *transaction_prefix,
|
||||
struct binder_work *w)
|
||||
struct binder_proc *proc,
|
||||
const char *prefix,
|
||||
const char *transaction_prefix,
|
||||
struct binder_work *w, bool hash_ptrs)
|
||||
{
|
||||
struct binder_node *node;
|
||||
struct binder_transaction *t;
|
||||
|
|
@ -6363,9 +6363,15 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
|||
break;
|
||||
case BINDER_WORK_NODE:
|
||||
node = container_of(w, struct binder_node, work);
|
||||
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
|
||||
prefix, node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
if (hash_ptrs)
|
||||
seq_printf(m, "%snode work %d: u%p c%p\n",
|
||||
prefix, node->debug_id,
|
||||
(void *)(long)node->ptr,
|
||||
(void *)(long)node->cookie);
|
||||
else
|
||||
seq_printf(m, "%snode work %d: u%016llx c%016llx\n",
|
||||
prefix, node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
break;
|
||||
case BINDER_WORK_DEAD_BINDER:
|
||||
seq_printf(m, "%shas dead binder\n", prefix);
|
||||
|
|
@ -6390,7 +6396,7 @@ static void print_binder_work_ilocked(struct seq_file *m,
|
|||
|
||||
static void print_binder_thread_ilocked(struct seq_file *m,
|
||||
struct binder_thread *thread,
|
||||
int print_always)
|
||||
bool print_always, bool hash_ptrs)
|
||||
{
|
||||
struct binder_transaction *t;
|
||||
struct binder_work *w;
|
||||
|
|
@ -6420,14 +6426,16 @@ static void print_binder_thread_ilocked(struct seq_file *m,
|
|||
}
|
||||
list_for_each_entry(w, &thread->todo, entry) {
|
||||
print_binder_work_ilocked(m, thread->proc, " ",
|
||||
" pending transaction", w);
|
||||
" pending transaction",
|
||||
w, hash_ptrs);
|
||||
}
|
||||
if (!print_always && m->count == header_pos)
|
||||
m->count = start_pos;
|
||||
}
|
||||
|
||||
static void print_binder_node_nilocked(struct seq_file *m,
|
||||
struct binder_node *node)
|
||||
struct binder_node *node,
|
||||
bool hash_ptrs)
|
||||
{
|
||||
struct binder_ref *ref;
|
||||
struct binder_work *w;
|
||||
|
|
@ -6437,8 +6445,13 @@ static void print_binder_node_nilocked(struct seq_file *m,
|
|||
hlist_for_each_entry(ref, &node->refs, node_entry)
|
||||
count++;
|
||||
|
||||
seq_printf(m, " node %d: u%016llx c%016llx pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d",
|
||||
node->debug_id, (u64)node->ptr, (u64)node->cookie,
|
||||
if (hash_ptrs)
|
||||
seq_printf(m, " node %d: u%p c%p", node->debug_id,
|
||||
(void *)(long)node->ptr, (void *)(long)node->cookie);
|
||||
else
|
||||
seq_printf(m, " node %d: u%016llx c%016llx", node->debug_id,
|
||||
(u64)node->ptr, (u64)node->cookie);
|
||||
seq_printf(m, " pri %d:%d hs %d hw %d ls %d lw %d is %d iw %d tr %d",
|
||||
node->sched_policy, node->min_priority,
|
||||
node->has_strong_ref, node->has_weak_ref,
|
||||
node->local_strong_refs, node->local_weak_refs,
|
||||
|
|
@ -6452,7 +6465,8 @@ static void print_binder_node_nilocked(struct seq_file *m,
|
|||
if (node->proc) {
|
||||
list_for_each_entry(w, &node->async_todo, entry)
|
||||
print_binder_work_ilocked(m, node->proc, " ",
|
||||
" pending async transaction", w);
|
||||
" pending async transaction",
|
||||
w, hash_ptrs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6468,8 +6482,54 @@ static void print_binder_ref_olocked(struct seq_file *m,
|
|||
binder_node_unlock(ref->node);
|
||||
}
|
||||
|
||||
static void print_binder_proc(struct seq_file *m,
|
||||
struct binder_proc *proc, int print_all)
|
||||
/**
|
||||
* print_next_binder_node_ilocked() - Print binder_node from a locked list
|
||||
* @m: struct seq_file for output via seq_printf()
|
||||
* @proc: struct binder_proc we hold the inner_proc_lock to (if any)
|
||||
* @node: struct binder_node to print fields of
|
||||
* @prev_node: struct binder_node we hold a temporary reference to (if any)
|
||||
* @hash_ptrs: whether to hash @node's binder_uintptr_t fields
|
||||
*
|
||||
* Helper function to handle synchronization around printing a struct
|
||||
* binder_node while iterating through @proc->nodes or the dead nodes list.
|
||||
* Caller must hold either @proc->inner_lock (for live nodes) or
|
||||
* binder_dead_nodes_lock. This lock will be released during the body of this
|
||||
* function, but it will be reacquired before returning to the caller.
|
||||
*
|
||||
* Return: pointer to the struct binder_node we hold a tmpref on
|
||||
*/
|
||||
static struct binder_node *
|
||||
print_next_binder_node_ilocked(struct seq_file *m, struct binder_proc *proc,
|
||||
struct binder_node *node,
|
||||
struct binder_node *prev_node, bool hash_ptrs)
|
||||
{
|
||||
/*
|
||||
* Take a temporary reference on the node so that isn't freed while
|
||||
* we print it.
|
||||
*/
|
||||
binder_inc_node_tmpref_ilocked(node);
|
||||
/*
|
||||
* Live nodes need to drop the inner proc lock and dead nodes need to
|
||||
* drop the binder_dead_nodes_lock before trying to take the node lock.
|
||||
*/
|
||||
if (proc)
|
||||
binder_inner_proc_unlock(proc);
|
||||
else
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (prev_node)
|
||||
binder_put_node(prev_node);
|
||||
binder_node_inner_lock(node);
|
||||
print_binder_node_nilocked(m, node, hash_ptrs);
|
||||
binder_node_inner_unlock(node);
|
||||
if (proc)
|
||||
binder_inner_proc_lock(proc);
|
||||
else
|
||||
spin_lock(&binder_dead_nodes_lock);
|
||||
return node;
|
||||
}
|
||||
|
||||
static void print_binder_proc(struct seq_file *m, struct binder_proc *proc,
|
||||
bool print_all, bool hash_ptrs)
|
||||
{
|
||||
struct binder_work *w;
|
||||
struct rb_node *n;
|
||||
|
|
@ -6482,31 +6542,19 @@ static void print_binder_proc(struct seq_file *m,
|
|||
header_pos = m->count;
|
||||
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->threads); n; n = rb_next(n))
|
||||
print_binder_thread_ilocked(m, rb_entry(n, struct binder_thread,
|
||||
rb_node), print_all);
|
||||
rb_node), print_all, hash_ptrs);
|
||||
|
||||
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) {
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n)) {
|
||||
struct binder_node *node = rb_entry(n, struct binder_node,
|
||||
rb_node);
|
||||
if (!print_all && !node->has_async_transaction)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* take a temporary reference on the node so it
|
||||
* survives and isn't removed from the tree
|
||||
* while we print it.
|
||||
*/
|
||||
binder_inc_node_tmpref_ilocked(node);
|
||||
/* Need to drop inner lock to take node lock */
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
binder_node_inner_lock(node);
|
||||
print_binder_node_nilocked(m, node);
|
||||
binder_node_inner_unlock(node);
|
||||
last_node = node;
|
||||
binder_inner_proc_lock(proc);
|
||||
last_node = print_next_binder_node_ilocked(m, proc, node,
|
||||
last_node,
|
||||
hash_ptrs);
|
||||
}
|
||||
binder_inner_proc_unlock(proc);
|
||||
if (last_node)
|
||||
|
|
@ -6514,19 +6562,18 @@ static void print_binder_proc(struct seq_file *m,
|
|||
|
||||
if (print_all) {
|
||||
binder_proc_lock(proc);
|
||||
for (n = rb_first(&proc->refs_by_desc);
|
||||
n != NULL;
|
||||
n = rb_next(n))
|
||||
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n))
|
||||
print_binder_ref_olocked(m, rb_entry(n,
|
||||
struct binder_ref,
|
||||
rb_node_desc));
|
||||
struct binder_ref,
|
||||
rb_node_desc));
|
||||
binder_proc_unlock(proc);
|
||||
}
|
||||
binder_alloc_print_allocated(m, &proc->alloc);
|
||||
binder_inner_proc_lock(proc);
|
||||
list_for_each_entry(w, &proc->todo, entry)
|
||||
print_binder_work_ilocked(m, proc, " ",
|
||||
" pending transaction", w);
|
||||
" pending transaction", w,
|
||||
hash_ptrs);
|
||||
list_for_each_entry(w, &proc->delivered_death, entry) {
|
||||
seq_puts(m, " has delivered dead binder\n");
|
||||
break;
|
||||
|
|
@ -6652,7 +6699,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
count = 0;
|
||||
ready_threads = 0;
|
||||
binder_inner_proc_lock(proc);
|
||||
for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->threads); n; n = rb_next(n))
|
||||
count++;
|
||||
|
||||
list_for_each_entry(thread, &proc->waiting_threads, waiting_thread_node)
|
||||
|
|
@ -6666,7 +6713,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
ready_threads,
|
||||
free_async_space);
|
||||
count = 0;
|
||||
for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n))
|
||||
for (n = rb_first(&proc->nodes); n; n = rb_next(n))
|
||||
count++;
|
||||
binder_inner_proc_unlock(proc);
|
||||
seq_printf(m, " nodes: %d\n", count);
|
||||
|
|
@ -6674,7 +6721,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
strong = 0;
|
||||
weak = 0;
|
||||
binder_proc_lock(proc);
|
||||
for (n = rb_first(&proc->refs_by_desc); n != NULL; n = rb_next(n)) {
|
||||
for (n = rb_first(&proc->refs_by_desc); n; n = rb_next(n)) {
|
||||
struct binder_ref *ref = rb_entry(n, struct binder_ref,
|
||||
rb_node_desc);
|
||||
count++;
|
||||
|
|
@ -6701,8 +6748,7 @@ static void print_binder_proc_stats(struct seq_file *m,
|
|||
print_binder_stats(m, " ", &proc->stats);
|
||||
}
|
||||
|
||||
|
||||
int binder_state_show(struct seq_file *m, void *unused)
|
||||
static void print_binder_state(struct seq_file *m, bool hash_ptrs)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
struct binder_node *node;
|
||||
|
|
@ -6713,31 +6759,40 @@ int binder_state_show(struct seq_file *m, void *unused)
|
|||
spin_lock(&binder_dead_nodes_lock);
|
||||
if (!hlist_empty(&binder_dead_nodes))
|
||||
seq_puts(m, "dead nodes:\n");
|
||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node) {
|
||||
/*
|
||||
* take a temporary reference on the node so it
|
||||
* survives and isn't removed from the list
|
||||
* while we print it.
|
||||
*/
|
||||
node->tmp_refs++;
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
binder_node_lock(node);
|
||||
print_binder_node_nilocked(m, node);
|
||||
binder_node_unlock(node);
|
||||
last_node = node;
|
||||
spin_lock(&binder_dead_nodes_lock);
|
||||
}
|
||||
hlist_for_each_entry(node, &binder_dead_nodes, dead_node)
|
||||
last_node = print_next_binder_node_ilocked(m, NULL, node,
|
||||
last_node,
|
||||
hash_ptrs);
|
||||
spin_unlock(&binder_dead_nodes_lock);
|
||||
if (last_node)
|
||||
binder_put_node(last_node);
|
||||
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, 1);
|
||||
print_binder_proc(m, proc, true, hash_ptrs);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
}
|
||||
|
||||
static void print_binder_transactions(struct seq_file *m, bool hash_ptrs)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
|
||||
seq_puts(m, "binder transactions:\n");
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, false, hash_ptrs);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
}
|
||||
|
||||
int binder_state_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_state(m, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int binder_state_hashed_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_state(m, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -6759,14 +6814,13 @@ int binder_stats_show(struct seq_file *m, void *unused)
|
|||
|
||||
int binder_transactions_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
struct binder_proc *proc;
|
||||
|
||||
seq_puts(m, "binder transactions:\n");
|
||||
mutex_lock(&binder_procs_lock);
|
||||
hlist_for_each_entry(proc, &binder_procs, proc_node)
|
||||
print_binder_proc(m, proc, 0);
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
print_binder_transactions(m, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int binder_transactions_hashed_show(struct seq_file *m, void *unused)
|
||||
{
|
||||
print_binder_transactions(m, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -6779,7 +6833,7 @@ static int proc_show(struct seq_file *m, void *unused)
|
|||
hlist_for_each_entry(itr, &binder_procs, proc_node) {
|
||||
if (itr->pid == pid) {
|
||||
seq_puts(m, "binder proc state:\n");
|
||||
print_binder_proc(m, itr, 1);
|
||||
print_binder_proc(m, itr, true, false);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&binder_procs_lock);
|
||||
|
|
@ -6900,6 +6954,11 @@ static int __init binder_init(void)
|
|||
binder_debugfs_dir_entry_root,
|
||||
NULL,
|
||||
&binder_state_fops);
|
||||
debugfs_create_file("state_hashed",
|
||||
0444,
|
||||
binder_debugfs_dir_entry_root,
|
||||
NULL,
|
||||
&binder_state_hashed_fops);
|
||||
debugfs_create_file("stats",
|
||||
0444,
|
||||
binder_debugfs_dir_entry_root,
|
||||
|
|
@ -6910,6 +6969,11 @@ static int __init binder_init(void)
|
|||
binder_debugfs_dir_entry_root,
|
||||
NULL,
|
||||
&binder_transactions_fops);
|
||||
debugfs_create_file("transactions_hashed",
|
||||
0444,
|
||||
binder_debugfs_dir_entry_root,
|
||||
NULL,
|
||||
&binder_transactions_hashed_fops);
|
||||
debugfs_create_file("transaction_log",
|
||||
0444,
|
||||
binder_debugfs_dir_entry_root,
|
||||
|
|
|
|||
|
|
@ -113,9 +113,15 @@ DEFINE_SHOW_ATTRIBUTE(binder_stats);
|
|||
int binder_state_show(struct seq_file *m, void *unused);
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_state);
|
||||
|
||||
int binder_state_hashed_show(struct seq_file *m, void *unused);
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_state_hashed);
|
||||
|
||||
int binder_transactions_show(struct seq_file *m, void *unused);
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_transactions);
|
||||
|
||||
int binder_transactions_hashed_show(struct seq_file *m, void *unused);
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_transactions_hashed);
|
||||
|
||||
int binder_transaction_log_show(struct seq_file *m, void *unused);
|
||||
DEFINE_SHOW_ATTRIBUTE(binder_transaction_log);
|
||||
|
||||
|
|
|
|||
|
|
@ -659,6 +659,13 @@ static int init_binder_logs(struct super_block *sb)
|
|||
goto out;
|
||||
}
|
||||
|
||||
dentry = binderfs_create_file(binder_logs_root_dir, "state_hashed",
|
||||
&binder_state_hashed_fops, NULL);
|
||||
if (IS_ERR(dentry)) {
|
||||
ret = PTR_ERR(dentry);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dentry = binderfs_create_file(binder_logs_root_dir, "transactions",
|
||||
&binder_transactions_fops, NULL);
|
||||
if (IS_ERR(dentry)) {
|
||||
|
|
@ -666,6 +673,13 @@ static int init_binder_logs(struct super_block *sb)
|
|||
goto out;
|
||||
}
|
||||
|
||||
dentry = binderfs_create_file(binder_logs_root_dir, "transactions_hashed",
|
||||
&binder_transactions_hashed_fops, NULL);
|
||||
if (IS_ERR(dentry)) {
|
||||
ret = PTR_ERR(dentry);
|
||||
goto out;
|
||||
}
|
||||
|
||||
dentry = binderfs_create_file(binder_logs_root_dir,
|
||||
"transaction_log",
|
||||
&binder_transaction_log_fops,
|
||||
|
|
|
|||
Loading…
Reference in a new issue