summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mm/damon/stat.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/mm/damon/stat.c b/mm/damon/stat.c
index dd00f2384b95..3be86ca57c8b 100644
--- a/mm/damon/stat.c
+++ b/mm/damon/stat.c
@@ -29,8 +29,42 @@ static bool enabled __read_mostly = IS_ENABLED(
module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
MODULE_PARM_DESC(enabled, "Enable of disable DAMON_STAT");
+static unsigned long estimated_memory_bandwidth __read_mostly;
+module_param(estimated_memory_bandwidth, ulong, 0400);
+MODULE_PARM_DESC(estimated_memory_bandwidth,
+ "Estimated memory bandwidth usage in bytes per second");
+
static struct damon_ctx *damon_stat_context;
+static void damon_stat_set_estimated_memory_bandwidth(struct damon_ctx *c)
+{
+ struct damon_target *t;
+ struct damon_region *r;
+ unsigned long access_bytes = 0;
+
+ damon_for_each_target(t, c) {
+ damon_for_each_region(r, t)
+ access_bytes += (r->ar.end - r->ar.start) *
+ r->nr_accesses;
+ }
+ estimated_memory_bandwidth = access_bytes * USEC_PER_MSEC *
+ MSEC_PER_SEC / c->attrs.aggr_interval;
+}
+
+static int damon_stat_after_aggregation(struct damon_ctx *c)
+{
+ static unsigned long last_refresh_jiffies;
+
+ /* avoid unnecessarily frequent stat update */
+ if (time_before_eq(jiffies, last_refresh_jiffies +
+ msecs_to_jiffies(5 * MSEC_PER_SEC)))
+ return 0;
+ last_refresh_jiffies = jiffies;
+
+ damon_stat_set_estimated_memory_bandwidth(c);
+ return 0;
+}
+
static struct damon_ctx *damon_stat_build_ctx(void)
{
struct damon_ctx *ctx;
@@ -76,6 +110,7 @@ static struct damon_ctx *damon_stat_build_ctx(void)
damon_add_target(ctx, target);
if (damon_set_region_biggest_system_ram_default(target, &start, &end))
goto free_out;
+ ctx->callback.after_aggregation = damon_stat_after_aggregation;
return ctx;
free_out:
damon_destroy_ctx(ctx);