From: Prasanna Meda <pmeda@akamai.com>

Second version:
Tested it more, and fixed bug in last_addr vs. next_addr handling, and  added
comments. Also got rid of assumption that zero adress is not part of address space.

Signed-off-by: Prasanna Meda <pmeda@akamai.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/proc/task_mmu.c |   19 ++++++++++++++-----
 1 files changed, 14 insertions(+), 5 deletions(-)

diff -puN fs/proc/task_mmu.c~speedup-proc-pid-maps-fix fs/proc/task_mmu.c
--- 25/fs/proc/task_mmu.c~speedup-proc-pid-maps-fix	2005-02-22 18:17:10.000000000 -0800
+++ 25-akpm/fs/proc/task_mmu.c	2005-02-22 18:17:10.000000000 -0800
@@ -161,6 +161,15 @@ static void *m_start(struct seq_file *m,
 	tail_map = get_gate_vma(task);
 	down_read(&mm->mmap_sem);
 
+	/*
+	 * First map is special, since we remember last_addr
+	 * rather than current_addr to hit with mmap_cache most of the time.
+	 */
+	if (!l) {
+		map = mm->mmap;
+		goto out;
+	}
+
 	/* Start with last addr hint */
 	map = find_vma(mm, last_addr);
 	if (map) {
@@ -168,7 +177,7 @@ static void *m_start(struct seq_file *m,
 		goto out;
 	}
 
-	/* Check the map index is within the range */
+	/* Check the map index is within the range, and do linear scan */
 	if ((unsigned long)l < mm->map_count) {
 		map = mm->mmap;
 		while (l-- && map)
@@ -207,16 +216,16 @@ static void *m_next(struct seq_file *m, 
 {
 	struct task_struct *task = m->private;
 	struct vm_area_struct *map = v;
+	struct vm_area_struct *tail_map = get_gate_vma(task);
+
 	(*pos)++;
 	if (map && map->vm_next) {
-		m->version = map->vm_next->vm_start;
+		m->version = (map != tail_map)? map->vm_start: -1UL;
 		return map->vm_next;
 	}
 	m_stop(m, v);
 	m->version = -1UL;
-	if (map != get_gate_vma(task))
-		return get_gate_vma(task);
-	return NULL;
+	return (map != tail_map)? tail_map: NULL;
 }
 
 struct seq_operations proc_pid_maps_op = {
_