Skip to content

Commit 1d91df8

Browse files
JoonsooKimtorvalds
authored andcommitted
mm/page_alloc: handle a missing case for memalloc_nocma_{save/restore} APIs
memalloc_nocma_{save/restore} APIs can be used to skip page allocation on CMA area, but, there is a missing case and the page on CMA area could be allocated even if APIs are used. This patch handles this case to fix the potential issue. For now, these APIs are used to prevent long-term pinning on the CMA page. When the long-term pinning is requested on the CMA page, it is migrated to the non-CMA page before pinning. This non-CMA page is allocated by using memalloc_nocma_{save/restore} APIs. If APIs doesn't work as intended, the CMA page is allocated and it is pinned for a long time. This long-term pin for the CMA page causes cma_alloc() failure and it could result in wrong behaviour on the device driver who uses the cma_alloc(). Missing case is an allocation from the pcplist. MIGRATE_MOVABLE pcplist could have the pages on CMA area so we need to skip it if ALLOC_CMA isn't specified. Fixes: 8510e69 (mm/page_alloc: fix memalloc_nocma_{save/restore} APIs) Signed-off-by: Joonsoo Kim <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Acked-by: Michal Hocko <[email protected]> Cc: "Aneesh Kumar K . V" <[email protected]> Cc: Mel Gorman <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent 484cfac commit 1d91df8

File tree

1 file changed

+16
-3
lines changed

1 file changed

+16
-3
lines changed

mm/page_alloc.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3367,9 +3367,16 @@ struct page *rmqueue(struct zone *preferred_zone,
33673367
struct page *page;
33683368

33693369
if (likely(order == 0)) {
3370-
page = rmqueue_pcplist(preferred_zone, zone, gfp_flags,
3370+
/*
3371+
* MIGRATE_MOVABLE pcplist could have the pages on CMA area and
3372+
* we need to skip it when CMA area isn't allowed.
3373+
*/
3374+
if (!IS_ENABLED(CONFIG_CMA) || alloc_flags & ALLOC_CMA ||
3375+
migratetype != MIGRATE_MOVABLE) {
3376+
page = rmqueue_pcplist(preferred_zone, zone, gfp_flags,
33713377
migratetype, alloc_flags);
3372-
goto out;
3378+
goto out;
3379+
}
33733380
}
33743381

33753382
/*
@@ -3381,7 +3388,13 @@ struct page *rmqueue(struct zone *preferred_zone,
33813388

33823389
do {
33833390
page = NULL;
3384-
if (alloc_flags & ALLOC_HARDER) {
3391+
/*
3392+
* order-0 request can reach here when the pcplist is skipped
3393+
* due to non-CMA allocation context. HIGHATOMIC area is
3394+
* reserved for high-order atomic allocation, so order-0
3395+
* request should skip it.
3396+
*/
3397+
if (order > 0 && alloc_flags & ALLOC_HARDER) {
33853398
page = __rmqueue_smallest(zone, order, MIGRATE_HIGHATOMIC);
33863399
if (page)
33873400
trace_mm_page_alloc_zone_locked(page, order, migratetype);

0 commit comments

Comments
 (0)