diff options
author | Mel Gorman <mel@csn.ul.ie> | 2008-07-24 00:26:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-07-24 13:47:13 -0400 |
commit | 708614e6180f398cd307ea0048d48ba6fa274610 (patch) | |
tree | 8fedf22cf9a2f404e2aef10c5b3858b99880c4c2 /mm/mm_init.c | |
parent | 6b74ab97bc12ce74acec900f1d89a4aee2e4d70d (diff) |
mm: verify the page links and memory model
Print out information on how the page flags are being used if mminit_loglevel
is MMINIT_VERIFY or higher and unconditionally performs sanity checks on the
flags regardless of loglevel.
When the page flags are updated with section, node and zone information, a
check are made to ensure the values can be retrieved correctly. Finally we
confirm that pfn_to_page and page_to_pfn are the correct inverse functions.
[akpm@linux-foundation.org: fix printk warnings]
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Cc: Christoph Lameter <cl@linux-foundation.org>
Cc: Andy Whitcroft <apw@shadowen.org>
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/mm_init.c')
-rw-r--r-- | mm/mm_init.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/mm/mm_init.c b/mm/mm_init.c index c01d8dfec817..e16990d629e6 100644 --- a/mm/mm_init.c +++ b/mm/mm_init.c | |||
@@ -7,9 +7,80 @@ | |||
7 | */ | 7 | */ |
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include "internal.h" | ||
10 | 11 | ||
11 | int __meminitdata mminit_loglevel; | 12 | int __meminitdata mminit_loglevel; |
12 | 13 | ||
14 | void __init mminit_verify_pageflags_layout(void) | ||
15 | { | ||
16 | int shift, width; | ||
17 | unsigned long or_mask, add_mask; | ||
18 | |||
19 | shift = 8 * sizeof(unsigned long); | ||
20 | width = shift - SECTIONS_WIDTH - NODES_WIDTH - ZONES_WIDTH; | ||
21 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_widths", | ||
22 | "Section %d Node %d Zone %d Flags %d\n", | ||
23 | SECTIONS_WIDTH, | ||
24 | NODES_WIDTH, | ||
25 | ZONES_WIDTH, | ||
26 | NR_PAGEFLAGS); | ||
27 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_shifts", | ||
28 | "Section %d Node %d Zone %d\n", | ||
29 | #ifdef SECTIONS_SHIFT | ||
30 | SECTIONS_SHIFT, | ||
31 | #else | ||
32 | 0, | ||
33 | #endif | ||
34 | NODES_SHIFT, | ||
35 | ZONES_SHIFT); | ||
36 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_offsets", | ||
37 | "Section %lu Node %lu Zone %lu\n", | ||
38 | (unsigned long)SECTIONS_PGSHIFT, | ||
39 | (unsigned long)NODES_PGSHIFT, | ||
40 | (unsigned long)ZONES_PGSHIFT); | ||
41 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_zoneid", | ||
42 | "Zone ID: %lu -> %lu\n", | ||
43 | (unsigned long)ZONEID_PGOFF, | ||
44 | (unsigned long)(ZONEID_PGOFF + ZONEID_SHIFT)); | ||
45 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_usage", | ||
46 | "location: %d -> %d unused %d -> %d flags %d -> %d\n", | ||
47 | shift, width, width, NR_PAGEFLAGS, NR_PAGEFLAGS, 0); | ||
48 | #ifdef NODE_NOT_IN_PAGE_FLAGS | ||
49 | mminit_dprintk(MMINIT_TRACE, "pageflags_layout_nodeflags", | ||
50 | "Node not in page flags"); | ||
51 | #endif | ||
52 | |||
53 | if (SECTIONS_WIDTH) { | ||
54 | shift -= SECTIONS_WIDTH; | ||
55 | BUG_ON(shift != SECTIONS_PGSHIFT); | ||
56 | } | ||
57 | if (NODES_WIDTH) { | ||
58 | shift -= NODES_WIDTH; | ||
59 | BUG_ON(shift != NODES_PGSHIFT); | ||
60 | } | ||
61 | if (ZONES_WIDTH) { | ||
62 | shift -= ZONES_WIDTH; | ||
63 | BUG_ON(shift != ZONES_PGSHIFT); | ||
64 | } | ||
65 | |||
66 | /* Check for bitmask overlaps */ | ||
67 | or_mask = (ZONES_MASK << ZONES_PGSHIFT) | | ||
68 | (NODES_MASK << NODES_PGSHIFT) | | ||
69 | (SECTIONS_MASK << SECTIONS_PGSHIFT); | ||
70 | add_mask = (ZONES_MASK << ZONES_PGSHIFT) + | ||
71 | (NODES_MASK << NODES_PGSHIFT) + | ||
72 | (SECTIONS_MASK << SECTIONS_PGSHIFT); | ||
73 | BUG_ON(or_mask != add_mask); | ||
74 | } | ||
75 | |||
76 | void __meminit mminit_verify_page_links(struct page *page, enum zone_type zone, | ||
77 | unsigned long nid, unsigned long pfn) | ||
78 | { | ||
79 | BUG_ON(page_to_nid(page) != nid); | ||
80 | BUG_ON(page_zonenum(page) != zone); | ||
81 | BUG_ON(page_to_pfn(page) != pfn); | ||
82 | } | ||
83 | |||
13 | static __init int set_mminit_loglevel(char *str) | 84 | static __init int set_mminit_loglevel(char *str) |
14 | { | 85 | { |
15 | get_option(&str, &mminit_loglevel); | 86 | get_option(&str, &mminit_loglevel); |