diff --git a/mm/compaction.c b/mm/compaction.c index 027eb794e747f5efa3c7b243bf4bf8b828209e52..1be7928af62b57fd83937b698a2e7d488e12ea9f 100644 --- a/mm/compaction.c +++ b/mm/compaction.c @@ -2529,6 +2529,14 @@ static enum compact_result compact_zone_order(struct zone *zone, int order, */ WRITE_ONCE(current->capture_control, NULL); *capture = READ_ONCE(capc.page); + /* + * Technically, it is also possible that compaction is skipped but + * the page is still captured out of luck(IRQ came and freed the page). + * Returning COMPACT_SUCCESS in such cases helps in properly accounting + * the COMPACT[STALL|FAIL] when compaction is skipped. + */ + if (*capture) + ret = COMPACT_SUCCESS; return ret; } diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 19cdd8a829dcab5f4f0e3757e7222cd58932f15f..64d4aae2a78abcd7903ba9c13fffcd8ac3198b39 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -4204,6 +4204,8 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order, memalloc_noreclaim_restore(noreclaim_flag); psi_memstall_leave(&pflags); + if (*compact_result == COMPACT_SKIPPED) + return NULL; /* * At least in one zone compaction wasn't deferred or skipped, so let's * count a compaction stall