mincore: Report whether page is anon or not

From: Pavel Emelyanov <xemul@parallels.com>

This is required not to dump pages from private file mappings, that are
not mapped or not yet COW-ed.

The thing is that mincode reports bit 1 for pages that are in memory, regardless
of whether they are mapped or not. But in case we have mapped a file of 2 pages and
read a single page mincore will report 1 for both - the 1st one being mapped and
the 2nd one being in page cache due to readahead.

With this fix both pages will be !PageAnon and we can skip them from dumping.

Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
---
 include/linux/mman.h |    1 +
 mm/mincore.c         |   15 +++++++++++++--
 2 files changed, 14 insertions(+), 2 deletions(-)

Index: linux-2.6.git/include/linux/mman.h
===================================================================
--- linux-2.6.git.orig/include/linux/mman.h
+++ linux-2.6.git/include/linux/mman.h
@@ -11,6 +11,7 @@
 #define OVERCOMMIT_NEVER		2
 
 #define MINCORE_RESIDENT	0x1
+#define MINCORE_ANON		0x2
 
 #ifdef __KERNEL__
 #include <linux/mm.h>
Index: linux-2.6.git/mm/mincore.c
===================================================================
--- linux-2.6.git.orig/mm/mincore.c
+++ linux-2.6.git/mm/mincore.c
@@ -38,7 +38,7 @@ static void mincore_hugetlb_page_range(s
 				       addr & huge_page_mask(h));
 		present = ptep && !huge_pte_none(huge_ptep_get(ptep));
 		while (1) {
-			*vec = (present ? MINCORE_RESIDENT : 0);
+			*vec = (present ? MINCORE_RESIDENT : 0) | MINCORE_ANON;
 			vec++;
 			addr += PAGE_SIZE;
 			if (addr == end)
@@ -86,6 +86,17 @@ static unsigned char mincore_page(struct
 	return present ? MINCORE_RESIDENT : 0;
 }
 
+static unsigned char mincore_pte(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
+{
+	struct page *pg;
+
+	pg = vm_normal_page(vma, addr, pte);
+	if (!pg)
+		return 0;
+	else
+		return PageAnon(pg) ? MINCORE_ANON : 0;
+}
+
 static void mincore_unmapped_range(struct vm_area_struct *vma,
 				unsigned long addr, unsigned long end,
 				unsigned char *vec)
@@ -122,7 +133,7 @@ static void mincore_pte_range(struct vm_
 		if (pte_none(pte))
 			mincore_unmapped_range(vma, addr, next, vec);
 		else if (pte_present(pte))
-			*vec = MINCORE_RESIDENT;
+			*vec = MINCORE_RESIDENT | mincore_pte(vma, addr, pte);
 		else if (pte_file(pte)) {
 			pgoff = pte_to_pgoff(pte);
 			*vec = mincore_page(vma->vm_file->f_mapping, pgoff);
