prcl.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. #define pr_fmt(fmt) "damon_sample_prcl: " fmt
  7. #include <linux/damon.h>
  8. #include <linux/init.h>
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #ifdef MODULE_PARAM_PREFIX
  12. #undef MODULE_PARAM_PREFIX
  13. #endif
  14. #define MODULE_PARAM_PREFIX "damon_sample_prcl."
  15. static int target_pid __read_mostly;
  16. module_param(target_pid, int, 0600);
  17. static int damon_sample_prcl_enable_store(
  18. const char *val, const struct kernel_param *kp);
  19. static const struct kernel_param_ops enabled_param_ops = {
  20. .set = damon_sample_prcl_enable_store,
  21. .get = param_get_bool,
  22. };
  23. static bool enabled __read_mostly;
  24. module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
  25. MODULE_PARM_DESC(enabled, "Enable or disable DAMON_SAMPLE_PRCL");
  26. static struct damon_ctx *ctx;
  27. static struct pid *target_pidp;
  28. static int damon_sample_prcl_repeat_call_fn(void *data)
  29. {
  30. struct damon_ctx *c = data;
  31. struct damon_target *t;
  32. damon_for_each_target(t, c) {
  33. struct damon_region *r;
  34. unsigned long wss = 0;
  35. damon_for_each_region(r, t) {
  36. if (r->nr_accesses > 0)
  37. wss += r->ar.end - r->ar.start;
  38. }
  39. pr_info("wss: %lu\n", wss);
  40. }
  41. return 0;
  42. }
  43. static struct damon_call_control repeat_call_control = {
  44. .fn = damon_sample_prcl_repeat_call_fn,
  45. .repeat = true,
  46. };
  47. static int damon_sample_prcl_start(void)
  48. {
  49. struct damon_target *target;
  50. struct damos *scheme;
  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. scheme = damon_new_scheme(
  73. &(struct damos_access_pattern) {
  74. .min_sz_region = PAGE_SIZE,
  75. .max_sz_region = ULONG_MAX,
  76. .min_nr_accesses = 0,
  77. .max_nr_accesses = 0,
  78. .min_age_region = 50,
  79. .max_age_region = UINT_MAX},
  80. DAMOS_PAGEOUT,
  81. 0,
  82. &(struct damos_quota){},
  83. &(struct damos_watermarks){},
  84. NUMA_NO_NODE);
  85. if (!scheme) {
  86. damon_destroy_ctx(ctx);
  87. return -ENOMEM;
  88. }
  89. damon_set_schemes(ctx, &scheme, 1);
  90. err = damon_start(&ctx, 1, true);
  91. if (err)
  92. return err;
  93. repeat_call_control.data = ctx;
  94. return damon_call(ctx, &repeat_call_control);
  95. }
  96. static void damon_sample_prcl_stop(void)
  97. {
  98. pr_info("stop\n");
  99. if (ctx) {
  100. damon_stop(&ctx, 1);
  101. damon_destroy_ctx(ctx);
  102. }
  103. }
  104. static int damon_sample_prcl_enable_store(
  105. const char *val, const struct kernel_param *kp)
  106. {
  107. bool is_enabled = enabled;
  108. int err;
  109. err = kstrtobool(val, &enabled);
  110. if (err)
  111. return err;
  112. if (enabled == is_enabled)
  113. return 0;
  114. if (!damon_initialized())
  115. return 0;
  116. if (enabled) {
  117. err = damon_sample_prcl_start();
  118. if (err)
  119. enabled = false;
  120. return err;
  121. }
  122. damon_sample_prcl_stop();
  123. return 0;
  124. }
  125. static int __init damon_sample_prcl_init(void)
  126. {
  127. int err = 0;
  128. if (!damon_initialized()) {
  129. if (enabled)
  130. enabled = false;
  131. return -ENOMEM;
  132. }
  133. if (enabled) {
  134. err = damon_sample_prcl_start();
  135. if (err)
  136. enabled = false;
  137. }
  138. return 0;
  139. }
  140. module_init(damon_sample_prcl_init);