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 static int target_pid __read_mostly; 15 module_param(target_pid, int, 0600); 16 17 static int damon_sample_prcl_enable_store( 18 const char *val, const struct kernel_param *kp); 19 20 static const struct kernel_param_ops enable_param_ops = { 21 .set = damon_sample_prcl_enable_store, 22 .get = param_get_bool, 23 }; 24 25 static bool enable __read_mostly; 26 module_param_cb(enable, &enable_param_ops, &enable, 0600); 27 MODULE_PARM_DESC(enable, "Enable of disable DAMON_SAMPLE_WSSE"); 28 29 static struct damon_ctx *ctx; 30 static struct pid *target_pidp; 31 32 static int damon_sample_prcl_after_aggregate(struct damon_ctx *c) 33 { 34 struct damon_target *t; 35 36 damon_for_each_target(t, c) { 37 struct damon_region *r; 38 unsigned long wss = 0; 39 40 damon_for_each_region(r, t) { 41 if (r->nr_accesses > 0) 42 wss += r->ar.end - r->ar.start; 43 } 44 pr_info("wss: %lu\n", wss); 45 } 46 return 0; 47 } 48 49 static int damon_sample_prcl_start(void) 50 { 51 struct damon_target *target; 52 struct damos *scheme; 53 54 pr_info("start\n"); 55 56 ctx = damon_new_ctx(); 57 if (!ctx) 58 return -ENOMEM; 59 if (damon_select_ops(ctx, DAMON_OPS_VADDR)) { 60 damon_destroy_ctx(ctx); 61 return -EINVAL; 62 } 63 64 target = damon_new_target(); 65 if (!target) { 66 damon_destroy_ctx(ctx); 67 return -ENOMEM; 68 } 69 damon_add_target(ctx, target); 70 target_pidp = find_get_pid(target_pid); 71 if (!target_pidp) { 72 damon_destroy_ctx(ctx); 73 return -EINVAL; 74 } 75 target->pid = target_pidp; 76 77 ctx->callback.after_aggregation = damon_sample_prcl_after_aggregate; 78 79 scheme = damon_new_scheme( 80 &(struct damos_access_pattern) { 81 .min_sz_region = PAGE_SIZE, 82 .max_sz_region = ULONG_MAX, 83 .min_nr_accesses = 0, 84 .max_nr_accesses = 0, 85 .min_age_region = 50, 86 .max_age_region = UINT_MAX}, 87 DAMOS_PAGEOUT, 88 0, 89 &(struct damos_quota){}, 90 &(struct damos_watermarks){}, 91 NUMA_NO_NODE); 92 if (!scheme) { 93 damon_destroy_ctx(ctx); 94 return -ENOMEM; 95 } 96 damon_set_schemes(ctx, &scheme, 1); 97 98 return damon_start(&ctx, 1, true); 99 } 100 101 static void damon_sample_prcl_stop(void) 102 { 103 pr_info("stop\n"); 104 if (ctx) { 105 damon_stop(&ctx, 1); 106 damon_destroy_ctx(ctx); 107 } 108 if (target_pidp) 109 put_pid(target_pidp); 110 } 111 112 static int damon_sample_prcl_enable_store( 113 const char *val, const struct kernel_param *kp) 114 { 115 bool enabled = enable; 116 int err; 117 118 err = kstrtobool(val, &enable); 119 if (err) 120 return err; 121 122 if (enable == enabled) 123 return 0; 124 125 if (enable) 126 return damon_sample_prcl_start(); 127 damon_sample_prcl_stop(); 128 return 0; 129 } 130 131 static int __init damon_sample_prcl_init(void) 132 { 133 return 0; 134 } 135 136 module_init(damon_sample_prcl_init); 137