On Fri, Apr 30, 2021 at 12:01 AM Andrew Morton <akpm@linux-foundation.org> wrote: > > From: Minchan Kim <minchan@kernel.org> > Subject: 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]. > FWIW, the "format ^$prefix" specifier allows selection of "classes" of pr_debugs examples: "^drm:kms:" etc "^drm:" too, for example to set +fmlt across entire subsystem "gvt:" "^Lo", "^MID", "^HI" "^1:", "^2:", "^3:" all hierarchy / set-creation is applied by authors
--- a/mm/page_alloc.c~mm-page_alloc-dump-migrate-failed-pages +++ a/mm/page_alloc.c @@ -8497,6 +8497,27 @@ static unsigned long pfn_max_align_up(un 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) @@ -8540,6 +8561,7 @@ static int __alloc_contig_migrate_range( 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; }