Blame view
mm/debug.c
6.12 KB
b24413180
|
1 |
// SPDX-License-Identifier: GPL-2.0 |
31c9afa6d
|
2 3 4 5 6 7 |
/* * mm/debug.c * * mm/ specific debug routines. * */ |
82742a3a5
|
8 9 |
#include <linux/kernel.h> #include <linux/mm.h> |
af658dca2
|
10 |
#include <linux/trace_events.h> |
82742a3a5
|
11 |
#include <linux/memcontrol.h> |
420adbe9f
|
12 |
#include <trace/events/mmflags.h> |
7cd12b4ab
|
13 |
#include <linux/migrate.h> |
4e462112e
|
14 |
#include <linux/page_owner.h> |
f682a97a0
|
15 |
#include <linux/ctype.h> |
82742a3a5
|
16 |
|
edf14cdbf
|
17 |
#include "internal.h" |
9a2f45ff3
|
18 |
const char *migrate_reason_names[MR_TYPES] = { |
7cd12b4ab
|
19 20 21 22 23 24 25 26 |
"compaction", "memory_failure", "memory_hotplug", "syscall_or_cpuset", "mempolicy_mbind", "numa_misplaced", "cma", }; |
edf14cdbf
|
27 28 29 30 31 32 33 34 |
const struct trace_print_flags pageflag_names[] = { __def_pageflag_names, {0, NULL} }; const struct trace_print_flags gfpflag_names[] = { __def_gfpflag_names, {0, NULL} |
420adbe9f
|
35 |
}; |
edf14cdbf
|
36 37 38 |
const struct trace_print_flags vmaflag_names[] = { __def_vmaflag_names, {0, NULL} |
82742a3a5
|
39 |
}; |
ff8e81163
|
40 |
void __dump_page(struct page *page, const char *reason) |
82742a3a5
|
41 |
{ |
311ade0ea
|
42 |
struct address_space *mapping; |
fc36def99
|
43 44 |
bool page_poisoned = PagePoisoned(page); int mapcount; |
2bb9bfcde
|
45 |
char *type = ""; |
fc36def99
|
46 47 48 49 50 51 52 |
/* * If struct page is poisoned don't access Page*() functions as that * leads to recursive loop. Page*() check for poisoned pages, and calls * dump_page() when detected. */ if (page_poisoned) { |
e0392cf7c
|
53 |
pr_warn("page:%px is uninitialized and poisoned", page); |
fc36def99
|
54 55 |
goto hex_only; } |
311ade0ea
|
56 |
mapping = page_mapping(page); |
9996f05ea
|
57 58 59 60 61 |
/* * Avoid VM_BUG_ON() in page_mapcount(). * page->_mapcount space in struct page is used by sl[aou]b pages to * encode own info. */ |
fc36def99
|
62 |
mapcount = PageSlab(page) ? 0 : page_mapcount(page); |
4d35427ad
|
63 |
|
53f9263ba
|
64 |
if (PageCompound(page)) |
76a1850e4
|
65 66 67 68 69 70 71 72 73 74 75 |
pr_warn("page:%px refcount:%d mapcount:%d mapping:%px " "index:%#lx compound_mapcount: %d ", page, page_ref_count(page), mapcount, page->mapping, page_to_pgoff(page), compound_mapcount(page)); else pr_warn("page:%px refcount:%d mapcount:%d mapping:%px index:%#lx ", page, page_ref_count(page), mapcount, page->mapping, page_to_pgoff(page)); |
6855ac4ac
|
76 |
if (PageKsm(page)) |
2bb9bfcde
|
77 |
type = "ksm "; |
6855ac4ac
|
78 |
else if (PageAnon(page)) |
2bb9bfcde
|
79 |
type = "anon "; |
1c6fb1d89
|
80 |
else if (mapping) { |
5ae2efb1d
|
81 |
if (mapping->host && mapping->host->i_dentry.first) { |
1c6fb1d89
|
82 83 |
struct dentry *dentry; dentry = container_of(mapping->host->i_dentry.first, struct dentry, d_u.d_alias); |
76a1850e4
|
84 85 86 87 88 |
pr_warn("%ps name:\"%pd\" ", mapping->a_ops, dentry); } else pr_warn("%ps ", mapping->a_ops); |
1c6fb1d89
|
89 |
} |
edf14cdbf
|
90 |
BUILD_BUG_ON(ARRAY_SIZE(pageflag_names) != __NR_PAGEFLAGS + 1); |
ff8e81163
|
91 |
|
2bb9bfcde
|
92 93 |
pr_warn("%sflags: %#lx(%pGp) ", type, page->flags, &page->flags); |
fc36def99
|
94 |
hex_only: |
e0392cf7c
|
95 |
print_hex_dump(KERN_WARNING, "raw: ", DUMP_PREFIX_NONE, 32, |
46e8a3a08
|
96 97 |
sizeof(unsigned long), page, sizeof(struct page), false); |
82742a3a5
|
98 |
if (reason) |
e0392cf7c
|
99 100 |
pr_warn("page dumped because: %s ", reason); |
b8eceeb99
|
101 |
|
9edad6ea0
|
102 |
#ifdef CONFIG_MEMCG |
fc36def99
|
103 |
if (!page_poisoned && page->mem_cgroup) |
e0392cf7c
|
104 105 |
pr_warn("page->mem_cgroup:%px ", page->mem_cgroup); |
9edad6ea0
|
106 |
#endif |
82742a3a5
|
107 108 109 110 |
} void dump_page(struct page *page, const char *reason) { |
ff8e81163
|
111 |
__dump_page(page, reason); |
4e462112e
|
112 |
dump_page_owner(page); |
82742a3a5
|
113 114 115 116 |
} EXPORT_SYMBOL(dump_page); #ifdef CONFIG_DEBUG_VM |
82742a3a5
|
117 118 |
void dump_vma(const struct vm_area_struct *vma) { |
152a2d199
|
119 120 121 122 123 124 125 126 |
pr_emerg("vma %px start %px end %px " "next %px prev %px mm %px " "prot %lx anon_vma %px vm_ops %px " "pgoff %lx file %px private_data %px " |
b8eceeb99
|
127 128 |
"flags: %#lx(%pGv) ", |
82742a3a5
|
129 130 131 132 |
vma, (void *)vma->vm_start, (void *)vma->vm_end, vma->vm_next, vma->vm_prev, vma->vm_mm, (unsigned long)pgprot_val(vma->vm_page_prot), vma->anon_vma, vma->vm_ops, vma->vm_pgoff, |
b8eceeb99
|
133 134 |
vma->vm_file, vma->vm_private_data, vma->vm_flags, &vma->vm_flags); |
82742a3a5
|
135 136 |
} EXPORT_SYMBOL(dump_vma); |
31c9afa6d
|
137 138 |
void dump_mm(const struct mm_struct *mm) { |
7a9cdebdc
|
139 140 |
pr_emerg("mm %px mmap %px seqnum %llu task_size %lu " |
31c9afa6d
|
141 |
#ifdef CONFIG_MMU |
152a2d199
|
142 143 |
"get_unmapped_area %px " |
31c9afa6d
|
144 145 146 |
#endif "mmap_base %lu mmap_legacy_base %lu highest_vm_end %lu " |
152a2d199
|
147 148 |
"pgd %px mm_users %d mm_count %d pgtables_bytes %lu map_count %d " |
31c9afa6d
|
149 150 |
"hiwater_rss %lx hiwater_vm %lx total_vm %lx locked_vm %lx " |
70f8a3ca6
|
151 152 |
"pinned_vm %llx data_vm %lx exec_vm %lx stack_vm %lx " |
31c9afa6d
|
153 154 155 156 157 158 |
"start_code %lx end_code %lx start_data %lx end_data %lx " "start_brk %lx brk %lx start_stack %lx " "arg_start %lx arg_end %lx env_start %lx env_end %lx " |
152a2d199
|
159 160 |
"binfmt %px flags %lx core_state %px " |
31c9afa6d
|
161 |
#ifdef CONFIG_AIO |
152a2d199
|
162 163 |
"ioctx_table %px " |
31c9afa6d
|
164 165 |
#endif #ifdef CONFIG_MEMCG |
152a2d199
|
166 |
"owner %px " |
31c9afa6d
|
167 |
#endif |
152a2d199
|
168 169 |
"exe_file %px " |
31c9afa6d
|
170 |
#ifdef CONFIG_MMU_NOTIFIER |
152a2d199
|
171 172 |
"mmu_notifier_mm %px " |
31c9afa6d
|
173 174 175 176 177 |
#endif #ifdef CONFIG_NUMA_BALANCING "numa_next_scan %lu numa_scan_offset %lu numa_scan_seq %d " #endif |
31c9afa6d
|
178 179 |
"tlb_flush_pending %d " |
b8eceeb99
|
180 181 |
"def_flags: %#lx(%pGv) ", |
31c9afa6d
|
182 |
|
7a9cdebdc
|
183 |
mm, mm->mmap, (long long) mm->vmacache_seqnum, mm->task_size, |
31c9afa6d
|
184 185 186 187 188 189 |
#ifdef CONFIG_MMU mm->get_unmapped_area, #endif mm->mmap_base, mm->mmap_legacy_base, mm->highest_vm_end, mm->pgd, atomic_read(&mm->mm_users), atomic_read(&mm->mm_count), |
af5b0f6a0
|
190 |
mm_pgtables_bytes(mm), |
31c9afa6d
|
191 192 |
mm->map_count, mm->hiwater_rss, mm->hiwater_vm, mm->total_vm, mm->locked_vm, |
44dc1b1fa
|
193 |
(u64)atomic64_read(&mm->pinned_vm), |
70f8a3ca6
|
194 |
mm->data_vm, mm->exec_vm, mm->stack_vm, |
31c9afa6d
|
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
mm->start_code, mm->end_code, mm->start_data, mm->end_data, mm->start_brk, mm->brk, mm->start_stack, mm->arg_start, mm->arg_end, mm->env_start, mm->env_end, mm->binfmt, mm->flags, mm->core_state, #ifdef CONFIG_AIO mm->ioctx_table, #endif #ifdef CONFIG_MEMCG mm->owner, #endif mm->exe_file, #ifdef CONFIG_MMU_NOTIFIER mm->mmu_notifier_mm, #endif #ifdef CONFIG_NUMA_BALANCING mm->numa_next_scan, mm->numa_scan_offset, mm->numa_scan_seq, #endif |
16af97dc5
|
212 |
atomic_read(&mm->tlb_flush_pending), |
b8eceeb99
|
213 214 |
mm->def_flags, &mm->def_flags ); |
31c9afa6d
|
215 |
} |
f682a97a0
|
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
static bool page_init_poisoning __read_mostly = true; static int __init setup_vm_debug(char *str) { bool __page_init_poisoning = true; /* * Calling vm_debug with no arguments is equivalent to requesting * to enable all debugging options we can control. */ if (*str++ != '=' || !*str) goto out; __page_init_poisoning = false; if (*str == '-') goto out; while (*str) { switch (tolower(*str)) { case'p': __page_init_poisoning = true; break; default: pr_err("vm_debug option '%c' unknown. skipped ", *str); } str++; } out: if (page_init_poisoning && !__page_init_poisoning) pr_warn("Page struct poisoning disabled by kernel command line option 'vm_debug' "); page_init_poisoning = __page_init_poisoning; return 1; } __setup("vm_debug", setup_vm_debug); void page_init_poison(struct page *page, size_t size) { if (page_init_poisoning) memset(page, PAGE_POISON_PATTERN, size); } EXPORT_SYMBOL_GPL(page_init_poison); |
82742a3a5
|
263 |
#endif /* CONFIG_DEBUG_VM */ |