xref: /linux/samples/damon/prcl.c (revision 00c010e130e58301db2ea0cec1eadc931e1cb8cf)
12aca2546SSeongJae Park // SPDX-License-Identifier: GPL-2.0
22aca2546SSeongJae Park /*
32aca2546SSeongJae Park  * proactive reclamation: monitor access pattern of a given process, find
4*1477b8cdSEnze Li  * regions that seems not accessed, and proactively page out the regions.
52aca2546SSeongJae Park  */
62aca2546SSeongJae Park 
72aca2546SSeongJae Park #define pr_fmt(fmt) "damon_sample_prcl: " fmt
82aca2546SSeongJae Park 
92aca2546SSeongJae Park #include <linux/damon.h>
102aca2546SSeongJae Park #include <linux/init.h>
112aca2546SSeongJae Park #include <linux/kernel.h>
122aca2546SSeongJae Park #include <linux/module.h>
132aca2546SSeongJae Park 
142aca2546SSeongJae Park static int target_pid __read_mostly;
152aca2546SSeongJae Park module_param(target_pid, int, 0600);
162aca2546SSeongJae Park 
172aca2546SSeongJae Park static int damon_sample_prcl_enable_store(
182aca2546SSeongJae Park 		const char *val, const struct kernel_param *kp);
192aca2546SSeongJae Park 
202aca2546SSeongJae Park static const struct kernel_param_ops enable_param_ops = {
212aca2546SSeongJae Park 	.set = damon_sample_prcl_enable_store,
222aca2546SSeongJae Park 	.get = param_get_bool,
232aca2546SSeongJae Park };
242aca2546SSeongJae Park 
252aca2546SSeongJae Park static bool enable __read_mostly;
262aca2546SSeongJae Park module_param_cb(enable, &enable_param_ops, &enable, 0600);
272aca2546SSeongJae Park MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_WSSE");
282aca2546SSeongJae Park 
292aca2546SSeongJae Park static struct damon_ctx *ctx;
302aca2546SSeongJae Park static struct pid *target_pidp;
312aca2546SSeongJae Park 
damon_sample_prcl_after_aggregate(struct damon_ctx * c)322aca2546SSeongJae Park static int damon_sample_prcl_after_aggregate(struct damon_ctx *c)
332aca2546SSeongJae Park {
342aca2546SSeongJae Park 	struct damon_target *t;
352aca2546SSeongJae Park 
362aca2546SSeongJae Park 	damon_for_each_target(t, c) {
372aca2546SSeongJae Park 		struct damon_region *r;
382aca2546SSeongJae Park 		unsigned long wss = 0;
392aca2546SSeongJae Park 
402aca2546SSeongJae Park 		damon_for_each_region(r, t) {
412aca2546SSeongJae Park 			if (r->nr_accesses > 0)
422aca2546SSeongJae Park 				wss += r->ar.end - r->ar.start;
432aca2546SSeongJae Park 		}
442aca2546SSeongJae Park 		pr_info("wss: %lu\n", wss);
452aca2546SSeongJae Park 	}
462aca2546SSeongJae Park 	return 0;
472aca2546SSeongJae Park }
482aca2546SSeongJae Park 
damon_sample_prcl_start(void)492aca2546SSeongJae Park static int damon_sample_prcl_start(void)
502aca2546SSeongJae Park {
512aca2546SSeongJae Park 	struct damon_target *target;
5215e01f39SSeongJae Park 	struct damos *scheme;
532aca2546SSeongJae Park 
542aca2546SSeongJae Park 	pr_info("start\n");
552aca2546SSeongJae Park 
562aca2546SSeongJae Park 	ctx = damon_new_ctx();
572aca2546SSeongJae Park 	if (!ctx)
582aca2546SSeongJae Park 		return -ENOMEM;
592aca2546SSeongJae Park 	if (damon_select_ops(ctx, DAMON_OPS_VADDR)) {
602aca2546SSeongJae Park 		damon_destroy_ctx(ctx);
612aca2546SSeongJae Park 		return -EINVAL;
622aca2546SSeongJae Park 	}
632aca2546SSeongJae Park 
642aca2546SSeongJae Park 	target = damon_new_target();
652aca2546SSeongJae Park 	if (!target) {
662aca2546SSeongJae Park 		damon_destroy_ctx(ctx);
672aca2546SSeongJae Park 		return -ENOMEM;
682aca2546SSeongJae Park 	}
692aca2546SSeongJae Park 	damon_add_target(ctx, target);
702aca2546SSeongJae Park 	target_pidp = find_get_pid(target_pid);
712aca2546SSeongJae Park 	if (!target_pidp) {
722aca2546SSeongJae Park 		damon_destroy_ctx(ctx);
732aca2546SSeongJae Park 		return -EINVAL;
742aca2546SSeongJae Park 	}
752aca2546SSeongJae Park 	target->pid = target_pidp;
762aca2546SSeongJae Park 
772aca2546SSeongJae Park 	ctx->callback.after_aggregation = damon_sample_prcl_after_aggregate;
782aca2546SSeongJae Park 
7915e01f39SSeongJae Park 	scheme = damon_new_scheme(
8015e01f39SSeongJae Park 			&(struct damos_access_pattern) {
8115e01f39SSeongJae Park 			.min_sz_region = PAGE_SIZE,
8215e01f39SSeongJae Park 			.max_sz_region = ULONG_MAX,
8315e01f39SSeongJae Park 			.min_nr_accesses = 0,
8415e01f39SSeongJae Park 			.max_nr_accesses = 0,
8515e01f39SSeongJae Park 			.min_age_region = 50,
8615e01f39SSeongJae Park 			.max_age_region = UINT_MAX},
8715e01f39SSeongJae Park 			DAMOS_PAGEOUT,
8815e01f39SSeongJae Park 			0,
8915e01f39SSeongJae Park 			&(struct damos_quota){},
9015e01f39SSeongJae Park 			&(struct damos_watermarks){},
9115e01f39SSeongJae Park 			NUMA_NO_NODE);
9215e01f39SSeongJae Park 	if (!scheme) {
9315e01f39SSeongJae Park 		damon_destroy_ctx(ctx);
9415e01f39SSeongJae Park 		return -ENOMEM;
9515e01f39SSeongJae Park 	}
9615e01f39SSeongJae Park 	damon_set_schemes(ctx, &scheme, 1);
9715e01f39SSeongJae Park 
982aca2546SSeongJae Park 	return damon_start(&ctx, 1, true);
992aca2546SSeongJae Park }
1002aca2546SSeongJae Park 
damon_sample_prcl_stop(void)1012aca2546SSeongJae Park static void damon_sample_prcl_stop(void)
1022aca2546SSeongJae Park {
1032aca2546SSeongJae Park 	pr_info("stop\n");
1042aca2546SSeongJae Park 	if (ctx) {
1052aca2546SSeongJae Park 		damon_stop(&ctx, 1);
1062aca2546SSeongJae Park 		damon_destroy_ctx(ctx);
1072aca2546SSeongJae Park 	}
1082aca2546SSeongJae Park 	if (target_pidp)
1092aca2546SSeongJae Park 		put_pid(target_pidp);
1102aca2546SSeongJae Park }
1112aca2546SSeongJae Park 
damon_sample_prcl_enable_store(const char * val,const struct kernel_param * kp)1122aca2546SSeongJae Park static int damon_sample_prcl_enable_store(
1132aca2546SSeongJae Park 		const char *val, const struct kernel_param *kp)
1142aca2546SSeongJae Park {
1152aca2546SSeongJae Park 	bool enabled = enable;
1162aca2546SSeongJae Park 	int err;
1172aca2546SSeongJae Park 
1182aca2546SSeongJae Park 	err = kstrtobool(val, &enable);
1192aca2546SSeongJae Park 	if (err)
1202aca2546SSeongJae Park 		return err;
1212aca2546SSeongJae Park 
1222aca2546SSeongJae Park 	if (enable == enabled)
1232aca2546SSeongJae Park 		return 0;
1242aca2546SSeongJae Park 
1252aca2546SSeongJae Park 	if (enable)
1262aca2546SSeongJae Park 		return damon_sample_prcl_start();
1272aca2546SSeongJae Park 	damon_sample_prcl_stop();
1282aca2546SSeongJae Park 	return 0;
1292aca2546SSeongJae Park }
1302aca2546SSeongJae Park 
damon_sample_prcl_init(void)1312aca2546SSeongJae Park static int __init damon_sample_prcl_init(void)
1322aca2546SSeongJae Park {
1332aca2546SSeongJae Park 	return 0;
1342aca2546SSeongJae Park }
1352aca2546SSeongJae Park 
1362aca2546SSeongJae Park module_init(damon_sample_prcl_init);
137