binder: Use seq_file for debug interface.
authorArve Hjønnevåg <arve@android.com>
Wed, 29 Apr 2009 03:57:50 +0000 (20:57 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Wed, 30 Nov 2011 11:40:06 +0000 (20:40 +0900)
Signed-off-by: Arve Hjønnevåg <arve@android.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/staging/android/binder.c

index 3aec45301eb3547562731e08a013569608abd397..371232b12d96e91057bae8133586111b87d94552 100644 (file)
@@ -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;
 }