@@ -137,7 +137,6 @@ struct scan_control {
137
137
138
138
#ifdef CONFIG_LRU_GEN
139
139
/* help kswapd make better choices among multiple memcgs */
140
- unsigned int memcgs_need_aging :1 ;
141
140
unsigned long last_reclaimed ;
142
141
#endif
143
142
@@ -4468,7 +4467,7 @@ static bool try_to_inc_max_seq(struct lruvec *lruvec, unsigned long max_seq,
4468
4467
return true;
4469
4468
}
4470
4469
4471
- static bool should_run_aging (struct lruvec * lruvec , unsigned long max_seq , unsigned long * min_seq ,
4470
+ static bool should_run_aging (struct lruvec * lruvec , unsigned long max_seq ,
4472
4471
struct scan_control * sc , bool can_swap , unsigned long * nr_to_scan )
4473
4472
{
4474
4473
int gen , type , zone ;
@@ -4477,6 +4476,13 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
4477
4476
unsigned long total = 0 ;
4478
4477
struct lru_gen_folio * lrugen = & lruvec -> lrugen ;
4479
4478
struct mem_cgroup * memcg = lruvec_memcg (lruvec );
4479
+ DEFINE_MIN_SEQ (lruvec );
4480
+
4481
+ /* whether this lruvec is completely out of cold folios */
4482
+ if (min_seq [!can_swap ] + MIN_NR_GENS > max_seq ) {
4483
+ * nr_to_scan = 0 ;
4484
+ return true;
4485
+ }
4480
4486
4481
4487
for (type = !can_swap ; type < ANON_AND_FILE ; type ++ ) {
4482
4488
unsigned long seq ;
@@ -4505,8 +4511,6 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
4505
4511
* stalls when the number of generations reaches MIN_NR_GENS. Hence, the
4506
4512
* ideal number of generations is MIN_NR_GENS+1.
4507
4513
*/
4508
- if (min_seq [!can_swap ] + MIN_NR_GENS > max_seq )
4509
- return true;
4510
4514
if (min_seq [!can_swap ] + MIN_NR_GENS < max_seq )
4511
4515
return false;
4512
4516
@@ -4525,40 +4529,54 @@ static bool should_run_aging(struct lruvec *lruvec, unsigned long max_seq, unsig
4525
4529
return false;
4526
4530
}
4527
4531
4528
- static bool age_lruvec (struct lruvec * lruvec , struct scan_control * sc , unsigned long min_ttl )
4532
+ static bool lruvec_is_sizable (struct lruvec * lruvec , struct scan_control * sc )
4529
4533
{
4530
- bool need_aging ;
4531
- unsigned long nr_to_scan ;
4532
- int swappiness = get_swappiness (lruvec , sc );
4534
+ int gen , type , zone ;
4535
+ unsigned long total = 0 ;
4536
+ bool can_swap = get_swappiness (lruvec , sc );
4537
+ struct lru_gen_folio * lrugen = & lruvec -> lrugen ;
4533
4538
struct mem_cgroup * memcg = lruvec_memcg (lruvec );
4534
4539
DEFINE_MAX_SEQ (lruvec );
4535
4540
DEFINE_MIN_SEQ (lruvec );
4536
4541
4537
- VM_WARN_ON_ONCE (sc -> memcg_low_reclaim );
4542
+ for (type = !can_swap ; type < ANON_AND_FILE ; type ++ ) {
4543
+ unsigned long seq ;
4538
4544
4539
- mem_cgroup_calculate_protection (NULL , memcg );
4545
+ for (seq = min_seq [type ]; seq <= max_seq ; seq ++ ) {
4546
+ gen = lru_gen_from_seq (seq );
4540
4547
4541
- if (mem_cgroup_below_min (NULL , memcg ))
4542
- return false;
4548
+ for (zone = 0 ; zone < MAX_NR_ZONES ; zone ++ )
4549
+ total += max (READ_ONCE (lrugen -> nr_pages [gen ][type ][zone ]), 0L );
4550
+ }
4551
+ }
4543
4552
4544
- need_aging = should_run_aging (lruvec , max_seq , min_seq , sc , swappiness , & nr_to_scan );
4553
+ /* whether the size is big enough to be helpful */
4554
+ return mem_cgroup_online (memcg ) ? (total >> sc -> priority ) : total ;
4555
+ }
4545
4556
4546
- if (min_ttl ) {
4547
- int gen = lru_gen_from_seq (min_seq [LRU_GEN_FILE ]);
4548
- unsigned long birth = READ_ONCE (lruvec -> lrugen .timestamps [gen ]);
4557
+ static bool lruvec_is_reclaimable (struct lruvec * lruvec , struct scan_control * sc ,
4558
+ unsigned long min_ttl )
4559
+ {
4560
+ int gen ;
4561
+ unsigned long birth ;
4562
+ struct mem_cgroup * memcg = lruvec_memcg (lruvec );
4563
+ DEFINE_MIN_SEQ (lruvec );
4549
4564
4550
- if (time_is_after_jiffies (birth + min_ttl ))
4551
- return false;
4565
+ VM_WARN_ON_ONCE (sc -> memcg_low_reclaim );
4552
4566
4553
- /* the size is likely too small to be helpful */
4554
- if (!nr_to_scan && sc -> priority != DEF_PRIORITY )
4555
- return false;
4556
- }
4567
+ /* see the comment on lru_gen_folio */
4568
+ gen = lru_gen_from_seq (min_seq [LRU_GEN_FILE ]);
4569
+ birth = READ_ONCE (lruvec -> lrugen .timestamps [gen ]);
4557
4570
4558
- if (need_aging )
4559
- try_to_inc_max_seq ( lruvec , max_seq , sc , swappiness , false) ;
4571
+ if (time_is_after_jiffies ( birth + min_ttl ) )
4572
+ return false;
4560
4573
4561
- return true;
4574
+ if (!lruvec_is_sizable (lruvec , sc ))
4575
+ return false;
4576
+
4577
+ mem_cgroup_calculate_protection (NULL , memcg );
4578
+
4579
+ return !mem_cgroup_below_min (NULL , memcg );
4562
4580
}
4563
4581
4564
4582
/* to protect the working set of the last N jiffies */
@@ -4567,46 +4585,32 @@ static unsigned long lru_gen_min_ttl __read_mostly;
4567
4585
static void lru_gen_age_node (struct pglist_data * pgdat , struct scan_control * sc )
4568
4586
{
4569
4587
struct mem_cgroup * memcg ;
4570
- bool success = false;
4571
4588
unsigned long min_ttl = READ_ONCE (lru_gen_min_ttl );
4572
4589
4573
4590
VM_WARN_ON_ONCE (!current_is_kswapd ());
4574
4591
4575
4592
sc -> last_reclaimed = sc -> nr_reclaimed ;
4576
4593
4577
- /*
4578
- * To reduce the chance of going into the aging path, which can be
4579
- * costly, optimistically skip it if the flag below was cleared in the
4580
- * eviction path. This improves the overall performance when multiple
4581
- * memcgs are available.
4582
- */
4583
- if (!sc -> memcgs_need_aging ) {
4584
- sc -> memcgs_need_aging = true;
4594
+ /* check the order to exclude compaction-induced reclaim */
4595
+ if (!min_ttl || sc -> order || sc -> priority == DEF_PRIORITY )
4585
4596
return ;
4586
- }
4587
-
4588
- set_mm_walk (pgdat );
4589
4597
4590
4598
memcg = mem_cgroup_iter (NULL , NULL , NULL );
4591
4599
do {
4592
4600
struct lruvec * lruvec = mem_cgroup_lruvec (memcg , pgdat );
4593
4601
4594
- if (age_lruvec (lruvec , sc , min_ttl ))
4595
- success = true;
4602
+ if (lruvec_is_reclaimable (lruvec , sc , min_ttl )) {
4603
+ mem_cgroup_iter_break (NULL , memcg );
4604
+ return ;
4605
+ }
4596
4606
4597
4607
cond_resched ();
4598
4608
} while ((memcg = mem_cgroup_iter (NULL , memcg , NULL )));
4599
4609
4600
- clear_mm_walk ();
4601
-
4602
- /* check the order to exclude compaction-induced reclaim */
4603
- if (success || !min_ttl || sc -> order )
4604
- return ;
4605
-
4606
4610
/*
4607
4611
* The main goal is to OOM kill if every generation from all memcgs is
4608
4612
* younger than min_ttl. However, another possibility is all memcgs are
4609
- * either below min or empty .
4613
+ * either too small or below min .
4610
4614
*/
4611
4615
if (mutex_trylock (& oom_lock )) {
4612
4616
struct oom_control oc = {
@@ -5114,34 +5118,28 @@ static int evict_folios(struct lruvec *lruvec, struct scan_control *sc, int swap
5114
5118
* reclaim.
5115
5119
*/
5116
5120
static unsigned long get_nr_to_scan (struct lruvec * lruvec , struct scan_control * sc ,
5117
- bool can_swap , bool * need_aging )
5121
+ bool can_swap )
5118
5122
{
5119
5123
unsigned long nr_to_scan ;
5120
5124
struct mem_cgroup * memcg = lruvec_memcg (lruvec );
5121
5125
DEFINE_MAX_SEQ (lruvec );
5122
- DEFINE_MIN_SEQ (lruvec );
5123
5126
5124
5127
if (mem_cgroup_below_min (sc -> target_mem_cgroup , memcg ) ||
5125
5128
(mem_cgroup_below_low (sc -> target_mem_cgroup , memcg ) &&
5126
5129
!sc -> memcg_low_reclaim ))
5127
5130
return 0 ;
5128
5131
5129
- * need_aging = should_run_aging (lruvec , max_seq , min_seq , sc , can_swap , & nr_to_scan );
5130
- if (!* need_aging )
5132
+ if (!should_run_aging (lruvec , max_seq , sc , can_swap , & nr_to_scan ))
5131
5133
return nr_to_scan ;
5132
5134
5133
5135
/* skip the aging path at the default priority */
5134
5136
if (sc -> priority == DEF_PRIORITY )
5135
- goto done ;
5137
+ return nr_to_scan ;
5136
5138
5137
- /* leave the work to lru_gen_age_node() */
5138
- if (current_is_kswapd ())
5139
- return 0 ;
5139
+ try_to_inc_max_seq (lruvec , max_seq , sc , can_swap , false);
5140
5140
5141
- if (try_to_inc_max_seq (lruvec , max_seq , sc , can_swap , false))
5142
- return nr_to_scan ;
5143
- done :
5144
- return min_seq [!can_swap ] + MIN_NR_GENS <= max_seq ? nr_to_scan : 0 ;
5141
+ /* skip this lruvec as it's low on cold folios */
5142
+ return 0 ;
5145
5143
}
5146
5144
5147
5145
static unsigned long get_nr_to_reclaim (struct scan_control * sc )
@@ -5160,9 +5158,7 @@ static unsigned long get_nr_to_reclaim(struct scan_control *sc)
5160
5158
static void lru_gen_shrink_lruvec (struct lruvec * lruvec , struct scan_control * sc )
5161
5159
{
5162
5160
struct blk_plug plug ;
5163
- bool need_aging = false;
5164
5161
unsigned long scanned = 0 ;
5165
- unsigned long reclaimed = sc -> nr_reclaimed ;
5166
5162
unsigned long nr_to_reclaim = get_nr_to_reclaim (sc );
5167
5163
5168
5164
lru_add_drain ();
@@ -5183,13 +5179,13 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
5183
5179
else
5184
5180
swappiness = 0 ;
5185
5181
5186
- nr_to_scan = get_nr_to_scan (lruvec , sc , swappiness , & need_aging );
5182
+ nr_to_scan = get_nr_to_scan (lruvec , sc , swappiness );
5187
5183
if (!nr_to_scan )
5188
- goto done ;
5184
+ break ;
5189
5185
5190
5186
delta = evict_folios (lruvec , sc , swappiness );
5191
5187
if (!delta )
5192
- goto done ;
5188
+ break ;
5193
5189
5194
5190
scanned += delta ;
5195
5191
if (scanned >= nr_to_scan )
@@ -5201,10 +5197,6 @@ static void lru_gen_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc
5201
5197
cond_resched ();
5202
5198
}
5203
5199
5204
- /* see the comment in lru_gen_age_node() */
5205
- if (sc -> nr_reclaimed - reclaimed >= MIN_LRU_BATCH && !need_aging )
5206
- sc -> memcgs_need_aging = false;
5207
- done :
5208
5200
clear_mm_walk ();
5209
5201
5210
5202
blk_finish_plug (& plug );
0 commit comments