diff options
author | Vegard Nossum <vegard.nossum@gmail.com> | 2008-11-25 10:55:53 -0500 |
---|---|---|
committer | Vegard Nossum <vegard.nossum@gmail.com> | 2009-06-15 09:48:33 -0400 |
commit | b1eeab67682a5e397aecf172046b3a8bd4808ae4 (patch) | |
tree | c357b6ac1945dc8beecc2f8c4d84660ad8d35aae /mm/page_alloc.c | |
parent | 9b5cab31897e9e89e36c0c2a89b16b93ff1a971a (diff) |
kmemcheck: add hooks for the page allocator
This adds support for tracking the initializedness of memory that
was allocated with the page allocator. Highmem requests are not
tracked.
Cc: Dave Hansen <dave@linux.vnet.ibm.com>
Acked-by: Pekka Enberg <penberg@cs.helsinki.fi>
[build fix for !CONFIG_KMEMCHECK]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
[rebased for mainline inclusion]
Signed-off-by: Vegard Nossum <vegard.nossum@gmail.com>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 17d5f539a9aa..0727896a88ac 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
24 | #include <linux/compiler.h> | 24 | #include <linux/compiler.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/kmemcheck.h> | ||
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
27 | #include <linux/suspend.h> | 28 | #include <linux/suspend.h> |
28 | #include <linux/pagevec.h> | 29 | #include <linux/pagevec.h> |
@@ -546,6 +547,8 @@ static void __free_pages_ok(struct page *page, unsigned int order) | |||
546 | int i; | 547 | int i; |
547 | int bad = 0; | 548 | int bad = 0; |
548 | 549 | ||
550 | kmemcheck_free_shadow(page, order); | ||
551 | |||
549 | for (i = 0 ; i < (1 << order) ; ++i) | 552 | for (i = 0 ; i < (1 << order) ; ++i) |
550 | bad += free_pages_check(page + i); | 553 | bad += free_pages_check(page + i); |
551 | if (bad) | 554 | if (bad) |
@@ -994,6 +997,8 @@ static void free_hot_cold_page(struct page *page, int cold) | |||
994 | struct per_cpu_pages *pcp; | 997 | struct per_cpu_pages *pcp; |
995 | unsigned long flags; | 998 | unsigned long flags; |
996 | 999 | ||
1000 | kmemcheck_free_shadow(page, 0); | ||
1001 | |||
997 | if (PageAnon(page)) | 1002 | if (PageAnon(page)) |
998 | page->mapping = NULL; | 1003 | page->mapping = NULL; |
999 | if (free_pages_check(page)) | 1004 | if (free_pages_check(page)) |
@@ -1047,6 +1052,16 @@ void split_page(struct page *page, unsigned int order) | |||
1047 | 1052 | ||
1048 | VM_BUG_ON(PageCompound(page)); | 1053 | VM_BUG_ON(PageCompound(page)); |
1049 | VM_BUG_ON(!page_count(page)); | 1054 | VM_BUG_ON(!page_count(page)); |
1055 | |||
1056 | #ifdef CONFIG_KMEMCHECK | ||
1057 | /* | ||
1058 | * Split shadow pages too, because free(page[0]) would | ||
1059 | * otherwise free the whole shadow. | ||
1060 | */ | ||
1061 | if (kmemcheck_page_is_tracked(page)) | ||
1062 | split_page(virt_to_page(page[0].shadow), order); | ||
1063 | #endif | ||
1064 | |||
1050 | for (i = 1; i < (1 << order); i++) | 1065 | for (i = 1; i < (1 << order); i++) |
1051 | set_page_refcounted(page + i); | 1066 | set_page_refcounted(page + i); |
1052 | } | 1067 | } |
@@ -1667,7 +1682,10 @@ nopage: | |||
1667 | dump_stack(); | 1682 | dump_stack(); |
1668 | show_mem(); | 1683 | show_mem(); |
1669 | } | 1684 | } |
1685 | return page; | ||
1670 | got_pg: | 1686 | got_pg: |
1687 | if (kmemcheck_enabled) | ||
1688 | kmemcheck_pagealloc_alloc(page, order, gfp_mask); | ||
1671 | return page; | 1689 | return page; |
1672 | } | 1690 | } |
1673 | EXPORT_SYMBOL(__alloc_pages_internal); | 1691 | EXPORT_SYMBOL(__alloc_pages_internal); |