]>
Commit | Line | Data |
---|---|---|
82742a3a SL |
1 | #include <linux/kernel.h> |
2 | #include <linux/mm.h> | |
3 | #include <linux/ftrace_event.h> | |
4 | #include <linux/memcontrol.h> | |
5 | ||
6 | static const struct trace_print_flags pageflag_names[] = { | |
7 | {1UL << PG_locked, "locked" }, | |
8 | {1UL << PG_error, "error" }, | |
9 | {1UL << PG_referenced, "referenced" }, | |
10 | {1UL << PG_uptodate, "uptodate" }, | |
11 | {1UL << PG_dirty, "dirty" }, | |
12 | {1UL << PG_lru, "lru" }, | |
13 | {1UL << PG_active, "active" }, | |
14 | {1UL << PG_slab, "slab" }, | |
15 | {1UL << PG_owner_priv_1, "owner_priv_1" }, | |
16 | {1UL << PG_arch_1, "arch_1" }, | |
17 | {1UL << PG_reserved, "reserved" }, | |
18 | {1UL << PG_private, "private" }, | |
19 | {1UL << PG_private_2, "private_2" }, | |
20 | {1UL << PG_writeback, "writeback" }, | |
21 | #ifdef CONFIG_PAGEFLAGS_EXTENDED | |
22 | {1UL << PG_head, "head" }, | |
23 | {1UL << PG_tail, "tail" }, | |
24 | #else | |
25 | {1UL << PG_compound, "compound" }, | |
26 | #endif | |
27 | {1UL << PG_swapcache, "swapcache" }, | |
28 | {1UL << PG_mappedtodisk, "mappedtodisk" }, | |
29 | {1UL << PG_reclaim, "reclaim" }, | |
30 | {1UL << PG_swapbacked, "swapbacked" }, | |
31 | {1UL << PG_unevictable, "unevictable" }, | |
32 | #ifdef CONFIG_MMU | |
33 | {1UL << PG_mlocked, "mlocked" }, | |
34 | #endif | |
35 | #ifdef CONFIG_ARCH_USES_PG_UNCACHED | |
36 | {1UL << PG_uncached, "uncached" }, | |
37 | #endif | |
38 | #ifdef CONFIG_MEMORY_FAILURE | |
39 | {1UL << PG_hwpoison, "hwpoison" }, | |
40 | #endif | |
41 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | |
42 | {1UL << PG_compound_lock, "compound_lock" }, | |
43 | #endif | |
44 | }; | |
45 | ||
46 | static void dump_flags(unsigned long flags, | |
47 | const struct trace_print_flags *names, int count) | |
48 | { | |
49 | const char *delim = ""; | |
50 | unsigned long mask; | |
51 | int i; | |
52 | ||
53 | printk(KERN_ALERT "flags: %#lx(", flags); | |
54 | ||
55 | /* remove zone id */ | |
56 | flags &= (1UL << NR_PAGEFLAGS) - 1; | |
57 | ||
58 | for (i = 0; i < count && flags; i++) { | |
59 | ||
60 | mask = names[i].mask; | |
61 | if ((flags & mask) != mask) | |
62 | continue; | |
63 | ||
64 | flags &= ~mask; | |
65 | printk("%s%s", delim, names[i].name); | |
66 | delim = "|"; | |
67 | } | |
68 | ||
69 | /* check for left over flags */ | |
70 | if (flags) | |
71 | printk("%s%#lx", delim, flags); | |
72 | ||
73 | printk(")\n"); | |
74 | } | |
75 | ||
76 | void dump_page_badflags(struct page *page, const char *reason, | |
77 | unsigned long badflags) | |
78 | { | |
79 | printk(KERN_ALERT | |
80 | "page:%p count:%d mapcount:%d mapping:%p index:%#lx\n", | |
81 | page, atomic_read(&page->_count), page_mapcount(page), | |
82 | page->mapping, page->index); | |
83 | BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS); | |
84 | dump_flags(page->flags, pageflag_names, ARRAY_SIZE(pageflag_names)); | |
85 | if (reason) | |
86 | pr_alert("page dumped because: %s\n", reason); | |
87 | if (page->flags & badflags) { | |
88 | pr_alert("bad because of flags:\n"); | |
89 | dump_flags(page->flags & badflags, | |
90 | pageflag_names, ARRAY_SIZE(pageflag_names)); | |
91 | } | |
92 | mem_cgroup_print_bad_page(page); | |
93 | } | |
94 | ||
95 | void dump_page(struct page *page, const char *reason) | |
96 | { | |
97 | dump_page_badflags(page, reason, 0); | |
98 | } | |
99 | EXPORT_SYMBOL(dump_page); | |
100 | ||
101 | #ifdef CONFIG_DEBUG_VM | |
102 | ||
103 | static const struct trace_print_flags vmaflags_names[] = { | |
104 | {VM_READ, "read" }, | |
105 | {VM_WRITE, "write" }, | |
106 | {VM_EXEC, "exec" }, | |
107 | {VM_SHARED, "shared" }, | |
108 | {VM_MAYREAD, "mayread" }, | |
109 | {VM_MAYWRITE, "maywrite" }, | |
110 | {VM_MAYEXEC, "mayexec" }, | |
111 | {VM_MAYSHARE, "mayshare" }, | |
112 | {VM_GROWSDOWN, "growsdown" }, | |
113 | {VM_PFNMAP, "pfnmap" }, | |
114 | {VM_DENYWRITE, "denywrite" }, | |
115 | {VM_LOCKED, "locked" }, | |
116 | {VM_IO, "io" }, | |
117 | {VM_SEQ_READ, "seqread" }, | |
118 | {VM_RAND_READ, "randread" }, | |
119 | {VM_DONTCOPY, "dontcopy" }, | |
120 | {VM_DONTEXPAND, "dontexpand" }, | |
121 | {VM_ACCOUNT, "account" }, | |
122 | {VM_NORESERVE, "noreserve" }, | |
123 | {VM_HUGETLB, "hugetlb" }, | |
124 | {VM_NONLINEAR, "nonlinear" }, | |
125 | #if defined(CONFIG_X86) | |
126 | {VM_PAT, "pat" }, | |
127 | #elif defined(CONFIG_PPC) | |
128 | {VM_SAO, "sao" }, | |
129 | #elif defined(CONFIG_PARISC) || defined(CONFIG_METAG) || defined(CONFIG_IA64) | |
130 | {VM_GROWSUP, "growsup" }, | |
131 | #elif !defined(CONFIG_MMU) | |
132 | {VM_MAPPED_COPY, "mappedcopy" }, | |
133 | #else | |
134 | {VM_ARCH_1, "arch_1" }, | |
135 | #endif | |
136 | {VM_DONTDUMP, "dontdump" }, | |
137 | #ifdef CONFIG_MEM_SOFT_DIRTY | |
138 | {VM_SOFTDIRTY, "softdirty" }, | |
139 | #endif | |
140 | {VM_MIXEDMAP, "mixedmap" }, | |
141 | {VM_HUGEPAGE, "hugepage" }, | |
142 | {VM_NOHUGEPAGE, "nohugepage" }, | |
143 | {VM_MERGEABLE, "mergeable" }, | |
144 | }; | |
145 | ||
146 | void dump_vma(const struct vm_area_struct *vma) | |
147 | { | |
148 | printk(KERN_ALERT | |
149 | "vma %p start %p end %p\n" | |
150 | "next %p prev %p mm %p\n" | |
151 | "prot %lx anon_vma %p vm_ops %p\n" | |
152 | "pgoff %lx file %p private_data %p\n", | |
153 | vma, (void *)vma->vm_start, (void *)vma->vm_end, vma->vm_next, | |
154 | vma->vm_prev, vma->vm_mm, | |
155 | (unsigned long)pgprot_val(vma->vm_page_prot), | |
156 | vma->anon_vma, vma->vm_ops, vma->vm_pgoff, | |
157 | vma->vm_file, vma->vm_private_data); | |
158 | dump_flags(vma->vm_flags, vmaflags_names, ARRAY_SIZE(vmaflags_names)); | |
159 | } | |
160 | EXPORT_SYMBOL(dump_vma); | |
161 | ||
162 | #endif /* CONFIG_DEBUG_VM */ |