2021-03-11 19:42:49

by Minchan Kim

[permalink] [raw]
Subject: [PATCH v5] mm: page_alloc: dump migrate-failed pages

Currently, debugging CMA allocation failures is quite limited.
The most common source of these failures seems to be page
migration which doesn't provide any useful information on the
reason of the failure by itself. alloc_contig_range can report
those failures as it holds a list of migrate-failed pages.

The information logged by dump_page() has already proven helpful
for debugging allocation issues, like identifying long-term
pinnings on ZONE_MOVABLE or MIGRATE_CMA.

Let's use the dynamic debugging infrastructure, such that we
avoid flooding the logs and creating a lot of noise on frequent
alloc_contig_range() calls. This information is helpful for
debugging only.

There are two ifdefery conditions to support common dyndbg options:

- CONFIG_DYNAMIC_DEBUG_CORE && DYNAMIC_DEBUG_MODULE
It aims for supporting the feature with only specific file
with adding ccflags.

- CONFIG_DYNAMIC_DEBUG
It aims for supporting the feature with system wide globally.

A simple example to enable the feature:

Admin could enable the dump like this(by default, disabled)

echo "func alloc_contig_dump_pages +p" > control

Admin could disable it.

echo "func alloc_contig_dump_pages =_" > control

Detail goes Documentation/admin-guide/dynamic-debug-howto.rst

A concern is utility functions in dump_page use inconsistent
loglevels. In the future, we might want to make the loglevels
used inside dump_page() consistent and eventually rework the way
we log the information here. See [1].

[1] https://lore.kernel.org/linux-mm/[email protected]/

Reviewed-by: David Hildenbrand <[email protected]>
Signed-off-by: Minchan Kim <[email protected]>
---
* from v4 - https://lore.kernel.org/linux-mm/[email protected]/
* better description - david
* add reviewed-by - david

* from v3 - https://lore.kernel.org/linux-mm/[email protected]
* add dyndgb usage comment - akpm
* use dumpstack instead of warn_on - david

* from v2 - https://lore.kernel.org/linux-mm/[email protected]/
* remove ratelimit - mhocko

* from v1 - https://lore.kernel.org/linux-mm/[email protected]/
* use dynamic debugging with system wide instead of per-call site - mhocko

mm/page_alloc.c | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3e4b29ee2b1e..d4b72b6682b6 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -8453,6 +8453,27 @@ static unsigned long pfn_max_align_up(unsigned long pfn)
pageblock_nr_pages));
}

+#if defined(CONFIG_DYNAMIC_DEBUG) || \
+ (defined(CONFIG_DYNAMIC_DEBUG_CORE) && defined(DYNAMIC_DEBUG_MODULE))
+/* Usage: See admin-guide/dynamic-debug-howto.rst */
+static void alloc_contig_dump_pages(struct list_head *page_list)
+{
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, "migrate failure");
+
+ if (DYNAMIC_DEBUG_BRANCH(descriptor)) {
+ struct page *page;
+
+ dump_stack();
+ list_for_each_entry(page, page_list, lru)
+ dump_page(page, "migration failure");
+ }
+}
+#else
+static inline void alloc_contig_dump_pages(struct list_head *page_list)
+{
+}
+#endif
+
/* [start, end) must belong to a single zone. */
static int __alloc_contig_migrate_range(struct compact_control *cc,
unsigned long start, unsigned long end)
@@ -8496,6 +8517,7 @@ static int __alloc_contig_migrate_range(struct compact_control *cc,
NULL, (unsigned long)&mtc, cc->mode, MR_CONTIG_RANGE);
}
if (ret < 0) {
+ alloc_contig_dump_pages(&cc->migratepages);
putback_movable_pages(&cc->migratepages);
return ret;
}
--
2.31.0.rc2.261.g7f71774620-goog