aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQian Cai <cai@lca.pw>2019-04-18 20:50:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-04-19 12:46:05 -0400
commit1a9f219157b22d0ffb340a9c5f431afd02cd2cf3 (patch)
treebcec3e46bee3f4c1761529ef82fc1e26d736c9ee
parent68545aa1cda847c4fdda7e49331807f99f799838 (diff)
mm/hotplug: treat CMA pages as unmovable
has_unmovable_pages() is used by allocating CMA and gigantic pages as well as the memory hotplug. The later doesn't know how to offline CMA pool properly now, but if an unused (free) CMA page is encountered, then has_unmovable_pages() happily considers it as a free memory and propagates this up the call chain. Memory offlining code then frees the page without a proper CMA tear down which leads to an accounting issues. Moreover if the same memory range is onlined again then the memory never gets back to the CMA pool. State after memory offline: # grep cma /proc/vmstat nr_free_cma 205824 # cat /sys/kernel/debug/cma/cma-kvm_cma/count 209920 Also, kmemleak still think those memory address are reserved below but have already been used by the buddy allocator after onlining. This patch fixes the situation by treating CMA pageblocks as unmovable except when has_unmovable_pages() is called as part of CMA allocation. Offlined Pages 4096 kmemleak: Cannot insert 0xc000201f7d040008 into the object search tree (overlaps existing) Call Trace: dump_stack+0xb0/0xf4 (unreliable) create_object+0x344/0x380 __kmalloc_node+0x3ec/0x860 kvmalloc_node+0x58/0x110 seq_read+0x41c/0x620 __vfs_read+0x3c/0x70 vfs_read+0xbc/0x1a0 ksys_read+0x7c/0x140 system_call+0x5c/0x70 kmemleak: Kernel memory leak detector disabled kmemleak: Object 0xc000201cc8000000 (size 13757317120): kmemleak: comm "swapper/0", pid 0, jiffies 4294937297 kmemleak: min_count = -1 kmemleak: count = 0 kmemleak: flags = 0x5 kmemleak: checksum = 0 kmemleak: backtrace: cma_declare_contiguous+0x2a4/0x3b0 kvm_cma_reserve+0x11c/0x134 setup_arch+0x300/0x3f8 start_kernel+0x9c/0x6e8 start_here_common+0x1c/0x4b0 kmemleak: Automatic memory scanning thread ended [cai@lca.pw: use is_migrate_cma_page() and update commit log] Link: http://lkml.kernel.org/r/20190416170510.20048-1-cai@lca.pw Link: http://lkml.kernel.org/r/20190413002623.8967-1-cai@lca.pw Signed-off-by: Qian Cai <cai@lca.pw> Acked-by: Michal Hocko <mhocko@suse.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Reviewed-by: Oscar Salvador <osalvador@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/page_alloc.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index d96ca5bc555b..c6ce20aaf80b 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -8005,7 +8005,10 @@ void *__init alloc_large_system_hash(const char *tablename,
8005bool has_unmovable_pages(struct zone *zone, struct page *page, int count, 8005bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
8006 int migratetype, int flags) 8006 int migratetype, int flags)
8007{ 8007{
8008 unsigned long pfn, iter, found; 8008 unsigned long found;
8009 unsigned long iter = 0;
8010 unsigned long pfn = page_to_pfn(page);
8011 const char *reason = "unmovable page";
8009 8012
8010 /* 8013 /*
8011 * TODO we could make this much more efficient by not checking every 8014 * TODO we could make this much more efficient by not checking every
@@ -8015,17 +8018,20 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
8015 * can still lead to having bootmem allocations in zone_movable. 8018 * can still lead to having bootmem allocations in zone_movable.
8016 */ 8019 */
8017 8020
8018 /* 8021 if (is_migrate_cma_page(page)) {
8019 * CMA allocations (alloc_contig_range) really need to mark isolate 8022 /*
8020 * CMA pageblocks even when they are not movable in fact so consider 8023 * CMA allocations (alloc_contig_range) really need to mark
8021 * them movable here. 8024 * isolate CMA pageblocks even when they are not movable in fact
8022 */ 8025 * so consider them movable here.
8023 if (is_migrate_cma(migratetype) && 8026 */
8024 is_migrate_cma(get_pageblock_migratetype(page))) 8027 if (is_migrate_cma(migratetype))
8025 return false; 8028 return false;
8029
8030 reason = "CMA page";
8031 goto unmovable;
8032 }
8026 8033
8027 pfn = page_to_pfn(page); 8034 for (found = 0; iter < pageblock_nr_pages; iter++) {
8028 for (found = 0, iter = 0; iter < pageblock_nr_pages; iter++) {
8029 unsigned long check = pfn + iter; 8035 unsigned long check = pfn + iter;
8030 8036
8031 if (!pfn_valid_within(check)) 8037 if (!pfn_valid_within(check))
@@ -8105,7 +8111,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
8105unmovable: 8111unmovable:
8106 WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE); 8112 WARN_ON_ONCE(zone_idx(zone) == ZONE_MOVABLE);
8107 if (flags & REPORT_FAILURE) 8113 if (flags & REPORT_FAILURE)
8108 dump_page(pfn_to_page(pfn+iter), "unmovable page"); 8114 dump_page(pfn_to_page(pfn + iter), reason);
8109 return true; 8115 return true;
8110} 8116}
8111 8117