Commit cbeaa77b authored by SeongJae Park's avatar SeongJae Park Committed by Andrew Morton
Browse files

mm/damon/core: use a dedicated struct for monitoring attributes

DAMON monitoring attributes are directly defined as fields of 'struct
damon_ctx'.  This makes 'struct damon_ctx' a little long and complicated. 
This commit defines and uses a struct, 'struct damon_attrs', which is
dedicated for only the monitoring attributes to make the purpose of the
five values clearer and simplify 'struct damon_ctx'.

Link: https://lkml.kernel.org/r/20220913174449.50645-6-sj@kernel.org


Signed-off-by: default avatarSeongJae Park <sj@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 70e0c1d1
Loading
Loading
Loading
Loading
+20 −10
Original line number Diff line number Diff line
@@ -389,13 +389,15 @@ struct damon_callback {
};

/**
 * struct damon_ctx - Represents a context for each monitoring.  This is the
 * main interface that allows users to set the attributes and get the results
 * of the monitoring.
 * struct damon_attrs - Monitoring attributes for accuracy/overhead control.
 *
 * @sample_interval:		The time between access samplings.
 * @aggr_interval:		The time between monitor results aggregations.
 * @ops_update_interval:	The time between monitoring operations updates.
 * @min_nr_regions:		The minimum number of adaptive monitoring
 *				regions.
 * @max_nr_regions:		The maximum number of adaptive monitoring
 *				regions.
 *
 * For each @sample_interval, DAMON checks whether each region is accessed or
 * not.  It aggregates and keeps the access information (number of accesses to
@@ -405,7 +407,21 @@ struct damon_callback {
 * @ops_update_interval.  All time intervals are in micro-seconds.
 * Please refer to &struct damon_operations and &struct damon_callback for more
 * detail.
 */
struct damon_attrs {
	unsigned long sample_interval;
	unsigned long aggr_interval;
	unsigned long ops_update_interval;
	unsigned long min_nr_regions;
	unsigned long max_nr_regions;
};

/**
 * struct damon_ctx - Represents a context for each monitoring.  This is the
 * main interface that allows users to set the attributes and get the results
 * of the monitoring.
 *
 * @attrs:		Monitoring attributes for accuracy/overhead control.
 * @kdamond:		Kernel thread who does the monitoring.
 * @kdamond_lock:	Mutex for the synchronizations with @kdamond.
 *
@@ -427,15 +443,11 @@ struct damon_callback {
 * @ops:	Set of monitoring operations for given use cases.
 * @callback:	Set of callbacks for monitoring events notifications.
 *
 * @min_nr_regions:	The minimum number of adaptive monitoring regions.
 * @max_nr_regions:	The maximum number of adaptive monitoring regions.
 * @adaptive_targets:	Head of monitoring targets (&damon_target) list.
 * @schemes:		Head of schemes (&damos) list.
 */
struct damon_ctx {
	unsigned long sample_interval;
	unsigned long aggr_interval;
	unsigned long ops_update_interval;
	struct damon_attrs attrs;

/* private: internal use only */
	struct timespec64 last_aggregation;
@@ -448,8 +460,6 @@ struct damon_ctx {
	struct damon_operations ops;
	struct damon_callback callback;

	unsigned long min_nr_regions;
	unsigned long max_nr_regions;
	struct list_head adaptive_targets;
	struct list_head schemes;
};
+17 −17
Original line number Diff line number Diff line
@@ -382,17 +382,17 @@ struct damon_ctx *damon_new_ctx(void)
	if (!ctx)
		return NULL;

	ctx->sample_interval = 5 * 1000;
	ctx->aggr_interval = 100 * 1000;
	ctx->ops_update_interval = 60 * 1000 * 1000;
	ctx->attrs.sample_interval = 5 * 1000;
	ctx->attrs.aggr_interval = 100 * 1000;
	ctx->attrs.ops_update_interval = 60 * 1000 * 1000;

	ktime_get_coarse_ts64(&ctx->last_aggregation);
	ctx->last_ops_update = ctx->last_aggregation;

	mutex_init(&ctx->kdamond_lock);

	ctx->min_nr_regions = 10;
	ctx->max_nr_regions = 1000;
	ctx->attrs.min_nr_regions = 10;
	ctx->attrs.max_nr_regions = 1000;

