1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * working set size estimation: monitor access pattern of given process and 4 * print estimated working set size (total size of regions that showing some 5 * access). 6 */ 7 8 #define pr_fmt(fmt) "damon_sample_wsse: " fmt 9 10 #include <linux/damon.h> 11 #include <linux/init.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 15 static int target_pid __read_mostly; 16 module_param(target_pid, int, 0600); 17 18 static int damon_sample_wsse_enable_store( 19 const char *val, const struct kernel_param *kp); 20 21 static const struct kernel_param_ops enable_param_ops = { 22 .set = damon_sample_wsse_enable_store, 23 .get = param_get_bool, 24 }; 25 26 static bool enable __read_mostly; 27 module_param_cb(enable, &enable_param_ops, &enable, 0600); 28 MODULE_PARM_DESC(enable, "Enable or disable DAMON_SAMPLE_WSSE"); 29 30 static struct damon_ctx *ctx; 31 static struct pid *target_pidp; 32 33 static int damon_sample_wsse_after_aggregate(struct damon_ctx *c) 34 { 35 struct damon_target *t; 36 37 damon_for_each_target(t, c) { 38 struct damon_region *r; 39 unsigned long wss = 0; 40 41 damon_for_each_region(r, t) { 42 if (r->nr_accesses > 0) 43 wss += r->ar.end - r->ar.start; 44 } 45 pr_info("wss: %lu\n", wss); 46 } 47 return 0; 48 } 49 50 static int damon_sample_wsse_start(void) 51 { 52 struct damon_target *target; 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_wsse_after_aggregate; 78 return damon_start(&ctx, 1, true); 79 } 80 81 static void damon_sample_wsse_stop(void) 82 { 83 pr_info("stop\n"); 84 if (ctx) { 85 damon_stop(&ctx, 1); 86 damon_destroy_ctx(ctx); 87 } 88 if (target_pidp) 89 put_pid(target_pidp); 90 } 91 92 static int damon_sample_wsse_enable_store( 93 const char *val, const struct kernel_param *kp) 94 { 95 bool enabled = enable; 96 int err; 97 98 err = kstrtobool(val, &enable); 99 if (err) 100 return err; 101 102 if (enable == enabled) 103 return 0; 104 105 if (enable) 106 return damon_sample_wsse_start(); 107 damon_sample_wsse_stop(); 108 return 0; 109 } 110 111 static int __init damon_sample_wsse_init(void) 112 { 113 return 0; 114 } 115 116 module_init(damon_sample_wsse_init); 117