1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * proactive reclamation: monitor access pattern of a given process, find 4 * regions that seems not accessed, and proactively page out the regions. 5 */ 6 7 #define pr_fmt(fmt) "damon_sample_prcl: " fmt 8 9 #include <linux/damon.h> 10 #include <linux/init.h> 11 #include <linux/kernel.h> 12 #include <linux/module.h> 13 14 #ifdef MODULE_PARAM_PREFIX 15 #undef MODULE_PARAM_PREFIX 16 #endif 17 #define MODULE_PARAM_PREFIX "damon_sample_prcl." 18 19 static int target_pid __read_mostly; 20 module_param(target_pid, int, 0600); 21 22 static int damon_sample_prcl_enable_store( 23 const char *val, const struct kernel_param *kp); 24 25 static const struct kernel_param_ops enabled_param_ops = { 26 .set = damon_sample_prcl_enable_store, 27 .get = param_get_bool, 28 }; 29 30 static bool enabled __read_mostly; 31 module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); 32 MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_PRCL"); 33 34 static struct damon_ctx *ctx; 35 static struct pid *target_pidp; 36 37 static int damon_sample_prcl_repeat_call_fn(void *data) 38 { 39 struct damon_ctx *c = data; 40 struct damon_target *t; 41 42 damon_for_each_target(t, c) { 43 struct damon_region *r; 44 unsigned long wss = 0; 45 46 damon_for_each_region(r, t) { 47 if (r->nr_accesses > 0) 48 wss += r->ar.end - r->ar.start; 49 } 50 pr_info("wss: %lu\n", wss); 51 } 52 return 0; 53 } 54 55 static struct damon_call_control repeat_call_control = { 56 .fn = damon_sample_prcl_repeat_call_fn, 57 .repeat = true, 58 }; 59 60 static int damon_sample_prcl_start(void) 61 { 62 struct damon_target *target; 63 struct damos *scheme; 64 int err; 65 66 pr_info("start\n"); 67 68 ctx = damon_new_ctx(); 69 if (!ctx) 70 return -ENOMEM; 71 if (damon_select_ops(ctx, DAMON_OPS_VADDR)) { 72 damon_destroy_ctx(ctx); 73 return -EINVAL; 74 } 75 76 target = damon_new_target(); 77 if (!target) { 78 damon_destroy_ctx(ctx); 79 return -ENOMEM; 80 } 81 damon_add_target(ctx, target); 82 target_pidp = find_get_pid(target_pid); 83 if (!target_pidp) { 84 damon_destroy_ctx(ctx); 85 return -EINVAL; 86 } 87 target->pid = target_pidp; 88 89 scheme = damon_new_scheme( 90 &(struct damos_access_pattern) { 91 .min_sz_region = PAGE_SIZE, 92 .max_sz_region = ULONG_MAX, 93 .min_nr_accesses = 0, 94 .max_nr_accesses = 0, 95 .min_age_region = 50, 96 .max_age_region = UINT_MAX}, 97 DAMOS_PAGEOUT, 98 0, 99 &(struct damos_quota){}, 100 &(struct damos_watermarks){}, 101 NUMA_NO_NODE); 102 if (!scheme) { 103 damon_destroy_ctx(ctx); 104 return -ENOMEM; 105 } 106 damon_set_schemes(ctx, &scheme, 1); 107 108 err = damon_start(&ctx, 1, true); 109 if (err) 110 return err; 111 112 repeat_call_control.data = ctx; 113 return damon_call(ctx, &repeat_call_control); 114 } 115 116 static void damon_sample_prcl_stop(void) 117 { 118 pr_info("stop\n"); 119 if (ctx) { 120 damon_stop(&ctx, 1); 121 damon_destroy_ctx(ctx); 122 } 123 } 124 125 static bool init_called; 126 127 static int damon_sample_prcl_enable_store( 128 const char *val, const struct kernel_param *kp) 129 { 130 bool is_enabled = enabled; 131 int err; 132 133 err = kstrtobool(val, &enabled); 134 if (err) 135 return err; 136 137 if (enabled == is_enabled) 138 return 0; 139 140 if (enabled) { 141 err = damon_sample_prcl_start(); 142 if (err) 143 enabled = false; 144 return err; 145 } 146 damon_sample_prcl_stop(); 147 return 0; 148 } 149 150 static int __init damon_sample_prcl_init(void) 151 { 152 int err = 0; 153 154 init_called = true; 155 if (enabled) { 156 err = damon_sample_prcl_start(); 157 if (err) 158 enabled = false; 159 } 160 return 0; 161 } 162 163 module_init(damon_sample_prcl_init); 164