wsse.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  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. #define pr_fmt(fmt) "damon_sample_wsse: " fmt
  8. #include <linux/damon.h>
  9. #include <linux/init.h>
  10. #include <linux/kernel.h>
  11. #include <linux/module.h>
  12. #ifdef MODULE_PARAM_PREFIX
  13. #undef MODULE_PARAM_PREFIX
  14. #endif
  15. #define MODULE_PARAM_PREFIX "damon_sample_wsse."
  16. static int target_pid __read_mostly;
  17. module_param(target_pid, int, 0600);
  18. static int damon_sample_wsse_enable_store(
  19. const char *val, const struct kernel_param *kp);
  20. static const struct kernel_param_ops enabled_param_ops = {
  21. .set = damon_sample_wsse_enable_store,
  22. .get = param_get_bool,
  23. };
  24. static bool enabled __read_mostly;
  25. module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
  26. MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_WSSE");
  27. static struct damon_ctx *ctx;
  28. static struct pid *target_pidp;
  29. static int damon_sample_wsse_repeat_call_fn(void *data)
  30. {
  31. struct damon_ctx *c = data;
  32. struct damon_target *t;
  33. damon_for_each_target(t, c) {
  34. struct damon_region *r;
  35. unsigned long wss = 0;
  36. damon_for_each_region(r, t) {
  37. if (r->nr_accesses > 0)
  38. wss += r->ar.end - r->ar.start;
  39. }
  40. pr_info("wss: %lu\n", wss);
  41. }
  42. return 0;
  43. }
  44. static struct damon_call_control repeat_call_control = {
  45. .fn = damon_sample_wsse_repeat_call_fn,
  46. .repeat = true,
  47. };
  48. static int damon_sample_wsse_start(void)
  49. {
  50. struct damon_target *target;
  51. int err;
  52. pr_info("start\n");
  53. ctx = damon_new_ctx();
  54. if (!ctx)
  55. return -ENOMEM;
  56. if (damon_select_ops(ctx, DAMON_OPS_VADDR)) {
  57. damon_destroy_ctx(ctx);
  58. return -EINVAL;
  59. }
  60. target = damon_new_target();
  61. if (!target) {
  62. damon_destroy_ctx(ctx);
  63. return -ENOMEM;
  64. }
  65. damon_add_target(ctx, target);
  66. target_pidp = find_get_pid(target_pid);
  67. if (!target_pidp) {
  68. damon_destroy_ctx(ctx);
  69. return -EINVAL;
  70. }
  71. target->pid = target_pidp;
  72. err = damon_start(&ctx, 1, true);
  73. if (err)
  74. return err;
  75. repeat_call_control.data = ctx;
  76. return damon_call(ctx, &repeat_call_control);
  77. }
  78. static void damon_sample_wsse_stop(void)
  79. {
  80. pr_info("stop\n");
  81. if (ctx) {
  82. damon_stop(&ctx, 1);
  83. damon_destroy_ctx(ctx);
  84. }
  85. }
  86. static int damon_sample_wsse_enable_store(
  87. const char *val, const struct kernel_param *kp)
  88. {
  89. bool is_enabled = enabled;
  90. int err;
  91. err = kstrtobool(val, &enabled);
  92. if (err)
  93. return err;
  94. if (enabled == is_enabled)
  95. return 0;
  96. if (!damon_initialized())
  97. return 0;
  98. if (enabled) {
  99. err = damon_sample_wsse_start();
  100. if (err)
  101. enabled = false;
  102. return err;
  103. }
  104. damon_sample_wsse_stop();
  105. return 0;
  106. }
  107. static int __init damon_sample_wsse_init(void)
  108. {
  109. int err = 0;
  110. if (!damon_initialized()) {
  111. err = -ENOMEM;
  112. if (enabled)
  113. enabled = false;
  114. }
  115. if (enabled) {
  116. err = damon_sample_wsse_start();
  117. if (err)
  118. enabled = false;
  119. }
  120. return err;
  121. }
  122. module_init(damon_sample_wsse_init);