| From 5249f4883045de494916db7b1a6d6e1e422e9a0b Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= <arve@android.com> |
| Date: Tue, 28 Apr 2009 20:57:50 -0700 |
| Subject: binder: Use seq_file for debug interface. |
| MIME-Version: 1.0 |
| Content-Type: text/plain; charset=UTF-8 |
| Content-Transfer-Encoding: 8bit |
| Patch-mainline: HEAD |
| Git-commit: 5249f4883045de494916db7b1a6d6e1e422e9a0b |
| |
| Signed-off-by: Arve Hjønnevåg <arve@android.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c |
| index 3aec4530..371232b 100644 |
| --- a/drivers/staging/android/binder.c |
| +++ b/drivers/staging/android/binder.c |
| @@ -29,6 +29,7 @@ |
| #include <linux/proc_fs.h> |
| #include <linux/rbtree.h> |
| #include <linux/sched.h> |
| +#include <linux/seq_file.h> |
| #include <linux/uaccess.h> |
| #include <linux/vmalloc.h> |
| #include <linux/slab.h> |
| @@ -48,8 +49,22 @@ static struct binder_node *binder_context_mgr_node; |
| static uid_t binder_context_mgr_uid = -1; |
| static int binder_last_id; |
| |
| -static int binder_read_proc_proc(char *page, char **start, off_t off, |
| - int count, int *eof, void *data); |
| +#define BINDER_DEBUG_ENTRY(name) \ |
| +static int binder_##name##_open(struct inode *inode, struct file *file) \ |
| +{ \ |
| + return single_open(file, binder_##name##_show, PDE(inode)->data); \ |
| +} \ |
| +\ |
| +static const struct file_operations binder_##name##_fops = { \ |
| + .owner = THIS_MODULE, \ |
| + .open = binder_##name##_open, \ |
| + .read = seq_read, \ |
| + .llseek = seq_lseek, \ |
| + .release = single_release, \ |
| +} |
| + |
| +static int binder_proc_show(struct seq_file *m, void *unused); |
| +BINDER_DEBUG_ENTRY(proc); |
| |
| /* This is only defined in include/asm-arm/sizes.h */ |
| #ifndef SZ_1K |
| @@ -2880,9 +2895,9 @@ static int binder_open(struct inode *nodp, struct file *filp) |
| char strbuf[11]; |
| snprintf(strbuf, sizeof(strbuf), "%u", proc->pid); |
| remove_proc_entry(strbuf, binder_proc_dir_entry_proc); |
| - create_proc_read_entry(strbuf, S_IRUGO, |
| - binder_proc_dir_entry_proc, |
| - binder_read_proc_proc, proc); |
| + proc_create_data(strbuf, S_IRUGO, |
| + binder_proc_dir_entry_proc, |
| + &binder_proc_fops, proc); |
| } |
| |
| return 0; |
| @@ -3105,49 +3120,41 @@ binder_defer_work(struct binder_proc *proc, enum binder_deferred_state defer) |
| mutex_unlock(&binder_deferred_lock); |
| } |
| |
| -static char *print_binder_transaction(char *buf, char *end, const char *prefix, |
| - struct binder_transaction *t) |
| -{ |
| - buf += snprintf(buf, end - buf, |
| - "%s %d: %p from %d:%d to %d:%d code %x " |
| - "flags %x pri %ld r%d", |
| - prefix, t->debug_id, t, |
| - t->from ? t->from->proc->pid : 0, |
| - t->from ? t->from->pid : 0, |
| - t->to_proc ? t->to_proc->pid : 0, |
| - t->to_thread ? t->to_thread->pid : 0, |
| - t->code, t->flags, t->priority, t->need_reply); |
| - if (buf >= end) |
| - return buf; |
| +static void print_binder_transaction(struct seq_file *m, const char *prefix, |
| + struct binder_transaction *t) |
| +{ |
| + seq_printf(m, |
| + "%s %d: %p from %d:%d to %d:%d code %x flags %x pri %ld r%d", |
| + prefix, t->debug_id, t, |
| + t->from ? t->from->proc->pid : 0, |
| + t->from ? t->from->pid : 0, |
| + t->to_proc ? t->to_proc->pid : 0, |
| + t->to_thread ? t->to_thread->pid : 0, |
| + t->code, t->flags, t->priority, t->need_reply); |
| if (t->buffer == NULL) { |
| - buf += snprintf(buf, end - buf, " buffer free\n"); |
| - return buf; |
| - } |
| - if (t->buffer->target_node) { |
| - buf += snprintf(buf, end - buf, " node %d", |
| - t->buffer->target_node->debug_id); |
| - if (buf >= end) |
| - return buf; |
| + seq_puts(m, " buffer free\n"); |
| + return; |
| } |
| - buf += snprintf(buf, end - buf, " size %zd:%zd data %p\n", |
| - t->buffer->data_size, t->buffer->offsets_size, |
| - t->buffer->data); |
| - return buf; |
| + if (t->buffer->target_node) |
| + seq_printf(m, " node %d", |
| + t->buffer->target_node->debug_id); |
| + seq_printf(m, " size %zd:%zd data %p\n", |
| + t->buffer->data_size, t->buffer->offsets_size, |
| + t->buffer->data); |
| } |
| |
| -static char *print_binder_buffer(char *buf, char *end, const char *prefix, |
| - struct binder_buffer *buffer) |
| +static void print_binder_buffer(struct seq_file *m, const char *prefix, |
| + struct binder_buffer *buffer) |
| { |
| - buf += snprintf(buf, end - buf, "%s %d: %p size %zd:%zd %s\n", |
| - prefix, buffer->debug_id, buffer->data, |
| - buffer->data_size, buffer->offsets_size, |
| - buffer->transaction ? "active" : "delivered"); |
| - return buf; |
| + seq_printf(m, "%s %d: %p size %zd:%zd %s\n", |
| + prefix, buffer->debug_id, buffer->data, |
| + buffer->data_size, buffer->offsets_size, |
| + buffer->transaction ? "active" : "delivered"); |
| } |
| |
| -static char *print_binder_work(char *buf, char *end, const char *prefix, |
| - const char *transaction_prefix, |
| - struct binder_work *w) |
| +static void print_binder_work(struct seq_file *m, const char *prefix, |
| + const char *transaction_prefix, |
| + struct binder_work *w) |
| { |
| struct binder_node *node; |
| struct binder_transaction *t; |
| @@ -3155,79 +3162,65 @@ static char *print_binder_work(char *buf, char *end, const char *prefix, |
| switch (w->type) { |
| case BINDER_WORK_TRANSACTION: |
| t = container_of(w, struct binder_transaction, work); |
| - buf = print_binder_transaction(buf, end, transaction_prefix, t); |
| + print_binder_transaction(m, transaction_prefix, t); |
| break; |
| case BINDER_WORK_TRANSACTION_COMPLETE: |
| - buf += snprintf(buf, end - buf, |
| - "%stransaction complete\n", prefix); |
| + seq_printf(m, "%stransaction complete\n", prefix); |
| break; |
| case BINDER_WORK_NODE: |
| node = container_of(w, struct binder_node, work); |
| - buf += snprintf(buf, end - buf, "%snode work %d: u%p c%p\n", |
| - prefix, node->debug_id, node->ptr, |
| - node->cookie); |
| + seq_printf(m, "%snode work %d: u%p c%p\n", |
| + prefix, node->debug_id, node->ptr, node->cookie); |
| break; |
| case BINDER_WORK_DEAD_BINDER: |
| - buf += snprintf(buf, end - buf, "%shas dead binder\n", prefix); |
| + seq_printf(m, "%shas dead binder\n", prefix); |
| break; |
| case BINDER_WORK_DEAD_BINDER_AND_CLEAR: |
| - buf += snprintf(buf, end - buf, |
| - "%shas cleared dead binder\n", prefix); |
| + seq_printf(m, "%shas cleared dead binder\n", prefix); |
| break; |
| case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: |
| - buf += snprintf(buf, end - buf, |
| - "%shas cleared death notification\n", prefix); |
| + seq_printf(m, "%shas cleared death notification\n", prefix); |
| break; |
| default: |
| - buf += snprintf(buf, end - buf, "%sunknown work: type %d\n", |
| - prefix, w->type); |
| + seq_printf(m, "%sunknown work: type %d\n", prefix, w->type); |
| break; |
| } |
| - return buf; |
| } |
| |
| -static char *print_binder_thread(char *buf, char *end, |
| - struct binder_thread *thread, |
| - int print_always) |
| +static void print_binder_thread(struct seq_file *m, |
| + struct binder_thread *thread, |
| + int print_always) |
| { |
| struct binder_transaction *t; |
| struct binder_work *w; |
| - char *start_buf = buf; |
| - char *header_buf; |
| + size_t start_pos = m->count; |
| + size_t header_pos; |
| |
| - buf += snprintf(buf, end - buf, " thread %d: l %02x\n", |
| - thread->pid, thread->looper); |
| - header_buf = buf; |
| + seq_printf(m, " thread %d: l %02x\n", thread->pid, thread->looper); |
| + header_pos = m->count; |
| t = thread->transaction_stack; |
| while (t) { |
| - if (buf >= end) |
| - break; |
| if (t->from == thread) { |
| - buf = print_binder_transaction(buf, end, |
| - " outgoing transaction", t); |
| + print_binder_transaction(m, |
| + " outgoing transaction", t); |
| t = t->from_parent; |
| } else if (t->to_thread == thread) { |
| - buf = print_binder_transaction(buf, end, |
| - " incoming transaction", t); |
| + print_binder_transaction(m, |
| + " incoming transaction", t); |
| t = t->to_parent; |
| } else { |
| - buf = print_binder_transaction(buf, end, |
| - " bad transaction", t); |
| + print_binder_transaction(m, " bad transaction", t); |
| t = NULL; |
| } |
| } |
| list_for_each_entry(w, &thread->todo, entry) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_work(buf, end, " ", |
| - " pending transaction", w); |
| + print_binder_work(m, " ", " pending transaction", w); |
| } |
| - if (!print_always && buf == header_buf) |
| - buf = start_buf; |
| - return buf; |
| + if (!print_always && m->count == header_pos) |
| + m->count = start_pos; |
| } |
| |
| -static char *print_binder_node(char *buf, char *end, struct binder_node *node) |
| +static void print_binder_node(struct seq_file *m, struct binder_node *node) |
| { |
| struct binder_ref *ref; |
| struct hlist_node *pos; |
| @@ -3238,100 +3231,67 @@ static char *print_binder_node(char *buf, char *end, struct binder_node *node) |
| hlist_for_each_entry(ref, pos, &node->refs, node_entry) |
| count++; |
| |
| - buf += snprintf(buf, end - buf, |
| - " node %d: u%p c%p hs %d hw %d ls %d lw %d " |
| - "is %d iw %d", |
| - node->debug_id, node->ptr, node->cookie, |
| - node->has_strong_ref, node->has_weak_ref, |
| - node->local_strong_refs, node->local_weak_refs, |
| - node->internal_strong_refs, count); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, " node %d: u%p c%p hs %d hw %d ls %d lw %d is %d iw %d", |
| + node->debug_id, node->ptr, node->cookie, |
| + node->has_strong_ref, node->has_weak_ref, |
| + node->local_strong_refs, node->local_weak_refs, |
| + node->internal_strong_refs, count); |
| if (count) { |
| - buf += snprintf(buf, end - buf, " proc"); |
| - if (buf >= end) |
| - return buf; |
| - hlist_for_each_entry(ref, pos, &node->refs, node_entry) { |
| - buf += snprintf(buf, end - buf, " %d", ref->proc->pid); |
| - if (buf >= end) |
| - return buf; |
| - } |
| + seq_puts(m, " proc"); |
| + hlist_for_each_entry(ref, pos, &node->refs, node_entry) |
| + seq_printf(m, " %d", ref->proc->pid); |
| } |
| - buf += snprintf(buf, end - buf, "\n"); |
| - list_for_each_entry(w, &node->async_todo, entry) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_work(buf, end, " ", |
| - " pending async transaction", w); |
| - } |
| - return buf; |
| + seq_puts(m, "\n"); |
| + list_for_each_entry(w, &node->async_todo, entry) |
| + print_binder_work(m, " ", |
| + " pending async transaction", w); |
| } |
| |
| -static char *print_binder_ref(char *buf, char *end, struct binder_ref *ref) |
| +static void print_binder_ref(struct seq_file *m, struct binder_ref *ref) |
| { |
| - buf += snprintf(buf, end - buf, |
| - " ref %d: desc %d %snode %d s %d w %d d %p\n", |
| - ref->debug_id, ref->desc, |
| - ref->node->proc ? "" : "dead ", ref->node->debug_id, |
| - ref->strong, ref->weak, ref->death); |
| - return buf; |
| + seq_printf(m, " ref %d: desc %d %snode %d s %d w %d d %p\n", |
| + ref->debug_id, ref->desc, ref->node->proc ? "" : "dead ", |
| + ref->node->debug_id, ref->strong, ref->weak, ref->death); |
| } |
| |
| -static char *print_binder_proc(char *buf, char *end, |
| - struct binder_proc *proc, int print_all) |
| +static void print_binder_proc(struct seq_file *m, |
| + struct binder_proc *proc, int print_all) |
| { |
| struct binder_work *w; |
| struct rb_node *n; |
| - char *start_buf = buf; |
| - char *header_buf; |
| - |
| - buf += snprintf(buf, end - buf, "proc %d\n", proc->pid); |
| - header_buf = buf; |
| - |
| - for (n = rb_first(&proc->threads); |
| - n != NULL && buf < end; |
| - n = rb_next(n)) |
| - buf = print_binder_thread(buf, end, |
| - rb_entry(n, struct binder_thread, |
| - rb_node), print_all); |
| - for (n = rb_first(&proc->nodes); |
| - n != NULL && buf < end; |
| - n = rb_next(n)) { |
| + size_t start_pos = m->count; |
| + size_t header_pos; |
| + |
| + seq_printf(m, "proc %d\n", proc->pid); |
| + header_pos = m->count; |
| + |
| + for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) |
| + print_binder_thread(m, rb_entry(n, struct binder_thread, |
| + rb_node), print_all); |
| + for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) { |
| struct binder_node *node = rb_entry(n, struct binder_node, |
| rb_node); |
| if (print_all || node->has_async_transaction) |
| - buf = print_binder_node(buf, end, node); |
| + print_binder_node(m, node); |
| } |
| if (print_all) { |
| for (n = rb_first(&proc->refs_by_desc); |
| - n != NULL && buf < end; |
| + n != NULL; |
| n = rb_next(n)) |
| - buf = print_binder_ref(buf, end, |
| - rb_entry(n, struct binder_ref, |
| - rb_node_desc)); |
| - } |
| - for (n = rb_first(&proc->allocated_buffers); |
| - n != NULL && buf < end; |
| - n = rb_next(n)) |
| - buf = print_binder_buffer(buf, end, " buffer", |
| - rb_entry(n, struct binder_buffer, |
| - rb_node)); |
| - list_for_each_entry(w, &proc->todo, entry) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_work(buf, end, " ", |
| - " pending transaction", w); |
| + print_binder_ref(m, rb_entry(n, struct binder_ref, |
| + rb_node_desc)); |
| } |
| + for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n)) |
| + print_binder_buffer(m, " buffer", |
| + rb_entry(n, struct binder_buffer, rb_node)); |
| + list_for_each_entry(w, &proc->todo, entry) |
| + print_binder_work(m, " ", " pending transaction", w); |
| list_for_each_entry(w, &proc->delivered_death, entry) { |
| - if (buf >= end) |
| - break; |
| - buf += snprintf(buf, end - buf, |
| - " has delivered dead binder\n"); |
| + seq_puts(m, " has delivered dead binder\n"); |
| break; |
| } |
| - if (!print_all && buf == header_buf) |
| - buf = start_buf; |
| - return buf; |
| + if (!print_all && m->count == header_pos) |
| + m->count = start_pos; |
| } |
| |
| static const char *binder_return_strings[] = { |
| @@ -3385,79 +3345,61 @@ static const char *binder_objstat_strings[] = { |
| "transaction_complete" |
| }; |
| |
| -static char *print_binder_stats(char *buf, char *end, const char *prefix, |
| - struct binder_stats *stats) |
| +static void print_binder_stats(struct seq_file *m, const char *prefix, |
| + struct binder_stats *stats) |
| { |
| int i; |
| |
| BUILD_BUG_ON(ARRAY_SIZE(stats->bc) != |
| - ARRAY_SIZE(binder_command_strings)); |
| + ARRAY_SIZE(binder_command_strings)); |
| for (i = 0; i < ARRAY_SIZE(stats->bc); i++) { |
| if (stats->bc[i]) |
| - buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix, |
| - binder_command_strings[i], |
| - stats->bc[i]); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, "%s%s: %d\n", prefix, |
| + binder_command_strings[i], stats->bc[i]); |
| } |
| |
| BUILD_BUG_ON(ARRAY_SIZE(stats->br) != |
| - ARRAY_SIZE(binder_return_strings)); |
| + ARRAY_SIZE(binder_return_strings)); |
| for (i = 0; i < ARRAY_SIZE(stats->br); i++) { |
| if (stats->br[i]) |
| - buf += snprintf(buf, end - buf, "%s%s: %d\n", prefix, |
| - binder_return_strings[i], stats->br[i]); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, "%s%s: %d\n", prefix, |
| + binder_return_strings[i], stats->br[i]); |
| } |
| |
| BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != |
| - ARRAY_SIZE(binder_objstat_strings)); |
| + ARRAY_SIZE(binder_objstat_strings)); |
| BUILD_BUG_ON(ARRAY_SIZE(stats->obj_created) != |
| - ARRAY_SIZE(stats->obj_deleted)); |
| + ARRAY_SIZE(stats->obj_deleted)); |
| for (i = 0; i < ARRAY_SIZE(stats->obj_created); i++) { |
| if (stats->obj_created[i] || stats->obj_deleted[i]) |
| - buf += snprintf(buf, end - buf, |
| - "%s%s: active %d total %d\n", prefix, |
| - binder_objstat_strings[i], |
| - stats->obj_created[i] - |
| - stats->obj_deleted[i], |
| - stats->obj_created[i]); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, "%s%s: active %d total %d\n", prefix, |
| + binder_objstat_strings[i], |
| + stats->obj_created[i] - stats->obj_deleted[i], |
| + stats->obj_created[i]); |
| } |
| - return buf; |
| } |
| |
| -static char *print_binder_proc_stats(char *buf, char *end, |
| - struct binder_proc *proc) |
| +static void print_binder_proc_stats(struct seq_file *m, |
| + struct binder_proc *proc) |
| { |
| struct binder_work *w; |
| struct rb_node *n; |
| int count, strong, weak; |
| |
| - buf += snprintf(buf, end - buf, "proc %d\n", proc->pid); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, "proc %d\n", proc->pid); |
| count = 0; |
| for (n = rb_first(&proc->threads); n != NULL; n = rb_next(n)) |
| count++; |
| - buf += snprintf(buf, end - buf, " threads: %d\n", count); |
| - if (buf >= end) |
| - return buf; |
| - buf += snprintf(buf, end - buf, " requested threads: %d+%d/%d\n" |
| + seq_printf(m, " threads: %d\n", count); |
| + seq_printf(m, " requested threads: %d+%d/%d\n" |
| " ready threads %d\n" |
| " free async space %zd\n", proc->requested_threads, |
| proc->requested_threads_started, proc->max_threads, |
| proc->ready_threads, proc->free_async_space); |
| - if (buf >= end) |
| - return buf; |
| count = 0; |
| for (n = rb_first(&proc->nodes); n != NULL; n = rb_next(n)) |
| count++; |
| - buf += snprintf(buf, end - buf, " nodes: %d\n", count); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, " nodes: %d\n", count); |
| count = 0; |
| strong = 0; |
| weak = 0; |
| @@ -3468,17 +3410,12 @@ static char *print_binder_proc_stats(char *buf, char *end, |
| strong += ref->strong; |
| weak += ref->weak; |
| } |
| - buf += snprintf(buf, end - buf, " refs: %d s %d w %d\n", |
| - count, strong, weak); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, " refs: %d s %d w %d\n", count, strong, weak); |
| |
| count = 0; |
| for (n = rb_first(&proc->allocated_buffers); n != NULL; n = rb_next(n)) |
| count++; |
| - buf += snprintf(buf, end - buf, " buffers: %d\n", count); |
| - if (buf >= end) |
| - return buf; |
| + seq_printf(m, " buffers: %d\n", count); |
| |
| count = 0; |
| list_for_each_entry(w, &proc->todo, entry) { |
| @@ -3490,222 +3427,110 @@ static char *print_binder_proc_stats(char *buf, char *end, |
| break; |
| } |
| } |
| - buf += snprintf(buf, end - buf, " pending transactions: %d\n", count); |
| - if (buf >= end) |
| - return buf; |
| - |
| - buf = print_binder_stats(buf, end, " ", &proc->stats); |
| + seq_printf(m, " pending transactions: %d\n", count); |
| |
| - return buf; |
| + print_binder_stats(m, " ", &proc->stats); |
| } |
| |
| |
| -static int binder_read_proc_state(char *page, char **start, off_t off, |
| - int count, int *eof, void *data) |
| +static int binder_state_show(struct seq_file *m, void *unused) |
| { |
| struct binder_proc *proc; |
| struct hlist_node *pos; |
| struct binder_node *node; |
| - int len = 0; |
| - char *buf = page; |
| - char *end = page + PAGE_SIZE; |
| int do_lock = !binder_debug_no_lock; |
| |
| - if (off) |
| - return 0; |
| - |
| if (do_lock) |
| mutex_lock(&binder_lock); |
| |
| - buf += snprintf(buf, end - buf, "binder state:\n"); |
| + seq_puts(m, "binder state:\n"); |
| |
| if (!hlist_empty(&binder_dead_nodes)) |
| - buf += snprintf(buf, end - buf, "dead nodes:\n"); |
| - hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_node(buf, end, node); |
| - } |
| + seq_puts(m, "dead nodes:\n"); |
| + hlist_for_each_entry(node, pos, &binder_dead_nodes, dead_node) |
| + print_binder_node(m, node); |
| |
| - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_proc(buf, end, proc, 1); |
| - } |
| + hlist_for_each_entry(proc, pos, &binder_procs, proc_node) |
| + print_binder_proc(m, proc, 1); |
| if (do_lock) |
| mutex_unlock(&binder_lock); |
| - if (buf > page + PAGE_SIZE) |
| - buf = page + PAGE_SIZE; |
| - |
| - *start = page + off; |
| - |
| - len = buf - page; |
| - if (len > off) |
| - len -= off; |
| - else |
| - len = 0; |
| - |
| - return len < count ? len : count; |
| + return 0; |
| } |
| |
| -static int binder_read_proc_stats(char *page, char **start, off_t off, |
| - int count, int *eof, void *data) |
| +static int binder_stats_show(struct seq_file *m, void *unused) |
| { |
| struct binder_proc *proc; |
| struct hlist_node *pos; |
| - int len = 0; |
| - char *p = page; |
| int do_lock = !binder_debug_no_lock; |
| |
| - if (off) |
| - return 0; |
| - |
| if (do_lock) |
| mutex_lock(&binder_lock); |
| |
| - p += snprintf(p, PAGE_SIZE, "binder stats:\n"); |
| + seq_puts(m, "binder stats:\n"); |
| |
| - p = print_binder_stats(p, page + PAGE_SIZE, "", &binder_stats); |
| + print_binder_stats(m, "", &binder_stats); |
| |
| - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { |
| - if (p >= page + PAGE_SIZE) |
| - break; |
| - p = print_binder_proc_stats(p, page + PAGE_SIZE, proc); |
| - } |
| + hlist_for_each_entry(proc, pos, &binder_procs, proc_node) |
| + print_binder_proc_stats(m, proc); |
| if (do_lock) |
| mutex_unlock(&binder_lock); |
| - if (p > page + PAGE_SIZE) |
| - p = page + PAGE_SIZE; |
| - |
| - *start = page + off; |
| - |
| - len = p - page; |
| - if (len > off) |
| - len -= off; |
| - else |
| - len = 0; |
| - |
| - return len < count ? len : count; |
| + return 0; |
| } |
| |
| -static int binder_read_proc_transactions(char *page, char **start, off_t off, |
| - int count, int *eof, void *data) |
| +static int binder_transactions_show(struct seq_file *m, void *unused) |
| { |
| struct binder_proc *proc; |
| struct hlist_node *pos; |
| - int len = 0; |
| - char *buf = page; |
| - char *end = page + PAGE_SIZE; |
| int do_lock = !binder_debug_no_lock; |
| |
| - if (off) |
| - return 0; |
| - |
| if (do_lock) |
| mutex_lock(&binder_lock); |
| |
| - buf += snprintf(buf, end - buf, "binder transactions:\n"); |
| - hlist_for_each_entry(proc, pos, &binder_procs, proc_node) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_proc(buf, end, proc, 0); |
| - } |
| + seq_puts(m, "binder transactions:\n"); |
| + hlist_for_each_entry(proc, pos, &binder_procs, proc_node) |
| + print_binder_proc(m, proc, 0); |
| if (do_lock) |
| mutex_unlock(&binder_lock); |
| - if (buf > page + PAGE_SIZE) |
| - buf = page + PAGE_SIZE; |
| - |
| - *start = page + off; |
| - |
| - len = buf - page; |
| - if (len > off) |
| - len -= off; |
| - else |
| - len = 0; |
| - |
| - return len < count ? len : count; |
| + return 0; |
| } |
| |
| -static int binder_read_proc_proc(char *page, char **start, off_t off, |
| - int count, int *eof, void *data) |
| +static int binder_proc_show(struct seq_file *m, void *unused) |
| { |
| - struct binder_proc *proc = data; |
| - int len = 0; |
| - char *p = page; |
| + struct binder_proc *proc = m->private; |
| int do_lock = !binder_debug_no_lock; |
| |
| - if (off) |
| - return 0; |
| - |
| if (do_lock) |
| mutex_lock(&binder_lock); |
| - p += snprintf(p, PAGE_SIZE, "binder proc state:\n"); |
| - p = print_binder_proc(p, page + PAGE_SIZE, proc, 1); |
| + seq_puts(m, "binder proc state:\n"); |
| + print_binder_proc(m, proc, 1); |
| if (do_lock) |
| mutex_unlock(&binder_lock); |
| - |
| - if (p > page + PAGE_SIZE) |
| - p = page + PAGE_SIZE; |
| - *start = page + off; |
| - |
| - len = p - page; |
| - if (len > off) |
| - len -= off; |
| - else |
| - len = 0; |
| - |
| - return len < count ? len : count; |
| + return 0; |
| } |
| |
| -static char *print_binder_transaction_log_entry(char *buf, char *end, |
| +static void print_binder_transaction_log_entry(struct seq_file *m, |
| struct binder_transaction_log_entry *e) |
| { |
| - buf += snprintf(buf, end - buf, |
| - "%d: %s from %d:%d to %d:%d node %d handle %d " |
| - "size %d:%d\n", |
| - e->debug_id, (e->call_type == 2) ? "reply" : |
| - ((e->call_type == 1) ? "async" : "call "), e->from_proc, |
| - e->from_thread, e->to_proc, e->to_thread, e->to_node, |
| - e->target_handle, e->data_size, e->offsets_size); |
| - return buf; |
| + seq_printf(m, |
| + "%d: %s from %d:%d to %d:%d node %d handle %d size %d:%d\n", |
| + e->debug_id, (e->call_type == 2) ? "reply" : |
| + ((e->call_type == 1) ? "async" : "call "), e->from_proc, |
| + e->from_thread, e->to_proc, e->to_thread, e->to_node, |
| + e->target_handle, e->data_size, e->offsets_size); |
| } |
| |
| -static int binder_read_proc_transaction_log( |
| - char *page, char **start, off_t off, int count, int *eof, void *data) |
| +static int binder_transaction_log_show(struct seq_file *m, void *unused) |
| { |
| - struct binder_transaction_log *log = data; |
| - int len = 0; |
| + struct binder_transaction_log *log = m->private; |
| int i; |
| - char *buf = page; |
| - char *end = page + PAGE_SIZE; |
| - |
| - if (off) |
| - return 0; |
| |
| if (log->full) { |
| - for (i = log->next; i < ARRAY_SIZE(log->entry); i++) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_transaction_log_entry(buf, end, |
| - &log->entry[i]); |
| - } |
| + for (i = log->next; i < ARRAY_SIZE(log->entry); i++) |
| + print_binder_transaction_log_entry(m, &log->entry[i]); |
| } |
| - for (i = 0; i < log->next; i++) { |
| - if (buf >= end) |
| - break; |
| - buf = print_binder_transaction_log_entry(buf, end, |
| - &log->entry[i]); |
| - } |
| - |
| - *start = page + off; |
| - |
| - len = buf - page; |
| - if (len > off) |
| - len -= off; |
| - else |
| - len = 0; |
| - |
| - return len < count ? len : count; |
| + for (i = 0; i < log->next; i++) |
| + print_binder_transaction_log_entry(m, &log->entry[i]); |
| + return 0; |
| } |
| |
| static const struct file_operations binder_fops = { |
| @@ -3724,6 +3549,11 @@ static struct miscdevice binder_miscdev = { |
| .fops = &binder_fops |
| }; |
| |
| +BINDER_DEBUG_ENTRY(state); |
| +BINDER_DEBUG_ENTRY(stats); |
| +BINDER_DEBUG_ENTRY(transactions); |
| +BINDER_DEBUG_ENTRY(transaction_log); |
| + |
| static int __init binder_init(void) |
| { |
| int ret; |
| @@ -3734,31 +3564,28 @@ static int __init binder_init(void) |
| binder_proc_dir_entry_root); |
| ret = misc_register(&binder_miscdev); |
| if (binder_proc_dir_entry_root) { |
| - create_proc_read_entry("state", |
| - S_IRUGO, |
| - binder_proc_dir_entry_root, |
| - binder_read_proc_state, |
| - NULL); |
| - create_proc_read_entry("stats", |
| - S_IRUGO, |
| - binder_proc_dir_entry_root, |
| - binder_read_proc_stats, |
| - NULL); |
| - create_proc_read_entry("transactions", |
| - S_IRUGO, |
| - binder_proc_dir_entry_root, |
| - binder_read_proc_transactions, |
| - NULL); |
| - create_proc_read_entry("transaction_log", |
| - S_IRUGO, |
| - binder_proc_dir_entry_root, |
| - binder_read_proc_transaction_log, |
| - &binder_transaction_log); |
| - create_proc_read_entry("failed_transaction_log", |
| - S_IRUGO, |
| - binder_proc_dir_entry_root, |
| - binder_read_proc_transaction_log, |
| - &binder_transaction_log_failed); |
| + proc_create("state", |
| + S_IRUGO, |
| + binder_proc_dir_entry_root, |
| + &binder_state_fops); |
| + proc_create("stats", |
| + S_IRUGO, |
| + binder_proc_dir_entry_root, |
| + &binder_stats_fops); |
| + proc_create("transactions", |
| + S_IRUGO, |
| + binder_proc_dir_entry_root, |
| + &binder_transactions_fops); |
| + proc_create_data("transaction_log", |
| + S_IRUGO, |
| + binder_proc_dir_entry_root, |
| + &binder_transaction_log_fops, |
| + &binder_transaction_log); |
| + proc_create_data("failed_transaction_log", |
| + S_IRUGO, |
| + binder_proc_dir_entry_root, |
| + &binder_transaction_log_fops, |
| + &binder_transaction_log_failed); |
| } |
| return ret; |
| } |