Skip to content

Commit 310d6c1

Browse files
sjp38akpm00
authored andcommitted
mm/damon/core: merge regions aggressively when max_nr_regions is unmet
DAMON keeps the number of regions under max_nr_regions by skipping regions split operations when doing so can make the number higher than the limit. It works well for preventing violation of the limit. But, if somehow the violation happens, it cannot recovery well depending on the situation. In detail, if the real number of regions having different access pattern is higher than the limit, the mechanism cannot reduce the number below the limit. In such a case, the system could suffer from high monitoring overhead of DAMON. The violation can actually happen. For an example, the user could reduce max_nr_regions while DAMON is running, to be lower than the current number of regions. Fix the problem by repeating the merge operations with increasing aggressiveness in kdamond_merge_regions() for the case, until the limit is met. [[email protected]: increase regions merge aggressiveness while respecting min_nr_regions] Link: https://lkml.kernel.org/r/[email protected] [[email protected]: ensure max threshold attempt for max_nr_regions violation] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Fixes: b9a6ac4 ("mm/damon: adaptively adjust regions") Signed-off-by: SeongJae Park <[email protected]> Cc: <[email protected]> [5.15+] Signed-off-by: Andrew Morton <[email protected]>
1 parent 1723f04 commit 310d6c1

File tree

1 file changed

+20
-3
lines changed

1 file changed

+20
-3
lines changed

mm/damon/core.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,14 +1358,31 @@ static void damon_merge_regions_of(struct damon_target *t, unsigned int thres,
13581358
* access frequencies are similar. This is for minimizing the monitoring
13591359
* overhead under the dynamically changeable access pattern. If a merge was
13601360
* unnecessarily made, later 'kdamond_split_regions()' will revert it.
1361+
*
1362+
* The total number of regions could be higher than the user-defined limit,
1363+
* max_nr_regions for some cases. For example, the user can update
1364+
* max_nr_regions to a number that lower than the current number of regions
1365+
* while DAMON is running. For such a case, repeat merging until the limit is
1366+
* met while increasing @threshold up to possible maximum level.
13611367
*/
13621368
static void kdamond_merge_regions(struct damon_ctx *c, unsigned int threshold,
13631369
unsigned long sz_limit)
13641370
{
13651371
struct damon_target *t;
1366-
1367-
damon_for_each_target(t, c)
1368-
damon_merge_regions_of(t, threshold, sz_limit);
1372+
unsigned int nr_regions;
1373+
unsigned int max_thres;
1374+
1375+
max_thres = c->attrs.aggr_interval /
1376+
(c->attrs.sample_interval ? c->attrs.sample_interval : 1);
1377+
do {
1378+
nr_regions = 0;
1379+
damon_for_each_target(t, c) {
1380+
damon_merge_regions_of(t, threshold, sz_limit);
1381+
nr_regions += damon_nr_regions(t);
1382+
}
1383+
threshold = max(1, threshold * 2);
1384+
} while (nr_regions > c->attrs.max_nr_regions &&
1385+
threshold / 2 < max_thres);
13691386
}
13701387

13711388
/*

0 commit comments

Comments
 (0)