	INIT_LIST_HEAD(&ctx->adaptive_targets);
	INIT_LIST_HEAD(&ctx->schemes);
@@ -448,11 +448,11 @@ int damon_set_attrs(struct damon_ctx *ctx, unsigned long sample_int,
	if (min_nr_reg > max_nr_reg)
		return -EINVAL;

	ctx->sample_interval = sample_int;
	ctx->aggr_interval = aggr_int;
	ctx->ops_update_interval = ops_upd_int;
	ctx->min_nr_regions = min_nr_reg;
	ctx->max_nr_regions = max_nr_reg;
	ctx->attrs.sample_interval = sample_int;
	ctx->attrs.aggr_interval = aggr_int;
	ctx->attrs.ops_update_interval = ops_upd_int;
	ctx->attrs.min_nr_regions = min_nr_reg;
	ctx->attrs.max_nr_regions = max_nr_reg;

	return 0;
}
@@ -507,8 +507,8 @@ static unsigned long damon_region_sz_limit(struct damon_ctx *ctx)
			sz += r->ar.end - r->ar.start;
	}

	if (ctx->min_nr_regions)
		sz /= ctx->min_nr_regions;
	if (ctx->attrs.min_nr_regions)
		sz /= ctx->attrs.min_nr_regions;
	if (sz < DAMON_MIN_REGION)
		sz = DAMON_MIN_REGION;

@@ -657,7 +657,7 @@ static bool damon_check_reset_time_interval(struct timespec64 *baseline,
static bool kdamond_aggregate_interval_passed(struct damon_ctx *ctx)
{
	return damon_check_reset_time_interval(&ctx->last_aggregation,
			ctx->aggr_interval);
			ctx->attrs.aggr_interval);
}

/*
@@ -1016,12 +1016,12 @@ static void kdamond_split_regions(struct damon_ctx *ctx)
	damon_for_each_target(t, ctx)
		nr_regions += damon_nr_regions(t);

	if (nr_regions > ctx->max_nr_regions / 2)
	if (nr_regions > ctx->attrs.max_nr_regions / 2)
		return;

	/* Maybe the middle of the region has different access frequency */
	if (last_nr_regions == nr_regions &&
			nr_regions < ctx->max_nr_regions / 3)
			nr_regions < ctx->attrs.max_nr_regions / 3)
		nr_subregions = 3;

	damon_for_each_target(t, ctx)
@@ -1039,7 +1039,7 @@ static void kdamond_split_regions(struct damon_ctx *ctx)
static bool kdamond_need_update_operations(struct damon_ctx *ctx)
{
	return damon_check_reset_time_interval(&ctx->last_ops_update,
			ctx->ops_update_interval);
			ctx->attrs.ops_update_interval);
}

/*
@@ -1188,7 +1188,7 @@ static int kdamond_fn(void *data)
			continue;
		}

		kdamond_usleep(ctx->sample_interval);
		kdamond_usleep(ctx->attrs.sample_interval);

		if (ctx->ops.check_accesses)
			max_nr_accesses = ctx->ops.check_accesses(ctx);
+3 −3
Original line number Diff line number Diff line
@@ -55,9 +55,9 @@ static ssize_t dbgfs_attrs_read(struct file *file,

	mutex_lock(&ctx->kdamond_lock);
	ret = scnprintf(kbuf, ARRAY_SIZE(kbuf), "%lu %lu %lu %lu %lu\n",
			ctx->sample_interval, ctx->aggr_interval,
			ctx->ops_update_interval, ctx->min_nr_regions,
			ctx->max_nr_regions);
			ctx->attrs.sample_interval, ctx->attrs.aggr_interval,
			ctx->attrs.ops_update_interval,
			ctx->attrs.min_nr_regions, ctx->attrs.max_nr_regions);
	mutex_unlock(&ctx->kdamond_lock);

	return simple_read_from_buffer(buf, count, ppos, kbuf, ret);
+2 −2
Original line number Diff line number Diff line
@@ -99,10 +99,10 @@ int damon_hot_score(struct damon_ctx *c, struct damon_region *r,
	unsigned int age_weight = s->quota.weight_age;
	int hotness;

	max_nr_accesses = c->aggr_interval / c->sample_interval;
	max_nr_accesses = c->attrs.aggr_interval / c->attrs.sample_interval;
	freq_subscore = r->nr_accesses * DAMON_MAX_SUBSCORE / max_nr_accesses;

	age_in_sec = (unsigned long)r->age * c->aggr_interval / 1000000;
	age_in_sec = (unsigned long)r->age * c->attrs.aggr_interval / 1000000;
	for (age_in_log = 0; age_in_log < DAMON_MAX_AGE_IN_LOG && age_in_sec;
			age_in_log++, age_in_sec >>= 1)
		;
+2 −2
Original line number Diff line number Diff line
@@ -251,8 +251,8 @@ static void __damon_va_init_regions(struct damon_ctx *ctx,

	for (i = 0; i < 3; i++)
		sz += regions[i].end - regions[i].start;
	if (ctx->min_nr_regions)
		sz /= ctx->min_nr_regions;
	if (ctx->attrs.min_nr_regions)
		sz /= ctx->attrs.min_nr_regions;
	if (sz < DAMON_MIN_REGION)
		sz = DAMON_MIN_REGION;