[PATCH] mm/compaction: add check mechanism to avoid cma alloc fail

Baolin Wang baolin.wang at linux.alibaba.com
Sun Jan 21 22:59:20 PST 2024


On 1/22/2024 10:23 AM, Haiqiang Gong wrote:
> cma alloc may fail when we doing cma alloc/free test on kernel 5.10/5.15.

Do you have a real use case for the cma alloc issue? And have you tried 
it on the new kernel?

> We found that the next memory cannot be migrated because of the alloc of
> fs as next backtrace:
> __alloc_pages_nodemask
> pagecache_get_page
> grow_dev_page
> __getblk_gfp
> ext4_sb_breadahead_unmovable
> __ext4_get_inode_loc
> __ext4_iget
> ext4_lookup
> __lookup_slow
> walk_component
> path_lookupat
> filename_lookup
> vfs_statx
> This kind of unmovable memory is not placed in the cma buffer when kernel
> memory alloc but is migrated in by kcompactd when the kernel migration.
> It will cause memory can't be migrate when cma alloc.

Why the CMA memory can not be migrated? Could you describe in more 
detail the reasons for the CMA memory migration failure?

> Add check mechanism in the compaction_alloc() where kcompaced alloc for
> memory. Will return NULL and give up this memory migration if the
> allocated memory is in the cma buffer and the memory is unmovable.
> 
> Signed-off-by: Haiqiang Gong <Haiqiang.Gong at mediatek.com>
> ---
>   mm/compaction.c | 38 ++++++++++++++++++++++++++++++++++++++
>   1 file changed, 38 insertions(+)
> 
> diff --git a/mm/compaction.c b/mm/compaction.c
> index 27ada42924d5..29c0661adc22 100644
> --- a/mm/compaction.c
> +++ b/mm/compaction.c
> @@ -25,6 +25,11 @@
>   #include <linux/psi.h>
>   #include "internal.h"
>   
> +#ifdef CONFIG_CMA
> +#include <linux/cma.h>
> +#include "cma.h"
> +#endif
> +
>   #ifdef CONFIG_COMPACTION
>   /*
>    * Fragmentation score check interval for proactive compaction purposes.
> @@ -1758,6 +1763,33 @@ static void isolate_freepages(struct compact_control *cc)
>   	split_map_pages(freelist);
>   }
>   
> +#ifdef CONFIG_CMA
> +static bool is_in_cma_range(struct folio *folio)
> +{
> +	int i;
> +	unsigned long pfn = 0;
> +	struct page *page = folio_page(folio, 0);
> +
> +	pfn = page_to_pfn(page);
> +	for (i = 0; i < cma_area_count; i++) {
> +		struct cma *cma = &cma_areas[i];
> +
> +		if (cma->base_pfn <= pfn && (cma->base_pfn + cma->count) > pfn)
> +			return true;
> +	}
> +
> +	return false;
> +}
> +
> +static bool forbid_move_to_cma_range(struct folio *src, struct folio *dst)
> +{
> +	if (folio_mapping(src) && is_in_cma_range(dst))
> +		return true;
> +
> +	return false;
> +}
> +#endif
> +
>   /*
>    * This is a migrate-callback that "allocates" freepages by taking pages
>    * from the isolated freelists in the block we are migrating to.
> @@ -1775,6 +1807,12 @@ static struct folio *compaction_alloc(struct folio *src, unsigned long data)
>   	}
>   
>   	dst = list_entry(cc->freepages.next, struct folio, lru);
> +#ifdef CONFIG_CMA
> +	if (forbid_move_to_cma_range(src, dst)) {
> +		pr_notice("kcompactd: could not move non-cma memory to cma buffer\n");
> +		return NULL;
> +	}
> +#endif
>   	list_del(&dst->lru);
>   	cc->nr_freepages--;
>   



More information about the linux-arm-kernel mailing list