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_after_aggregate(struct damon_ctx *c) 38 { 39 struct damon_target *t; 40 41 damon_for_each_target(t, c) { 42 struct damon_region *r; 43 unsigned long wss = 0; 44 45 damon_for_each_region(r, t) { 46 if (r->nr_accesses > 0) 47 wss += r->ar.end - r->ar.start; 48 } 49 pr_info("wss: %lu\n", wss); 50 } 51 return 0; 52 } 53 54 static int damon_sample_prcl_start(void) 55 { 56 struct damon_target *target; 57 struct damos *scheme; 58 59 pr_info("start\n"); 60 61 ctx = damon_new_ctx(); 62 if (!ctx) 63 return -ENOMEM; 64 if (damon_select_ops(ctx, DAMON_OPS_VADDR)) { 65 damon_destroy_ctx(ctx); 66 return -EINVAL; 67 } 68 69 target = damon_new_target(); 70 if (!target) { 71 damon_destroy_ctx(ctx); 72 return -ENOMEM; 73 } 74 damon_add_target(ctx, target); 75 target_pidp = find_get_pid(target_pid); 76 if (!target_pidp) { 77 damon_destroy_ctx(ctx); 78 return -EINVAL; 79 } 80 target->pid = target_pidp; 81 82 ctx->callback.after_aggregation = damon_sample_prcl_after_aggregate; 83 84 scheme = damon_new_scheme( 85 &(struct damos_access_pattern) { 86 .min_sz_region = PAGE_SIZE, 87 .max_sz_region = ULONG_MAX, 88 .min_nr_accesses = 0, 89 .max_nr_accesses = 0, 90 .min_age_region = 50, 91 .max_age_region = UINT_MAX}, 92 DAMOS_PAGEOUT, 93 0, 94 &(struct damos_quota){}, 95 &(struct damos_watermarks){}, 96 NUMA_NO_NODE); 97 if (!scheme) { 98 damon_destroy_ctx(ctx); 99 return -ENOMEM; 100 } 101 damon_set_schemes(ctx, &scheme, 1); 102 103 return damon_start(&ctx, 1, true); 104 } 105 106 static void damon_sample_prcl_stop(void) 107 { 108 pr_info("stop\n"); 109 if (ctx) { 110 damon_stop(&ctx, 1); 111 damon_destroy_ctx(ctx); 112 } 113 if (target_pidp) 114 put_pid(target_pidp); 115 } 116 117 static bool init_called; 118 119 static int damon_sample_prcl_enable_store( 120 const char *val, const struct kernel_param *kp) 121 { 122 bool is_enabled = enabled; 123 int err; 124 125 err = kstrtobool(val, &enabled); 126 if (err) 127 return err; 128 129 if (enabled == is_enabled) 130 return 0; 131 132 if (enabled) { 133 err = damon_sample_prcl_start(); 134 if (err) 135 enabled = false; 136 return err; 137 } 138 damon_sample_prcl_stop(); 139 return 0; 140 } 141 142 static int __init damon_sample_prcl_init(void) 143 { 144 int err = 0; 145 146 init_called = true; 147 if (enabled) { 148 err = damon_sample_prcl_start(); 149 if (err) 150 enabled = false; 151 } 152 return 0; 153 } 154 155 module_init(damon_sample_prcl_init); 156