From: Ridong Chen <redacted>
The number of pages of a given type in a generation is computed by
summing lrugen->nr_pages[gen][type][] over all zones and clamping each
per-zone counter to >= 0, since the counters are updated locklessly and
can transiently go negative. This loop is open-coded in
lruvec_evictable_size() and in the debugfs lru_gen output.
Add lruvec_gen_size() to compute it from a seq, and convert both users.
Put it in mm/vmscan.h so that the vmscan tracepoints, which include that
header, can use it as well.
An upcoming tracepoint and the MGLRU swappiness rework will also use it.
No functional change.
Suggested-by: Barry Song <baohua@kernel.org>
Signed-off-by: Ridong Chen <redacted>
---
mm/vmscan.c | 18 ++++++------------
mm/vmscan.h | 16 ++++++++++++++++
2 files changed, 22 insertions(+), 12 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 3054175717ab..1581b73aec56 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4207,18 +4207,15 @@ static void set_initial_priority(struct pglist_data *pgdat, struct scan_control
static unsigned long lruvec_evictable_size(struct lruvec *lruvec, int swappiness)
{
- int gen, type, zone;
+ int type;
unsigned long seq, total = 0;
struct lru_gen_folio *lrugen = &lruvec->lrugen;
DEFINE_MAX_SEQ(lruvec);
DEFINE_MIN_SEQ(lruvec);
for_each_evictable_type(type, swappiness) {
- for (seq = min_seq[type]; seq <= max_seq; seq++) {
- gen = lru_gen_from_seq(seq);
- for (zone = 0; zone < MAX_NR_ZONES; zone++)
- total += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L);
- }
+ for (seq = min_seq[type]; seq <= max_seq; seq++)
+ total += lruvec_gen_size(lrugen, type, seq);
}
return total;@@ -5723,20 +5720,17 @@ static int lru_gen_seq_show(struct seq_file *m, void *v)
seq = 0;
for (; seq <= max_seq; seq++) {
- int type, zone;
+ int type;
int gen = lru_gen_from_seq(seq);
unsigned long birth = READ_ONCE(lruvec->lrugen.timestamps[gen]);
seq_printf(m, " %10lu %10u", seq, jiffies_to_msecs(jiffies - birth));
for (type = 0; type < ANON_AND_FILE; type++) {
- unsigned long size = 0;
char mark = full && seq < min_seq[type] ? 'x' : ' ';
- for (zone = 0; zone < MAX_NR_ZONES; zone++)
- size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L);
-
- seq_printf(m, " %10lu%c", size, mark);
+ seq_printf(m, " %10lu%c",
+ lruvec_gen_size(lrugen, type, seq), mark);
}
seq_putc(m, '\n');diff --git a/mm/vmscan.h b/mm/vmscan.h
index adb22e80d760..c6b583fc7493 100644
--- a/mm/vmscan.h
+++ b/mm/vmscan.h
@@ -3,6 +3,7 @@
#define _MM_VMSCAN_H
#include <linux/gfp_types.h>
+#include <linux/mm_inline.h>
#include <linux/nodemask.h>
#include <linux/swap.h>
#include <linux/types.h>
@@ -115,4 +116,19 @@ struct scan_control {
struct reclaim_state reclaim_state;
};
+#ifdef CONFIG_LRU_GEN
+/* The number of pages of @type in the generation @seq, summed over all zones */
+static inline unsigned long lruvec_gen_size(struct lru_gen_folio *lrugen,
+ int type, unsigned long seq)
+{
+ int gen = lru_gen_from_seq(seq);
+ unsigned long size = 0;
+
+ for (int zone = 0; zone < MAX_NR_ZONES; zone++)
+ size += max(READ_ONCE(lrugen->nr_pages[gen][type][zone]), 0L);
+
+ return size;
+}
+#endif /* CONFIG_LRU_GEN */
+
#endif /* _MM_VMSCAN_H */--
2.34.1