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 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
// SPDX-License-Identifier: GPL-2.0
/*
* proactive reclamation: monitor access pattern of a given process, find
* regions that seems not accessed, and proactively page out the regions.
*/
#define pr_fmt(fmt) "damon_sample_prcl: " fmt
#include <linux/damon.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#ifdef MODULE_PARAM_PREFIX
#undef MODULE_PARAM_PREFIX
#endif
#define MODULE_PARAM_PREFIX "damon_sample_prcl."
static int target_pid __read_mostly;
module_param(target_pid, int, 0600);
static int damon_sample_prcl_enable_store(
const char *val, const struct kernel_param *kp);
static const struct kernel_param_ops enabled_param_ops = {
.set = damon_sample_prcl_enable_store,
.get = param_get_bool,
};
static bool enabled __read_mostly;
module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_PRCL");
static struct damon_ctx *ctx;
static struct pid *target_pidp;
static int damon_sample_prcl_repeat_call_fn(void *data)
{
struct damon_ctx *c = data;
struct damon_target *t;
damon_for_each_target(t, c) {
struct damon_region *r;
unsigned long wss = 0;
damon_for_each_region(r, t) {
if (r->nr_accesses > 0)
wss += r->ar.end - r->ar.start;
}
pr_info("wss: %lu\n", wss);
}
return 0;
}
static struct damon_call_control repeat_call_control = {
.fn = damon_sample_prcl_repeat_call_fn,
.repeat = true,
};
static int damon_sample_prcl_start(void)
{
struct damon_target *target;
struct damos *scheme;
int err;
pr_info("start\n");
ctx = damon_new_ctx();
if (!ctx)
return -ENOMEM;
if (damon_select_ops(ctx, DAMON_OPS_VADDR)) {
damon_destroy_ctx(ctx);
return -EINVAL;
}
target = damon_new_target();
if (!target) {
damon_destroy_ctx(ctx);
return -ENOMEM;
}
damon_add_target(ctx, target);
target_pidp = find_get_pid(target_pid);
if (!target_pidp) {
damon_destroy_ctx(ctx);
return -EINVAL;
}
target->pid = target_pidp;
scheme = damon_new_scheme(
&(struct damos_access_pattern) {
.min_sz_region = PAGE_SIZE,
.max_sz_region = ULONG_MAX,
.min_nr_accesses = 0,
.max_nr_accesses = 0,
.min_age_region = 50,
.max_age_region = UINT_MAX},
DAMOS_PAGEOUT,
0,
&(struct damos_quota){},
&(struct damos_watermarks){},
NUMA_NO_NODE);
if (!scheme) {
damon_destroy_ctx(ctx);
return -ENOMEM;
}
damon_set_schemes(ctx, &scheme, 1);
err = damon_start(&ctx, 1, true);
if (err)
return err;
repeat_call_control.data = ctx;
return damon_call(ctx, &repeat_call_control);
}
static void damon_sample_prcl_stop(void)
{
pr_info("stop\n");
if (ctx) {
damon_stop(&ctx, 1);
damon_destroy_ctx(ctx);
}
}
static bool init_called;
static int damon_sample_prcl_enable_store(
const char *val, const struct kernel_param *kp)
{
bool is_enabled = enabled;
int err;
err = kstrtobool(val, &enabled);
if (err)
return err;
if (enabled == is_enabled)
return 0;
if (!init_called)
return 0;
if (enabled) {
err = damon_sample_prcl_start();
if (err)
enabled = false;
return err;
}
damon_sample_prcl_stop();
return 0;
}
static int __init damon_sample_prcl_init(void)
{
int err = 0;
init_called = true;
if (enabled) {
err = damon_sample_prcl_start();
if (err)
enabled = false;
}
return 0;
}
module_init(damon_sample_prcl_init);
|