1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
From 6f1b436575b5fb78c9eb72f9ae3707dea3407b9b Mon Sep 17 00:00:00 2001
From: SeongJae Park <sj@kernel.org>
Date: Sun, 14 Aug 2022 16:08:10 +0000
Subject: [PATCH] mm/damon: Add debug code
This commit adds verification check code. Those should not be merged in
the final code. Those are not expected to incur high overhead, though.
Signed-off-by: SeongJae Park <sj@kernel.org>
---
mm/damon/core.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 939ecfcd4641..31ac8e4b1189 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -126,6 +126,12 @@ struct damon_region *damon_new_region(unsigned long start, unsigned long end)
if (!region)
return NULL;
+ if (start >= end) {
+ pr_err("%s called with start %lu and end %lu!\n", __func__,
+ start, end);
+ BUG();
+ }
+
region->ar.start = start;
region->ar.end = end;
region->nr_accesses = 0;
@@ -146,6 +152,10 @@ void damon_add_region(struct damon_region *r, struct damon_target *t)
static void damon_del_region(struct damon_region *r, struct damon_target *t)
{
+ if (t->nr_regions == 0) {
+ pr_err("nr_regions 0 but damon_del_region called\n");
+ BUG();
+ }
list_del(&r->list);
t->nr_regions--;
}
@@ -476,8 +486,27 @@ void damon_destroy_target(struct damon_target *t)
damon_free_target(t);
}
+static void damon_nr_regions_verify(struct damon_target *t)
+{
+ struct damon_region *r;
+ unsigned int count = 0;
+ static unsigned called;
+
+ if (called++ % 100)
+ return;
+
+ damon_for_each_region(r, t)
+ count++;
+
+ if (count != t->nr_regions)
+ pr_err("%s expected %u but %u\n", __func__, count, t->nr_regions);
+ BUG_ON(count != t->nr_regions);
+}
+
unsigned int damon_nr_regions(struct damon_target *t)
{
+ damon_nr_regions_verify(t);
+
return t->nr_regions;
}
@@ -1033,6 +1062,15 @@ static void damos_apply_scheme(struct damon_ctx *c, struct damon_target *t,
DAMON_MIN_REGION);
if (!sz)
goto update_stat;
+ if (sz >= damon_sz_region(r)) {
+ pr_err("sz: %lu, region: %lu-%lu (%lu), quota: %lu, charged: %lu\n",
+ sz, r->ar.start,
+ r->ar.end, r->ar.end -
+ r->ar.start,
+ quota->esz,
+ quota->charged_sz);
+ BUG();
+ }
damon_split_region_at(t, r, sz);
}
if (damos_filter_out(c, t, r, s))
@@ -1318,6 +1356,14 @@ static void damon_merge_two_regions(struct damon_target *t,
l->nr_accesses_bp = l->nr_accesses * 10000;
l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r);
l->ar.end = r->ar.end;
+
+ if (l->ar.start >= l->ar.end) {
+ pr_err("%s made %lu-%lu region\n", __func__, l->ar.start,
+ r->ar.end);
+ pr_err("r: %lu-%lu\n", r->ar.start, r->ar.end);
+ BUG();
+ }
+
damon_destroy_region(r, t);
}
@@ -1339,6 +1385,12 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
else
r->age++;
+ if (r->nr_accesses != r->nr_accesses_bp / 10000) {
+ pr_err("nr_accesses (%u) != nr_accesses_bp (%u)\n",
+ r->nr_accesses, r->nr_accesses_bp);
+ BUG();
+ }
+
if (prev && prev->ar.end == r->ar.start &&
abs(prev->nr_accesses - r->nr_accesses) <= thres &&
damon_sz_region(prev) + damon_sz_region(r) <= sz_limit)
@@ -1379,6 +1431,12 @@ static void damon_split_region_at(struct damon_target *t,
{
struct damon_region *new;
+ if (sz_r == 0 || sz_r >= r->ar.end - r->ar.start) {
+ pr_err("%s called with region of %lu-%lu and sz_r %lu!\n",
+ __func__, r->ar.start, r->ar.end, sz_r);
+ BUG();
+ }
+
new = damon_new_region(r->ar.start + sz_r, r->ar.end);
if (!new)
return;
--
2.39.2
|