Skip to content

Commit fc6a128

Browse files
yhuang-intelopsiff
authored andcommitted
mm, pcp: decrease PCP high if free pages < high watermark
[ Upstream commit 57c0419 ] Conflict: none One target of PCP is to minimize pages in PCP if the system free pages is too few. To reach that target, when page reclaiming is active for the zone (ZONE_RECLAIM_ACTIVE), we will stop increasing PCP high in allocating path, decrease PCP high and free some pages in freeing path. But this may be too late because the background page reclaiming may introduce latency for some workloads. So, in this patch, during page allocation we will detect whether the number of free pages of the zone is below high watermark. If so, we will stop increasing PCP high in allocating path, decrease PCP high and free some pages in freeing path. With this, we can reduce the possibility of the premature background page reclaiming caused by too large PCP. The high watermark checking is done in allocating path to reduce the overhead in hotter freeing path. Intel-SIG: commit 57c0419 mm, pcp: decrease PCP high if free pages < high watermark. Backport Auto-tune per-CPU pageset size. Link: https://lkml.kernel.org/r/20231016053002.756205-9-ying.huang@intel.com Signed-off-by: "Huang, Ying" <ying.huang@intel.com> Cc: Mel Gorman <mgorman@techsingularity.net> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: David Hildenbrand <david@redhat.com> Cc: Johannes Weiner <jweiner@redhat.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Michal Hocko <mhocko@suse.com> Cc: Pavel Tatashin <pasha.tatashin@soleen.com> Cc: Matthew Wilcox <willy@infradead.org> Cc: Christoph Lameter <cl@linux.com> Cc: Arjan van de Ven <arjan@linux.intel.com> Cc: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> [ Aubrey Li: amend commit log ] Signed-off-by: Aubrey Li <aubrey.li@linux.intel.com>
1 parent 3eb5ca2 commit fc6a128

2 files changed

Lines changed: 32 additions & 2 deletions

File tree

include/linux/mmzone.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,7 @@ enum zone_flags {
10331033
* Cleared when kswapd is woken.
10341034
*/
10351035
ZONE_RECLAIM_ACTIVE, /* kswapd may be scanning the zone. */
1036+
ZONE_BELOW_HIGH, /* zone is below high watermark. */
10361037
};
10371038

10381039
static inline unsigned long zone_managed_pages(struct zone *zone)

mm/page_alloc.c

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2432,7 +2432,13 @@ static int nr_pcp_high(struct per_cpu_pages *pcp, struct zone *zone,
24322432
return min(batch << 2, pcp->high);
24332433
}
24342434

2435-
if (pcp->count >= high && high_min != high_max) {
2435+
if (high_min == high_max)
2436+
return high;
2437+
2438+
if (test_bit(ZONE_BELOW_HIGH, &zone->flags)) {
2439+
pcp->high = max(high - (batch << pcp->free_factor), high_min);
2440+
high = max(pcp->count, high_min);
2441+
} else if (pcp->count >= high) {
24362442
int need_high = (batch << pcp->free_factor) + batch;
24372443

24382444
/* pcp->high should be large enough to hold batch freed pages */
@@ -2482,6 +2488,10 @@ static void free_unref_page_commit(struct zone *zone, struct per_cpu_pages *pcp,
24822488
if (pcp->count >= high) {
24832489
free_pcppages_bulk(zone, nr_pcp_free(pcp, batch, high, free_high),
24842490
pcp, pindex);
2491+
if (test_bit(ZONE_BELOW_HIGH, &zone->flags) &&
2492+
zone_watermark_ok(zone, 0, high_wmark_pages(zone),
2493+
ZONE_MOVABLE, 0))
2494+
clear_bit(ZONE_BELOW_HIGH, &zone->flags);
24852495
}
24862496
}
24872497

@@ -2788,7 +2798,7 @@ static int nr_pcp_alloc(struct per_cpu_pages *pcp, struct zone *zone, int order)
27882798
* If we had larger pcp->high, we could avoid to allocate from
27892799
* zone.
27902800
*/
2791-
if (high_min != high_max && !test_bit(ZONE_RECLAIM_ACTIVE, &zone->flags))
2801+
if (high_min != high_max && !test_bit(ZONE_BELOW_HIGH, &zone->flags))
27922802
high = pcp->high = min(high + batch, high_max);
27932803

27942804
if (!order) {
@@ -3249,6 +3259,25 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
32493259

32503260
cond_accept_memory(zone, order);
32513261

3262+
/*
3263+
* Detect whether the number of free pages is below high
3264+
* watermark. If so, we will decrease pcp->high and free
3265+
* PCP pages in free path to reduce the possibility of
3266+
* premature page reclaiming. Detection is done here to
3267+
* avoid to do that in hotter free path.
3268+
*/
3269+
if (test_bit(ZONE_BELOW_HIGH, &zone->flags))
3270+
goto check_alloc_wmark;
3271+
3272+
mark = high_wmark_pages(zone);
3273+
if (zone_watermark_fast(zone, order, mark,
3274+
ac->highest_zoneidx, alloc_flags,
3275+
gfp_mask))
3276+
goto try_this_zone;
3277+
else
3278+
set_bit(ZONE_BELOW_HIGH, &zone->flags);
3279+
3280+
check_alloc_wmark:
32523281
mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK);
32533282
if (!zone_watermark_fast(zone, order, mark,
32543283
ac->highest_zoneidx, alloc_flags,

0 commit comments

Comments
 (0)