Skip to content

Commit a579086

Browse files
yuzhaogoogleakpm00
authored andcommitted
mm: multi-gen LRU: remove eviction fairness safeguard
Recall that the eviction consumes the oldest generation: first it bucket-sorts folios whose gen counters were updated by the aging and reclaims the rest; then it increments lrugen->min_seq. The current eviction fairness safeguard for global reclaim has a dilemma: when there are multiple eligible memcgs, should it continue or stop upon meeting the reclaim goal? If it continues, it overshoots and increases direct reclaim latency; if it stops, it loses fairness between memcgs it has taken memory away from and those it has yet to. With memcg LRU, the eviction, while ensuring eventual fairness, will stop upon meeting its goal. Therefore the current eviction fairness safeguard for global reclaim will not be needed. Note that memcg LRU only applies to global reclaim. For memcg reclaim, the eviction will continue, even if it is overshooting. This becomes unconditional due to code simplification. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Yu Zhao <[email protected]> Cc: Johannes Weiner <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Michael Larabel <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Roman Gushchin <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 6df1b22 commit a579086

File tree

1 file changed

+23
-58
lines changed

1 file changed

+23
-58
lines changed

mm/vmscan.c

Lines changed: 23 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,11 @@ static bool cgroup_reclaim(struct scan_control *sc)
449449
return sc->target_mem_cgroup;
450450
}
451451

452+
static bool global_reclaim(struct scan_control *sc)
453+
{
454+
return !sc->target_mem_cgroup || mem_cgroup_is_root(sc->target_mem_cgroup);
455+
}
456+
452457
/**
453458
* writeback_throttling_sane - is the usual dirty throttling mechanism available?
454459
* @sc: scan_control in question
@@ -499,6 +504,11 @@ static bool cgroup_reclaim(struct scan_control *sc)
499504
return false;
500505
}
501506

507+
static bool global_reclaim(struct scan_control *sc)
508+
{
509+
return true;
510+
}
511+
502512
static bool writeback_throttling_sane(struct scan_control *sc)
503513
{
504514
return true;
@@ -5006,8 +5016,7 @@ static int isolate_folios(struct lruvec *lruvec, struct scan_control *sc, int sw
50065016
return scanned;
50075017
}
50085018

5009-
static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness,
5010-
bool *need_swapping)
5019+
static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swappiness)
50115020
{
50125021
int type;
50135022
int scanned;
@@ -5096,9 +5105,6 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap
50965105
goto retry;
50975106
}
50985107

5099-
if (need_swapping && type == LRU_GEN_ANON)
5100-
*need_swapping = true;
5101-
51025108
return scanned;
51035109
}
51045110

@@ -5138,67 +5144,26 @@ static unsigned long get_nr_to_scan(struct lruvec *lruvec, struct scan_control *
51385144
return min_seq[!can_swap] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0;
51395145
}
51405146

5141-
static bool should_abort_scan(struct lruvec *lruvec, unsigned long seq,
5142-
struct scan_control *sc, bool need_swapping)
5147+
static unsigned long get_nr_to_reclaim(struct scan_control *sc)
51435148
{
5144-
int i;
5145-
DEFINE_MAX_SEQ(lruvec);
5146-
5147-
if (!current_is_kswapd()) {
5148-
/* age each memcg at most once to ensure fairness */
5149-
if (max_seq - seq > 1)
5150-
return true;
5151-
5152-
/* over-swapping can increase allocation latency */
5153-
if (sc->nr_reclaimed >= sc->nr_to_reclaim && need_swapping)
5154-
return true;
5155-
5156-
/* give this thread a chance to exit and free its memory */
5157-
if (fatal_signal_pending(current)) {
5158-
sc->nr_reclaimed += MIN_LRU_BATCH;
5159-
return true;
5160-
}
5161-
5162-
if (cgroup_reclaim(sc))
5163-
return false;
5164-
} else if (sc->nr_reclaimed - sc->last_reclaimed < sc->nr_to_reclaim)
5165-
return false;
5166-
5167-
/* keep scanning at low priorities to ensure fairness */
5168-
if (sc->priority > DEF_PRIORITY - 2)
5169-
return false;
5170-
5171-
/*
5172-
* A minimum amount of work was done under global memory pressure. For
5173-
* kswapd, it may be overshooting. For direct reclaim, the allocation
5174-
* may succeed if all suitable zones are somewhat safe. In either case,
5175-
* it's better to stop now, and restart later if necessary.
5176-
*/
5177-
for (i = 0; i <= sc->reclaim_idx; i++) {
5178-
unsigned long wmark;
5179-
struct zone *zone = lruvec_pgdat(lruvec)->node_zones + i;
5180-
5181-
if (!managed_zone(zone))
5182-
continue;
5183-
5184-
wmark = current_is_kswapd() ? high_wmark_pages(zone) : low_wmark_pages(zone);
5185-
if (wmark > zone_page_state(zone, NR_FREE_PAGES))
5186-
return false;
5187-
}
5149+
/* don't abort memcg reclaim to ensure fairness */
5150+
if (!global_reclaim(sc))
5151+
return -1;
51885152

5189-
sc->nr_reclaimed += MIN_LRU_BATCH;
5153+
/* discount the previous progress for kswapd */
5154+
if (current_is_kswapd())
5155+
return sc->nr_to_reclaim + sc->last_reclaimed;
51905156

5191-
return true;
5157+
return max(sc->nr_to_reclaim, compact_gap(sc->order));
51925158
}
51935159

51945160
static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
51955161
{
51965162
struct blk_plug plug;
51975163
bool need_aging = false;
5198-
bool need_swapping = false;
51995164
unsigned long scanned = 0;
52005165
unsigned long reclaimed = sc->nr_reclaimed;
5201-
DEFINE_MAX_SEQ(lruvec);
5166+
unsigned long nr_to_reclaim = get_nr_to_reclaim(sc);
52025167

52035168
lru_add_drain();
52045169

@@ -5222,15 +5187,15 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
52225187
if (!nr_to_scan)
52235188
goto done;
52245189

5225-
delta = evict_folios(lruvec, sc, swappiness, &need_swapping);
5190+
delta = evict_folios(lruvec, sc, swappiness);
52265191
if (!delta)
52275192
goto done;
52285193

52295194
scanned += delta;
52305195
if (scanned >= nr_to_scan)
52315196
break;
52325197

5233-
if (should_abort_scan(lruvec, max_seq, sc, need_swapping))
5198+
if (sc->nr_reclaimed >= nr_to_reclaim)
52345199
break;
52355200

52365201
cond_resched();
@@ -5677,7 +5642,7 @@ static int run_eviction(struct lruvec *lruvec, unsigned long seq, struct scan_co
56775642
if (sc->nr_reclaimed >= nr_to_reclaim)
56785643
return 0;
56795644

5680-
if (!evict_folios(lruvec, sc, swappiness, NULL))
5645+
if (!evict_folios(lruvec, sc, swappiness))
56815646
return 0;
56825647

56835648
cond_resched();

0 commit comments

Comments
 (0)