Skip to content

Commit 10ca291

Browse files
Charan Teja Reddygregkh
authored andcommitted
mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
commit f80b08f upstream. When boosting is enabled, it is observed that rate of atomic order-0 allocation failures are high due to the fact that free levels in the system are checked with ->watermark_boost offset. This is not a problem for sleepable allocations but for atomic allocations which looks like regression. This problem is seen frequently on system setup of Android kernel running on Snapdragon hardware with 4GB RAM size. When no extfrag event occurred in the system, ->watermark_boost factor is zero, thus the watermark configurations in the system are: _watermark = ( [WMARK_MIN] = 1272, --> ~5MB [WMARK_LOW] = 9067, --> ~36MB [WMARK_HIGH] = 9385), --> ~38MB watermark_boost = 0 After launching some memory hungry applications in Android which can cause extfrag events in the system to an extent that ->watermark_boost can be set to max i.e. default boost factor makes it to 150% of high watermark. _watermark = ( [WMARK_MIN] = 1272, --> ~5MB [WMARK_LOW] = 9067, --> ~36MB [WMARK_HIGH] = 9385), --> ~38MB watermark_boost = 14077, -->~57MB With default system configuration, for an atomic order-0 allocation to succeed, having free memory of ~2MB will suffice. But boosting makes the min_wmark to ~61MB thus for an atomic order-0 allocation to be successful system should have minimum of ~23MB of free memory(from calculations of zone_watermark_ok(), min = 3/4(min/2)). But failures are observed despite system is having ~20MB of free memory. In the testing, this is reproducible as early as first 300secs since boot and with furtherlowram configurations(<2GB) it is observed as early as first 150secs since boot. These failures can be avoided by excluding the ->watermark_boost in watermark caluculations for atomic order-0 allocations. [akpm@linux-foundation.org: fix comment grammar, reflow comment] [charante@codeaurora.org: fix suggested by Mel Gorman] Link: http://lkml.kernel.org/r/31556793-57b1-1c21-1a9d-22674d9bd938@codeaurora.org Signed-off-by: Charan Teja Reddy <charante@codeaurora.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Vinayak Menon <vinmenon@codeaurora.org> Cc: Mel Gorman <mgorman@techsingularity.net> Link: http://lkml.kernel.org/r/1589882284-21010-1-git-send-email-charante@codeaurora.org Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Ralph Siemsen <ralph.siemsen@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent a276147 commit 10ca291

1 file changed

Lines changed: 21 additions & 4 deletions

File tree

mm/page_alloc.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3484,7 +3484,8 @@ bool zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
34843484
}
34853485

34863486
static inline bool zone_watermark_fast(struct zone *z, unsigned int order,
3487-
unsigned long mark, int classzone_idx, unsigned int alloc_flags)
3487+
unsigned long mark, int classzone_idx,
3488+
unsigned int alloc_flags, gfp_t gfp_mask)
34883489
{
34893490
long free_pages = zone_page_state(z, NR_FREE_PAGES);
34903491
long cma_pages = 0;
@@ -3505,8 +3506,23 @@ static inline bool zone_watermark_fast(struct zone *z, unsigned int order,
35053506
if (!order && (free_pages - cma_pages) > mark + z->lowmem_reserve[classzone_idx])
35063507
return true;
35073508

3508-
return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
3509-
free_pages);
3509+
if (__zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
3510+
free_pages))
3511+
return true;
3512+
/*
3513+
* Ignore watermark boosting for GFP_ATOMIC order-0 allocations
3514+
* when checking the min watermark. The min watermark is the
3515+
* point where boosting is ignored so that kswapd is woken up
3516+
* when below the low watermark.
3517+
*/
3518+
if (unlikely(!order && (gfp_mask & __GFP_ATOMIC) && z->watermark_boost
3519+
&& ((alloc_flags & ALLOC_WMARK_MASK) == WMARK_MIN))) {
3520+
mark = z->_watermark[WMARK_MIN];
3521+
return __zone_watermark_ok(z, order, mark, classzone_idx,
3522+
alloc_flags, free_pages);
3523+
}
3524+
3525+
return false;
35103526
}
35113527

35123528
bool zone_watermark_ok_safe(struct zone *z, unsigned int order,
@@ -3647,7 +3663,8 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
36473663

36483664
mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK);
36493665
if (!zone_watermark_fast(zone, order, mark,
3650-
ac_classzone_idx(ac), alloc_flags)) {
3666+
ac_classzone_idx(ac), alloc_flags,
3667+
gfp_mask)) {
36513668
int ret;
36523669

36533670
#ifdef CONFIG_DEFERRED_STRUCT_PAGE_INIT

0 commit comments

Comments
 (0)