From: William Lee Irwin III <wli@holomorphy.com>

Andi Kleen requested that the number of pagetable pages in use by a process
be reported in /proc/$PID/status; this patch implements that.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/i386/mm/hugetlbpage.c  |    1 +
 25-akpm/arch/ppc64/mm/hugetlbpage.c |    1 +
 25-akpm/fs/proc/task_mmu.c          |    6 ++++--
 25-akpm/include/linux/sched.h       |    2 +-
 25-akpm/kernel/fork.c               |    1 +
 25-akpm/mm/memory.c                 |    3 ++-
 6 files changed, 10 insertions(+), 4 deletions(-)

diff -puN arch/i386/mm/hugetlbpage.c~report-per-process-pagetable-usage arch/i386/mm/hugetlbpage.c
--- 25/arch/i386/mm/hugetlbpage.c~report-per-process-pagetable-usage	2004-10-03 16:43:33.115297264 -0700
+++ 25-akpm/arch/i386/mm/hugetlbpage.c	2004-10-03 16:43:33.126295592 -0700
@@ -247,6 +247,7 @@ int hugetlb_prefault(struct address_spac
 
 			page = pmd_page(*pmd);
 			pmd_clear(pmd);
+			mm->nr_ptes--;
 			dec_page_state(nr_page_table_pages);
 			page_cache_release(page);
 		}
diff -puN arch/ppc64/mm/hugetlbpage.c~report-per-process-pagetable-usage arch/ppc64/mm/hugetlbpage.c
--- 25/arch/ppc64/mm/hugetlbpage.c~report-per-process-pagetable-usage	2004-10-03 16:43:33.116297112 -0700
+++ 25-akpm/arch/ppc64/mm/hugetlbpage.c	2004-10-03 16:43:33.127295440 -0700
@@ -213,6 +213,7 @@ static int prepare_low_seg_for_htlb(stru
 		}
 		page = pmd_page(*pmd);
 		pmd_clear(pmd);
+		mm->nr_ptes--;
 		dec_page_state(nr_page_table_pages);
 		pte_free_tlb(tlb, page);
 	}
diff -puN fs/proc/task_mmu.c~report-per-process-pagetable-usage fs/proc/task_mmu.c
--- 25/fs/proc/task_mmu.c~report-per-process-pagetable-usage	2004-10-03 16:43:33.117296960 -0700
+++ 25-akpm/fs/proc/task_mmu.c	2004-10-03 16:43:33.127295440 -0700
@@ -18,12 +18,14 @@ char *task_mem(struct mm_struct *mm, cha
 		"VmData:\t%8lu kB\n"
 		"VmStk:\t%8lu kB\n"
 		"VmExe:\t%8lu kB\n"
-		"VmLib:\t%8lu kB\n",
+		"VmLib:\t%8lu kB\n"
+		"VmPTE:\t%8lu kB\n",
 		(mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
 		mm->locked_vm << (PAGE_SHIFT-10),
 		mm->rss << (PAGE_SHIFT-10),
 		data << (PAGE_SHIFT-10),
-		mm->stack_vm << (PAGE_SHIFT-10), text, lib);
+		mm->stack_vm << (PAGE_SHIFT-10), text, lib,
+		(PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
 	return buffer;
 }
 
diff -puN include/linux/sched.h~report-per-process-pagetable-usage include/linux/sched.h
--- 25/include/linux/sched.h~report-per-process-pagetable-usage	2004-10-03 16:43:33.119296656 -0700
+++ 25-akpm/include/linux/sched.h	2004-10-03 16:43:33.128295288 -0700
@@ -228,7 +228,7 @@ struct mm_struct {
 	unsigned long start_brk, brk, start_stack;
 	unsigned long arg_start, arg_end, env_start, env_end;
 	unsigned long rss, total_vm, locked_vm, shared_vm;
-	unsigned long exec_vm, stack_vm, reserved_vm, def_flags;
+	unsigned long exec_vm, stack_vm, reserved_vm, def_flags, nr_ptes;
 
 	unsigned long saved_auxv[42]; /* for /proc/PID/auxv */
 
diff -puN kernel/fork.c~report-per-process-pagetable-usage kernel/fork.c
--- 25/kernel/fork.c~report-per-process-pagetable-usage	2004-10-03 16:43:33.120296504 -0700
+++ 25-akpm/kernel/fork.c	2004-10-03 16:43:33.129295136 -0700
@@ -297,6 +297,7 @@ static struct mm_struct * mm_init(struct
 	init_rwsem(&mm->mmap_sem);
 	INIT_LIST_HEAD(&mm->mmlist);
 	mm->core_waiters = 0;
+	mm->nr_ptes = 0;
 	mm->page_table_lock = SPIN_LOCK_UNLOCKED;
 	mm->ioctx_list_lock = RW_LOCK_UNLOCKED;
 	mm->ioctx_list = NULL;
diff -puN mm/memory.c~report-per-process-pagetable-usage mm/memory.c
--- 25/mm/memory.c~report-per-process-pagetable-usage	2004-10-03 16:43:33.122296200 -0700
+++ 25-akpm/mm/memory.c	2004-10-03 16:43:33.131294832 -0700
@@ -114,6 +114,7 @@ static inline void free_one_pmd(struct m
 	page = pmd_page(*dir);
 	pmd_clear(dir);
 	dec_page_state(nr_page_table_pages);
+	tlb->mm->nr_ptes--;
 	pte_free_tlb(tlb, page);
 }
 
@@ -163,7 +164,6 @@ pte_t fastcall * pte_alloc_map(struct mm
 		spin_lock(&mm->page_table_lock);
 		if (!new)
 			return NULL;
-
 		/*
 		 * Because we dropped the lock, we should re-check the
 		 * entry, as somebody else could have populated it..
@@ -172,6 +172,7 @@ pte_t fastcall * pte_alloc_map(struct mm
 			pte_free(new);
 			goto out;
 		}
+		mm->nr_ptes++;
 		inc_page_state(nr_page_table_pages);
 		pmd_populate(mm, pmd, new);
 	}
_