* [RFC PATCH v2 0/4] mm/damon: Support hot application detections
@ 2026-03-10 16:24 gutierrez.asier
2026-03-10 16:24 ` [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules gutierrez.asier
` (4 more replies)
0 siblings, 5 replies; 20+ messages in thread
From: gutierrez.asier @ 2026-03-10 16:24 UTC (permalink / raw)
To: gutierrez.asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, sj, akpm, linux-mm, linux-kernel
From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Overview
----------
This patch set introduces a new dynamic mechanism for detecting hot applications
and hot regions in those applications.
Motivation
-----------
Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
fragmentation and memory waste. For this reason, most application guides and
system administrators suggest to disable THP.
Solution
-----------
A new Linux kernel module that uses DAMON to detect hot regions and collapse
those regions into huge pages. The user supplies a set of PIDs using a module
parameter, and then, the module launches a new kdamond thread to monitor each
of the tasks.
In each kdamond, we start with a high min_access value. Our goal is to find the
"maximum" min_access value at which point the DAMON action is applied. In each
cycle, if no action is applied, we lower the min_access.
Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
collapse synchronously and avoid polluting khugepaged and other parts of the MM
subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
which needs the correct vm_flags_t set.
-----------
Changes in v2:
- Previously there was a mechanism to automatically detect hot applications.
Based on SeongJae Park's feedback [1], this was removed from the module, leaving
it entirely to the user space.
- All allocations now use kzalloc_obj.
- Since the user space provides now the list of pids to monitor, a commit_input
parameter is added to allow changing the pids while the module runs.
- Renamed the module from dynamic_hugepages to hugepages
[1]: https://lore.kernel.org/all/20260211150902.70066-1-sj@kernel.org/
Asier Gutierrez (4):
Damon_modules_new_paddr_ctx_target. This works only for physical
contexts. In case of virtual addresses, we should duplicate the
code.
Support for huge pages collapse, which will be used by
dynamic_hugepages module.
This new module launches a new kdamond thread for each of them. The
purpose is to detect hot regions in a given list of tasks and
collapse them into huge pages.
DAMON_HOT_HUGEPAGE documentation
.../admin-guide/mm/damon/hugepage.rst (new) | 186 ++++++++
include/linux/damon.h | 1 +
mm/damon/Kconfig | 7 +
mm/damon/Makefile | 1 +
mm/damon/hugepage.c (new) | 441 ++++++++++++++++++
mm/damon/lru_sort.c | 5 +-
mm/damon/modules-common.c | 6 +-
mm/damon/modules-common.h | 4 +-
mm/damon/reclaim.c | 5 +-
mm/damon/vaddr.c | 3 +
10 files changed, 650 insertions(+), 9 deletions(-)
create mode 100644 Documentation/admin-guide/mm/damon/hugepage.rst
create mode 100644 mm/damon/hugepage.c
--
2.43.0
^ permalink raw reply [flat|nested] 20+ messages in thread
* [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
@ 2026-03-10 16:24 ` gutierrez.asier
2026-03-11 0:57 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse gutierrez.asier
` (3 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: gutierrez.asier @ 2026-03-10 16:24 UTC (permalink / raw)
To: gutierrez.asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, sj, akpm, linux-mm, linux-kernel
From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
It is more elegant to have a generic version of new context creation
which receives the mode as a parameter.
Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
---
mm/damon/lru_sort.c | 5 +++--
mm/damon/modules-common.c | 6 +++---
mm/damon/modules-common.h | 4 ++--
mm/damon/reclaim.c | 5 +++--
4 files changed, 11 insertions(+), 9 deletions(-)
diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
index 7bc5c0b2aea3..143ee0b21da6 100644
--- a/mm/damon/lru_sort.c
+++ b/mm/damon/lru_sort.c
@@ -287,7 +287,8 @@ static int damon_lru_sort_apply_parameters(void)
unsigned int hot_thres, cold_thres;
int err;
- err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
+ err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
+ DAMON_OPS_PADDR);
if (err)
return err;
@@ -479,7 +480,7 @@ static int __init damon_lru_sort_init(void)
err = -ENOMEM;
goto out;
}
- err = damon_modules_new_paddr_ctx_target(&ctx, &target);
+ err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
if (err)
goto out;
diff --git a/mm/damon/modules-common.c b/mm/damon/modules-common.c
index 86d58f8c4f63..ae50b2fa3a86 100644
--- a/mm/damon/modules-common.c
+++ b/mm/damon/modules-common.c
@@ -14,8 +14,8 @@
* @ctxp: Pointer to save the point to the newly created context
* @targetp: Pointer to save the point to the newly created target
*/
-int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
- struct damon_target **targetp)
+int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
+ struct damon_target **targetp, enum damon_ops_id mode)
{
struct damon_ctx *ctx;
struct damon_target *target;
@@ -24,7 +24,7 @@ int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
if (!ctx)
return -ENOMEM;
- if (damon_select_ops(ctx, DAMON_OPS_PADDR)) {
+ if (damon_select_ops(ctx, mode)) {
damon_destroy_ctx(ctx);
return -EINVAL;
}
diff --git a/mm/damon/modules-common.h b/mm/damon/modules-common.h
index f103ad556368..379b49c6a617 100644
--- a/mm/damon/modules-common.h
+++ b/mm/damon/modules-common.h
@@ -45,5 +45,5 @@
module_param_named(nr_##qt_exceed_name, stat.qt_exceeds, ulong, \
0400);
-int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
- struct damon_target **targetp);
+int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
+ struct damon_target **targetp, enum damon_ops_id mode);
diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
index 43d76f5bed44..24786a58683a 100644
--- a/mm/damon/reclaim.c
+++ b/mm/damon/reclaim.c
@@ -197,7 +197,8 @@ static int damon_reclaim_apply_parameters(void)
struct damos_filter *filter;
int err;
- err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
+ err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
+ DAMON_OPS_PADDR);
if (err)
return err;
@@ -381,7 +382,7 @@ static int __init damon_reclaim_init(void)
err = -ENOMEM;
goto out;
}
- err = damon_modules_new_paddr_ctx_target(&ctx, &target);
+ err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
if (err)
goto out;
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
2026-03-10 16:24 ` [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules gutierrez.asier
@ 2026-03-10 16:24 ` gutierrez.asier
2026-03-11 1:02 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 3/4] mm/damon: New module with hot application detection gutierrez.asier
` (2 subsequent siblings)
4 siblings, 1 reply; 20+ messages in thread
From: gutierrez.asier @ 2026-03-10 16:24 UTC (permalink / raw)
To: gutierrez.asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, sj, akpm, linux-mm, linux-kernel
From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
---
include/linux/damon.h | 1 +
mm/damon/vaddr.c | 3 +++
2 files changed, 4 insertions(+)
diff --git a/include/linux/damon.h b/include/linux/damon.h
index a4fea23da857..a9cf17b9e8fa 100644
--- a/include/linux/damon.h
+++ b/include/linux/damon.h
@@ -142,6 +142,7 @@ enum damos_action {
DAMOS_LRU_DEPRIO,
DAMOS_MIGRATE_HOT,
DAMOS_MIGRATE_COLD,
+ DAMOS_COLLAPSE,
DAMOS_STAT, /* Do nothing but only record the stat */
NR_DAMOS_ACTIONS,
};
diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
index 729b7ffd3565..36791a9a1094 100644
--- a/mm/damon/vaddr.c
+++ b/mm/damon/vaddr.c
@@ -969,6 +969,9 @@ static unsigned long damon_va_apply_scheme(struct damon_ctx *ctx,
case DAMOS_NOHUGEPAGE:
madv_action = MADV_NOHUGEPAGE;
break;
+ case DAMOS_COLLAPSE:
+ madv_action = MADV_COLLAPSE;
+ break;
case DAMOS_MIGRATE_HOT:
case DAMOS_MIGRATE_COLD:
return damos_va_migrate(t, r, scheme, sz_filter_passed);
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH v2 3/4] mm/damon: New module with hot application detection
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
2026-03-10 16:24 ` [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules gutierrez.asier
2026-03-10 16:24 ` [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse gutierrez.asier
@ 2026-03-10 16:24 ` gutierrez.asier
2026-03-11 4:11 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 4/4] DAMON_HOT_HUGEPAGE documentation gutierrez.asier
2026-03-11 5:07 ` [RFC PATCH v2 0/4] mm/damon: Support hot application detections SeongJae Park
4 siblings, 1 reply; 20+ messages in thread
From: gutierrez.asier @ 2026-03-10 16:24 UTC (permalink / raw)
To: gutierrez.asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, sj, akpm, linux-mm, linux-kernel
From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
1. It first launches a new kthread called damon_dynamic. This thread
will behave as a supervisor, launching new kdamond threads for all
the processes we want to montiored. The tasks are sorted
by utime delta. For the top N tasks, a new kdamond thread will be
launched. Applications which turn cold will have their kdamond
stopped.
The processes are supplied by the monitored_pids parameter. When the
module is enabled, it will go through all the monitored_pids, start
the supervisor and a new kdamond thread for each of the tasks. This
tasks can be modified and applied using the commit_input parameters.
In that case, we will stop any kdamond thread for tasks that are not
going to be monitored anymore, and start a new kdamond thread for each
new task to be monitored. For tasks that were monitored before and are
still monitored after commiting a new monitored_pids list, kdamond
threads are left intact.
2. Initially we don't know the min_access for each of the task. We
want to find the highest min_access when collapses start happening.
For that we have an initial threashold of 90, which we will lower
until a collpase occurs.
Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
---
mm/damon/Kconfig | 7 +
mm/damon/Makefile | 1 +
mm/damon/hugepage.c (new) | 441 ++++++++++++++++++++++++++++++++++++++
3 files changed, 449 insertions(+)
diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig
index 8c868f7035fc..2355aacb6d12 100644
--- a/mm/damon/Kconfig
+++ b/mm/damon/Kconfig
@@ -110,4 +110,11 @@ config DAMON_STAT_ENABLED_DEFAULT
Whether to enable DAMON_STAT by default. Users can disable it in
boot or runtime using its 'enabled' parameter.
+config DAMON_HOT_HUGEPAGE
+ bool "Build DAMON-based collapse of hot regions (DAMON_HOT_HUGEPAGES)"
+ depends on DAMON_VADDR
+ help
+ Collapse hot region into huge pages. Hot regions are determined by
+ DAMON-based sampling
+
endmenu
diff --git a/mm/damon/Makefile b/mm/damon/Makefile
index d8d6bf5f8bff..ac3afbc81cc7 100644
--- a/mm/damon/Makefile
+++ b/mm/damon/Makefile
@@ -7,3 +7,4 @@ obj-$(CONFIG_DAMON_SYSFS) += sysfs-common.o sysfs-schemes.o sysfs.o
obj-$(CONFIG_DAMON_RECLAIM) += modules-common.o reclaim.o
obj-$(CONFIG_DAMON_LRU_SORT) += modules-common.o lru_sort.o
obj-$(CONFIG_DAMON_STAT) += modules-common.o stat.o
+obj-$(CONFIG_DAMON_HOT_HUGEPAGE) += modules-common.o hugepage.o
diff --git a/mm/damon/hugepage.c b/mm/damon/hugepage.c
new file mode 100644
index 000000000000..ccd31c48d391
--- /dev/null
+++ b/mm/damon/hugepage.c
@@ -0,0 +1,441 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2026 HUAWEI, Inc.
+ * https://www.huawei.com
+ *
+ * Author: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
+ */
+
+#define pr_fmt(fmt) "damon-hugepage: " fmt
+
+#include <linux/damon.h>
+#include <linux/kstrtox.h>
+#include <linux/module.h>
+
+#include "modules-common.h"
+
+#ifdef MODULE_PARAM_PREFIX
+#undef MODULE_PARAM_PREFIX
+#endif
+#define MODULE_PARAM_PREFIX "damon_hugepage."
+
+#define MAX_MONITORED_PIDS 100
+#define HIGHEST_MIN_ACCESS 90
+#define HIGH_ACC_THRESHOLD 50
+#define MID_ACC_THRESHOLD 15
+#define LOW_ACC_THRESHOLD 2
+
+static struct task_struct *monitor_thread;
+
+struct mutex enable_disable_lock;
+
+/*
+ * Enable or disable DAMON_HUGEPAGE.
+ *
+ * You can enable DAMON_HUGEPAGE by setting the value of this parameter
+ * as ``Y``. Setting it as ``N`` disables DAMON_HOT_HUGEPAGE. Note that
+ * DAMON_HOT_HUGEPAGE could do no real monitoring and reclamation due to the
+ * watermarks-based activation condition. Refer to below descriptions for the
+ * watermarks parameter for this.
+ */
+static bool enabled __read_mostly;
+
+/*
+ * Make DAMON_HUGEPAGE reads the input parameters again, except ``enabled``.
+ *
+ * Input parameters that updated while DAMON_HUGEPAGE is running are not applied
+ * by default. Once this parameter is set as ``Y``, DAMON_HUGEPAGE reads values
+ * of parametrs except ``enabled`` again. Once the re-reading is done, this
+ * parameter is set as ``N``. If invalid parameters are found while the
+ * re-reading, DAMON_HUGEPAGE will be disabled.
+ */
+static bool commit_inputs __read_mostly;
+module_param(commit_inputs, bool, 0600);
+
+/*
+ * DAMON_HUGEPAGE monitoring period in microseconds.
+ * 5000000 = 5s
+ */
+static unsigned long monitor_period __read_mostly = 5000000;
+module_param(monitor_period, ulong, 0600);
+
+static long monitored_pids[MAX_MONITORED_PIDS];
+static int num_monitored_pids;
+module_param_array(monitored_pids, long, &num_monitored_pids, 0600);
+
+static struct damos_quota damon_hugepage_quota = {
+ /* use up to 10 ms time, reclaim up to 128 MiB per 1 sec by default */
+ .ms = 10,
+ .sz = 0,
+ .reset_interval = 1000,
+ /* Within the quota, page out older regions first. */
+ .weight_sz = 0,
+ .weight_nr_accesses = 0,
+ .weight_age = 1
+};
+DEFINE_DAMON_MODULES_DAMOS_TIME_QUOTA(damon_hugepage_quota);
+
+static struct damos_watermarks damon_hugepage_wmarks = {
+ .metric = DAMOS_WMARK_FREE_MEM_RATE,
+ .interval = 5000000, /* 5 seconds */
+ .high = 900, /* 90 percent */
+ .mid = 800, /* 80 percent */
+ .low = 50, /* 5 percent */
+};
+DEFINE_DAMON_MODULES_WMARKS_PARAMS(damon_hugepage_wmarks);
+
+static struct damon_attrs damon_hugepage_mon_attrs = {
+ .sample_interval = 5000, /* 5 ms */
+ .aggr_interval = 100000, /* 100 ms */
+ .ops_update_interval = 0,
+ .min_nr_regions = 10,
+ .max_nr_regions = 1000,
+};
+DEFINE_DAMON_MODULES_MON_ATTRS_PARAMS(damon_hugepage_mon_attrs);
+
+struct hugepage_task {
+ struct damon_ctx *ctx;
+ int pid;
+ struct damon_target *target;
+ struct damon_call_control call_control;
+ struct list_head list;
+};
+
+static struct damos *damon_hugepage_new_scheme(int min_access,
+ enum damos_action action)
+{
+ struct damos_access_pattern pattern = {
+ /* Find regions having PAGE_SIZE or larger size */
+ .min_sz_region = PMD_SIZE,
+ .max_sz_region = ULONG_MAX,
+ /* and not accessed at all */
+ .min_nr_accesses = min_access,
+ .max_nr_accesses = 100,
+ /* for min_age or more micro-seconds */
+ .min_age_region = 0,
+ .max_age_region = UINT_MAX,
+ };
+
+ return damon_new_scheme(
+ &pattern,
+ /* synchrounous partial collapse as soon as found */
+ action, 0,
+ /* under the quota. */
+ &damon_hugepage_quota,
+ /* (De)activate this according to the watermarks. */
+ &damon_hugepage_wmarks, NUMA_NO_NODE);
+}
+
+static int damon_hugepage_apply_parameters(
+ struct hugepage_task *monitored_task,
+ int min_access,
+ enum damos_action action)
+{
+ struct damos *scheme;
+ struct damon_ctx *param_ctx;
+ struct damon_target *param_target;
+ struct damos_filter *filter;
+ int err;
+ struct pid *spid;
+
+ err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
+ DAMON_OPS_VADDR);
+ if (err)
+ return err;
+
+ spid = find_get_pid(monitored_task->pid);
+ if (!spid)
+ return err;
+
+ param_target->pid = spid;
+
+ err = damon_set_attrs(param_ctx, &damon_hugepage_mon_attrs);
+ if (err)
+ goto out;
+
+ err = -ENOMEM;
+ scheme = damon_hugepage_new_scheme(min_access, action);
+ if (!scheme)
+ goto out;
+
+ damon_set_schemes(param_ctx, &scheme, 1);
+
+ filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, false);
+ if (!filter)
+ goto out;
+ damos_add_filter(scheme, filter);
+
+ err = damon_commit_ctx(monitored_task->ctx, param_ctx);
+out:
+ damon_destroy_ctx(param_ctx);
+ return err;
+}
+
+static int damon_hugepage_damon_call_fn(void *arg)
+{
+ struct hugepage_task *monitored_task = arg;
+ struct damon_ctx *ctx = monitored_task->ctx;
+ struct damos *scheme;
+ int err = 0;
+ int min_access;
+ struct damos_stat stat;
+
+ damon_for_each_scheme(scheme, ctx)
+ stat = scheme->stat;
+ scheme = list_first_entry(&ctx->schemes, struct damos, list);
+
+ if (ctx->passed_sample_intervals < scheme->next_apply_sis)
+ return err;
+
+ if (stat.nr_applied)
+ return err;
+
+ min_access = scheme->pattern.min_nr_accesses;
+
+ if (min_access > HIGH_ACC_THRESHOLD) {
+ min_access = min_access - 10;
+ err = damon_hugepage_apply_parameters(
+ monitored_task, min_access, DAMOS_COLLAPSE);
+ } else if (min_access > MID_ACC_THRESHOLD) {
+ min_access = min_access - 5;
+ err = damon_hugepage_apply_parameters(
+ monitored_task, min_access, DAMOS_COLLAPSE);
+ } else if (min_access > LOW_ACC_THRESHOLD) {
+ min_access = min_access - 1;
+ err = damon_hugepage_apply_parameters(
+ monitored_task, min_access, DAMOS_COLLAPSE);
+ }
+ return err;
+}
+
+static int damon_hugepage_init_task(struct hugepage_task *monitored_task)
+{
+ int err = 0;
+ struct damon_ctx *ctx = monitored_task->ctx;
+ struct damon_target *target = monitored_task->target;
+ struct pid *spid;
+
+ if (!ctx || !target)
+ damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_VADDR);
+
+ if (damon_is_running(ctx))
+ return 0;
+
+ spid = find_get_pid(monitored_task->pid);
+ if (!spid)
+ return err;
+
+ target->pid = spid;
+
+ monitored_task->call_control.fn = damon_hugepage_damon_call_fn;
+ monitored_task->call_control.repeat = true;
+ monitored_task->call_control.data = monitored_task;
+
+ struct damos *scheme = damon_hugepage_new_scheme(
+ HIGHEST_MIN_ACCESS, DAMOS_COLLAPSE);
+ if (!scheme)
+ return -ENOMEM;
+
+ damon_set_schemes(ctx, &scheme, 1);
+
+ monitored_task->ctx = ctx;
+ err = damon_start(&monitored_task->ctx, 1, false);
+ if (err)
+ return err;
+
+ return damon_call(monitored_task->ctx, &monitored_task->call_control);
+}
+
+static int add_monitored_task(int pid, struct list_head *task_monitor)
+{
+ struct hugepage_task *new_hugepage_task;
+ int err;
+
+ new_hugepage_task = kzalloc_obj(*new_hugepage_task);
+ if (!new_hugepage_task)
+ return -ENOMEM;
+
+ new_hugepage_task->pid = pid;
+ INIT_LIST_HEAD(&new_hugepage_task->list);
+ err = damon_hugepage_init_task(new_hugepage_task);
+ if (err)
+ return err;
+ list_add(&new_hugepage_task->list, task_monitor);
+ return 0;
+}
+
+static int damon_hugepage_handle_commit_inputs(
+ struct list_head *monitored_tasks)
+{
+ int i = 0;
+ int err = 0;
+ bool found;
+ struct hugepage_task *monitored_task, *tmp;
+
+ if (!commit_inputs)
+ return 0;
+
+ while (i < MAX_MONITORED_PIDS) {
+ if (!monitored_pids[i])
+ break;
+
+ found = false;
+
+ rcu_read_lock();
+ if (!find_vpid(monitored_pids[i])) {
+ rcu_read_unlock();
+ continue;
+ }
+
+ rcu_read_unlock();
+
+ list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
+ if (monitored_task->pid == monitored_pids[i]) {
+ list_move(&monitored_task->list, monitored_tasks);
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ err = add_monitored_task(monitored_pids[i], monitored_tasks);
+ /* Skip failed tasks */
+ if (err)
+ continue;
+ }
+ i++;
+ }
+
+ i = 0;
+ list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
+ i++;
+ if (i <= num_monitored_pids)
+ continue;
+
+ err = damon_stop(&monitored_task->ctx, 1);
+ damon_destroy_ctx(monitored_task->ctx);
+ list_del(&monitored_task->list);
+ kfree(monitored_task);
+ }
+
+ commit_inputs = false;
+ return err;
+}
+
+static int damon_manager_monitor_thread(void *data)
+{
+ int err = 0;
+ int i;
+ struct hugepage_task *entry, *tmp;
+
+ LIST_HEAD(monitored_tasks);
+
+ for (i = 0; i < MAX_MONITORED_PIDS; i++) {
+ if (!monitored_pids[i])
+ break;
+
+ rcu_read_lock();
+ if (!find_vpid(monitored_pids[i])) {
+ rcu_read_unlock();
+ continue;
+ }
+ rcu_read_unlock();
+
+ add_monitored_task(monitored_pids[i], &monitored_tasks);
+ }
+
+
+ while (!kthread_should_stop()) {
+ schedule_timeout_idle(usecs_to_jiffies(monitor_period));
+ err = damon_hugepage_handle_commit_inputs(&monitored_tasks);
+ if (err)
+ break;
+ }
+
+ list_for_each_entry_safe(entry, tmp, &monitored_tasks, list) {
+ err = damon_stop(&entry->ctx, 1);
+ damon_destroy_ctx(entry->ctx);
+ }
+
+ for (int i = 0; i < MAX_MONITORED_PIDS;) {
+ monitored_pids[i] = 0;
+ i++;
+ }
+ return err;
+}
+
+static int damon_hugepage_start_monitor_thread(void)
+{
+ num_monitored_pids = 0;
+ monitor_thread = kthread_create(damon_manager_monitor_thread, NULL,
+ "damon_dynamic");
+
+ if (IS_ERR(monitor_thread))
+ return PTR_ERR(monitor_thread);
+
+ wake_up_process(monitor_thread);
+ return 0;
+}
+
+static int damon_hugepage_turn(bool on)
+{
+ int err = 0;
+
+ mutex_lock(&enable_disable_lock);
+ if (!on) {
+ if (monitor_thread) {
+ kthread_stop(monitor_thread);
+ monitor_thread = NULL;
+ }
+ goto out;
+ }
+ err = damon_hugepage_start_monitor_thread();
+out:
+ mutex_unlock(&enable_disable_lock);
+ return err;
+}
+
+static int damon_hugepage_enabled_store(const char *val,
+ const struct kernel_param *kp)
+{
+ bool is_enabled = enabled;
+ bool enable;
+ int err;
+
+ err = kstrtobool(val, &enable);
+ if (err)
+ return err;
+
+ if (is_enabled == enable)
+ return 0;
+
+ err = damon_hugepage_turn(enable);
+ if (err)
+ return err;
+
+ enabled = enable;
+ return err;
+}
+
+static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_hugepage_enabled_store,
+ .get = param_get_bool,
+};
+
+module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
+MODULE_PARM_DESC(enabled,
+ "Enable or disable DAMON_DYNAMIC_HUGEPAGES (default: disabled)");
+
+static int __init damon_hugepage_init(void)
+{
+ int err;
+
+ /* 'enabled' has set before this function, probably via command line */
+ if (enabled)
+ err = damon_hugepage_turn(true);
+
+ if (err && enabled)
+ enabled = false;
+ return err;
+}
+
+module_init(damon_hugepage_init);
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* [RFC PATCH v2 4/4] DAMON_HOT_HUGEPAGE documentation
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
` (2 preceding siblings ...)
2026-03-10 16:24 ` [RFC PATCH v2 3/4] mm/damon: New module with hot application detection gutierrez.asier
@ 2026-03-10 16:24 ` gutierrez.asier
2026-03-11 5:07 ` [RFC PATCH v2 0/4] mm/damon: Support hot application detections SeongJae Park
4 siblings, 0 replies; 20+ messages in thread
From: gutierrez.asier @ 2026-03-10 16:24 UTC (permalink / raw)
To: gutierrez.asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, sj, akpm, linux-mm, linux-kernel
From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Documentation for hugepage DAMON module.
Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
---
.../admin-guide/mm/damon/hugepage.rst (new) | 186 ++++++++++++++++++
1 file changed, 186 insertions(+)
diff --git a/Documentation/admin-guide/mm/damon/hugepage.rst b/Documentation/admin-guide/mm/damon/hugepage.rst
new file mode 100644
index 000000000000..a7b20a670824
--- /dev/null
+++ b/Documentation/admin-guide/mm/damon/hugepage.rst
@@ -0,0 +1,186 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=========================================
+DAMON-based Huge Pages Collapsing
+=========================================
+
+
+DAMON-based dynamic hugepages collapsing (DAMON_HOT_HUGEPAGE) is a kernel module
+that monitors a number of tasks simultaneously. The hot regions are collapsed
+into huge pages.
+
+Where Hot Region Huge Pages Collapsing is Required?
+================================================
+
+As main memory availability increases, the number of TLB entries does not
+increase proportionally. This adds more pressure to TLB. Huge pages are a
+solution. However, since turning on transparent huge pages globally may lead to
+fragmentation and memory waste, it is usually turned off.
+
+This module allows to automatically detect hot regions and collapse VMA that are
+hot.
+
+How It Works?
+=============
+
+DAMON_HOT_HUGEPAGE spawns a new kthread which will monitor the applications in
+the system. The monitor thread will calculate the moving average of the sum of
+utimes of all the threads for all the processes. Then, pick the top three and
+launch a damon process to monitor the hot regions in those tasks.
+
+Since we don't know the minaccess number in advance, we set it to 90 initially,
+and we keep decreasing that minaccess until a collapse happens.
+
+If a task turns cold, the monitor thread will detect it (it will not fall in the
+top three hot tasks), and stop the damon thread for that task.
+
+Interface: Module Parameters
+============================
+
+To use this feature, you should first ensure your system is running on a kernel
+that is built with CONFIG_DAMON_HOT_HUGEPAGE=y.
+
+To let sysadmins enable or disable it and tune for the given system,
+DAMON_HOT_HUGEPAGE utilizes module parameters. That is, you can put
+damon_dynamic_hotpages.<parameter>=<value> on the kernel boot command line or
+write proper values to /sys/module/damon_dynamic_hotpages/parameters/<parameter>
+files.
+
+Below are the description of each parameter.
+
+enabled
+-------
+
+Enable or disable DAMON_HOT_HUGEPAGE.
+
+You can enable DAMON_HOT_HUGEPAGE by setting the value of this parameter as Y.
+Setting it as N disables DAMON_HOT_HUGEPAGE. Note that, although
+DAMON_HOT_HUGEPAGE monitors the system and starts damon threads, those threads
+could do no real monitoring due to the watermarks-based activation condition.
+Refer to below descriptions for the watermarks parameter for this.
+
+quota_ms
+--------
+
+Limit of time for collapsing memory regions in milliseconds.
+
+DAMON_HOT_HUGEPAGE tries to use only up to this time within a time window
+(quota_reset_interval_ms) for trying memory collapse. This can be used for
+limiting CPU consumption of DAMONHOT_HUGEPAGE. If the value is zero, the limit
+is disabled.
+
+10 ms by default.
+
+quota_reset_interval_ms
+-----------------------
+
+The time quota charge reset interval in milliseconds.
+
+The charge reset interval for the quota of time (quota_ms). That is,
+DAMON_HOT_HUGEPAGE does not collapse memory for more than quota_ms milliseconds
+or quotasz bytes within quota_reset_interval_ms milliseconds.
+
+1 second by default.
+
+wmarks_interval
+---------------
+
+The watermarks check time interval in microseconds.
+
+Minimal time to wait before checking the watermarks, when DAMON_HOT_HUGEPAGE is
+enabled but inactive due to its watermarks rule. 5 seconds by default.
+
+wmarks_high
+-----------
+
+Free memory rate (per thousand) for the high watermark.
+
+If free memory of the system in bytes per thousand bytes is higher than this,
+DAMON_HOT_HUGEPAGE becomes inactive, so it does nothing but periodically checks
+the watermarks. 200 (20%) by default.
+
+wmarks_mid
+----------
+
+Free memory rate (per thousand) for the middle watermark.
+
+If free memory of the system in bytes per thousand bytes is between this and the
+low watermark, DAMON_HOT_HUGEPAGE becomes active, so starts the monitoring and
+the memory collapsing. 150 (15%) by default.
+
+wmarks_low
+----------
+
+Free memory rate (per thousand) for the low watermark.
+
+If free memory of the system in bytes per thousand bytes is lower than this,
+DAMON_HOT_HUGEPAGE becomes inactive, so it does nothing but periodically checks
+the watermarks. 50 (5%) by default.
+
+sample_interval
+---------------
+
+Sampling interval for the monitoring in microseconds.
+
+The sampling interval of DAMON for the cold memory monitoring. Please refer to
+the DAMON documentation (:doc:usage) for more detail. 5ms by default.
+
+aggr_interval
+-------------
+
+Aggregation interval for the monitoring in microseconds.
+
+The aggregation interval of DAMON for the cold memory monitoring. Please refer
+to the DAMON documentation (:doc:usage) for more detail. 100ms by default.
+
+min_nr_regions
+--------------
+
+Minimum number of monitoring regions.
+
+The minimal number of monitoring regions of DAMON for the cold memory
+monitoring. This can be used to set lower-bound of the monitoring quality. But,
+setting this too high could result in increased monitoring overhead. Please
+refer to the DAMON documentation (:doc:usage) for more detail. 10 by default.
+
+max_nr_regions
+--------------
+
+Maximum number of monitoring regions.
+
+The maximum number of monitoring regions of DAMON for the cold memory
+monitoring. This can be used to set upper-bound of the monitoring overhead.
+However, setting this too low could result in bad monitoring quality. Please
+refer to the DAMON documentation (:doc:usage) for more detail. 1000 by defaults.
+
+monitored_pids
+--------------
+
+List of the tasks that are being actively monitored by DAMON threads.
+
+commit_inputs
+-------------
+
+Make DAMON_HOT_HUGEPAGE reads the input parameters again, except ``enabled``.
+
+Input parameters that updated while DAMON_HOT_HUGEPAGE is running are not
+applied by default. Once this parameter is set as ``Y``, DAMON_HOT_HUGEPAGE
+reads values of parametrs except ``enabled`` again. Once the re-reading is done,
+this parameter is set as ``N``. If invalid parameters are found while the
+re-reading, DAMON_HOT_HUGEPAGE will be disabled.
+
+Example
+=======
+Below runtime example commands make DAMON_HOT_HUGEPAGE to find memory regions in
+the 3 tasks. It also asks DAMON_HOT_HUGEPAGE to do nothing if the system's free
+memory rate is more than 50%, but start the real works if it becomes lower than
+40%.
+
+ # cd /sys/module/damon_dynamic_hotpages/parameters/
+ # echo 3811,10123,12111 > monitored_pids
+ # echo 10 > quota_ms
+ # echo 1000 > quota_reset_interval_ms
+ # echo 500 > wmarks_high
+ # echo 400 > wmarks_mid
+ # echo 200 > wmarks_low
+ # echo Y > enabled
\ No newline at end of file
--
2.43.0
^ permalink raw reply related [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules
2026-03-10 16:24 ` [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules gutierrez.asier
@ 2026-03-11 0:57 ` SeongJae Park
2026-03-11 13:10 ` Gutierrez Asier
0 siblings, 1 reply; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 0:57 UTC (permalink / raw)
To: gutierrez.asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Tue, 10 Mar 2026 16:24:17 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>
> It is more elegant to have a generic version of new context creation
> which receives the mode as a parameter.
>
> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
> ---
> mm/damon/lru_sort.c | 5 +++--
> mm/damon/modules-common.c | 6 +++---
> mm/damon/modules-common.h | 4 ++--
> mm/damon/reclaim.c | 5 +++--
> 4 files changed, 11 insertions(+), 9 deletions(-)
>
> diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
> index 7bc5c0b2aea3..143ee0b21da6 100644
> --- a/mm/damon/lru_sort.c
> +++ b/mm/damon/lru_sort.c
> @@ -287,7 +287,8 @@ static int damon_lru_sort_apply_parameters(void)
> unsigned int hot_thres, cold_thres;
> int err;
>
> - err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
> + DAMON_OPS_PADDR);
I like the name of the function is becoming shorter. But I'm not happy with
the fact the resulting calling code becomes longer.
I understand you are doing this extension because you want a version of the
function for vaddr. What about introducing another dedicated function, say,
damon_modules_new_vaddr_ctx_target() ?
And you can avoid duplicates between damon_modules_new_{p,v}addr_ctx_target()
by implementing internal function, say, damon_modules_new_ctx_target() that
receives the damon_ops_id. And damon_modules_new_{P,v}addr_ctx_target() will
just wrappers of damon_modules_new_ctx_target().
> if (err)
> return err;
>
> @@ -479,7 +480,7 @@ static int __init damon_lru_sort_init(void)
> err = -ENOMEM;
> goto out;
> }
> - err = damon_modules_new_paddr_ctx_target(&ctx, &target);
> + err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
Ditto.
> if (err)
> goto out;
>
> diff --git a/mm/damon/modules-common.c b/mm/damon/modules-common.c
> index 86d58f8c4f63..ae50b2fa3a86 100644
> --- a/mm/damon/modules-common.c
> +++ b/mm/damon/modules-common.c
> @@ -14,8 +14,8 @@
> * @ctxp: Pointer to save the point to the newly created context
> * @targetp: Pointer to save the point to the newly created target
> */
> -int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
> - struct damon_target **targetp)
> +int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
> + struct damon_target **targetp, enum damon_ops_id mode)
Nit. I'd suggest 'ops_id' as the parameter name, instead of 'mode'.
> {
> struct damon_ctx *ctx;
> struct damon_target *target;
> @@ -24,7 +24,7 @@ int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
> if (!ctx)
> return -ENOMEM;
>
> - if (damon_select_ops(ctx, DAMON_OPS_PADDR)) {
> + if (damon_select_ops(ctx, mode)) {
> damon_destroy_ctx(ctx);
> return -EINVAL;
> }
> diff --git a/mm/damon/modules-common.h b/mm/damon/modules-common.h
> index f103ad556368..379b49c6a617 100644
> --- a/mm/damon/modules-common.h
> +++ b/mm/damon/modules-common.h
> @@ -45,5 +45,5 @@
> module_param_named(nr_##qt_exceed_name, stat.qt_exceeds, ulong, \
> 0400);
>
> -int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
> - struct damon_target **targetp);
> +int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
> + struct damon_target **targetp, enum damon_ops_id mode);
> diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
> index 43d76f5bed44..24786a58683a 100644
> --- a/mm/damon/reclaim.c
> +++ b/mm/damon/reclaim.c
> @@ -197,7 +197,8 @@ static int damon_reclaim_apply_parameters(void)
> struct damos_filter *filter;
> int err;
>
> - err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
> + DAMON_OPS_PADDR);
> if (err)
> return err;
>
> @@ -381,7 +382,7 @@ static int __init damon_reclaim_init(void)
> err = -ENOMEM;
> goto out;
> }
> - err = damon_modules_new_paddr_ctx_target(&ctx, &target);
> + err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
> if (err)
> goto out;
>
> --
> 2.43.0
Thanks,
SJ
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse
2026-03-10 16:24 ` [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse gutierrez.asier
@ 2026-03-11 1:02 ` SeongJae Park
2026-03-11 13:11 ` Gutierrez Asier
0 siblings, 1 reply; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 1:02 UTC (permalink / raw)
To: gutierrez.asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Tue, 10 Mar 2026 16:24:18 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
Please add more descriptions of the change, including the motivation.
I assume the motivation is similar to MADV_COLLAPSE that aims to make
synchronous and therefore faster huge page collapsing impacts copared to
MADV_HUGEPAGE? It would be nice to make it clear here. Also, if my assumption
is not wrong, adding a test results showing the benefit of DAMOS_COLLAPSE over
DAMOS_HUGEPAGE here would be nice.
>
> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
> ---
> include/linux/damon.h | 1 +
> mm/damon/vaddr.c | 3 +++
> 2 files changed, 4 insertions(+)
>
> diff --git a/include/linux/damon.h b/include/linux/damon.h
> index a4fea23da857..a9cf17b9e8fa 100644
> --- a/include/linux/damon.h
> +++ b/include/linux/damon.h
> @@ -142,6 +142,7 @@ enum damos_action {
> DAMOS_LRU_DEPRIO,
> DAMOS_MIGRATE_HOT,
> DAMOS_MIGRATE_COLD,
> + DAMOS_COLLAPSE,
> DAMOS_STAT, /* Do nothing but only record the stat */
> NR_DAMOS_ACTIONS,
> };
> diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
> index 729b7ffd3565..36791a9a1094 100644
> --- a/mm/damon/vaddr.c
> +++ b/mm/damon/vaddr.c
> @@ -969,6 +969,9 @@ static unsigned long damon_va_apply_scheme(struct damon_ctx *ctx,
> case DAMOS_NOHUGEPAGE:
> madv_action = MADV_NOHUGEPAGE;
> break;
> + case DAMOS_COLLAPSE:
> + madv_action = MADV_COLLAPSE;
> + break;
> case DAMOS_MIGRATE_HOT:
> case DAMOS_MIGRATE_COLD:
> return damos_va_migrate(t, r, scheme, sz_filter_passed);
> --
> 2.43.0
The code looks good to me.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 3/4] mm/damon: New module with hot application detection
2026-03-10 16:24 ` [RFC PATCH v2 3/4] mm/damon: New module with hot application detection gutierrez.asier
@ 2026-03-11 4:11 ` SeongJae Park
2026-03-11 13:45 ` Gutierrez Asier
0 siblings, 1 reply; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 4:11 UTC (permalink / raw)
To: gutierrez.asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Tue, 10 Mar 2026 16:24:19 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
I'd like to discuss about this in a high level, but I'd like to do that on the
cover letter. To this patch, I'm therefore adding comments for only details
that stand out immeadiately to me.
>
> 1. It first launches a new kthread called damon_dynamic. This thread
> will behave as a supervisor, launching new kdamond threads for all
> the processes we want to montiored. The tasks are sorted
> by utime delta. For the top N tasks, a new kdamond thread will be
> launched.
If I read the cover letter and the code of this patch correctly, seems the last
two sentences of the above paragraph is outdated. Please correct me if I'm
wrong.
> Applications which turn cold will have their kdamond
> stopped.
>
> The processes are supplied by the monitored_pids parameter. When the
> module is enabled, it will go through all the monitored_pids, start
> the supervisor and a new kdamond thread for each of the tasks. This
> tasks can be modified and applied using the commit_input parameters.
> In that case, we will stop any kdamond thread for tasks that are not
> going to be monitored anymore, and start a new kdamond thread for each
> new task to be monitored. For tasks that were monitored before and are
> still monitored after commiting a new monitored_pids list, kdamond
> threads are left intact.
>
> 2. Initially we don't know the min_access for each of the task. We
> want to find the highest min_access when collapses start happening.
> For that we have an initial threashold of 90, which we will lower
> until a collpase occurs.
>
> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
> ---
> mm/damon/Kconfig | 7 +
> mm/damon/Makefile | 1 +
> mm/damon/hugepage.c (new) | 441 ++++++++++++++++++++++++++++++++++++++
> 3 files changed, 449 insertions(+)
>
> diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig
> index 8c868f7035fc..2355aacb6d12 100644
> --- a/mm/damon/Kconfig
> +++ b/mm/damon/Kconfig
> @@ -110,4 +110,11 @@ config DAMON_STAT_ENABLED_DEFAULT
> Whether to enable DAMON_STAT by default. Users can disable it in
> boot or runtime using its 'enabled' parameter.
>
> +config DAMON_HOT_HUGEPAGE
I'd suggest renaming to DAMON_HUGEPAGE.
> + bool "Build DAMON-based collapse of hot regions (DAMON_HOT_HUGEPAGES)"
> + depends on DAMON_VADDR
> + help
> + Collapse hot region into huge pages. Hot regions are determined by
> + DAMON-based sampling
> +
> endmenu
> diff --git a/mm/damon/Makefile b/mm/damon/Makefile
> index d8d6bf5f8bff..ac3afbc81cc7 100644
> --- a/mm/damon/Makefile
> +++ b/mm/damon/Makefile
> @@ -7,3 +7,4 @@ obj-$(CONFIG_DAMON_SYSFS) += sysfs-common.o sysfs-schemes.o sysfs.o
> obj-$(CONFIG_DAMON_RECLAIM) += modules-common.o reclaim.o
> obj-$(CONFIG_DAMON_LRU_SORT) += modules-common.o lru_sort.o
> obj-$(CONFIG_DAMON_STAT) += modules-common.o stat.o
> +obj-$(CONFIG_DAMON_HOT_HUGEPAGE) += modules-common.o hugepage.o
> diff --git a/mm/damon/hugepage.c b/mm/damon/hugepage.c
> new file mode 100644
> index 000000000000..ccd31c48d391
> --- /dev/null
> +++ b/mm/damon/hugepage.c
> @@ -0,0 +1,441 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (C) 2026 HUAWEI, Inc.
> + * https://www.huawei.com
> + *
> + * Author: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> + */
> +
> +#define pr_fmt(fmt) "damon-hugepage: " fmt
> +
> +#include <linux/damon.h>
> +#include <linux/kstrtox.h>
> +#include <linux/module.h>
> +
> +#include "modules-common.h"
> +
> +#ifdef MODULE_PARAM_PREFIX
> +#undef MODULE_PARAM_PREFIX
> +#endif
> +#define MODULE_PARAM_PREFIX "damon_hugepage."
> +
> +#define MAX_MONITORED_PIDS 100
> +#define HIGHEST_MIN_ACCESS 90
> +#define HIGH_ACC_THRESHOLD 50
> +#define MID_ACC_THRESHOLD 15
> +#define LOW_ACC_THRESHOLD 2
On your setup where the sampling interval is 5ms and the aggregation interval
is 100ms, nr_accesses of each DAMON region can be up to only 20. So above
thresholds may better to be lowered.
> +
> +static struct task_struct *monitor_thread;
> +
> +struct mutex enable_disable_lock;
> +
> +/*
> + * Enable or disable DAMON_HUGEPAGE.
> + *
> + * You can enable DAMON_HUGEPAGE by setting the value of this parameter
> + * as ``Y``. Setting it as ``N`` disables DAMON_HOT_HUGEPAGE. Note that
> + * DAMON_HOT_HUGEPAGE could do no real monitoring and reclamation due to the
s/DAMON_HOT_HUGEPAGE/DAMON_HUGEPAGE/ ?
> + * watermarks-based activation condition. Refer to below descriptions for the
> + * watermarks parameter for this.
On RFC v1 discussion [1], you mentioned you will update this comment. But I
find no change?
> + */
> +static bool enabled __read_mostly;
> +
> +/*
> + * Make DAMON_HUGEPAGE reads the input parameters again, except ``enabled``.
> + *
> + * Input parameters that updated while DAMON_HUGEPAGE is running are not applied
> + * by default. Once this parameter is set as ``Y``, DAMON_HUGEPAGE reads values
> + * of parametrs except ``enabled`` again. Once the re-reading is done, this
> + * parameter is set as ``N``. If invalid parameters are found while the
> + * re-reading, DAMON_HUGEPAGE will be disabled.
> + */
> +static bool commit_inputs __read_mostly;
> +module_param(commit_inputs, bool, 0600);
> +
> +/*
> + * DAMON_HUGEPAGE monitoring period in microseconds.
> + * 5000000 = 5s
> + */
> +static unsigned long monitor_period __read_mostly = 5000000;
> +module_param(monitor_period, ulong, 0600);
> +
> +static long monitored_pids[MAX_MONITORED_PIDS];
> +static int num_monitored_pids;
> +module_param_array(monitored_pids, long, &num_monitored_pids, 0600);
> +
> +static struct damos_quota damon_hugepage_quota = {
> + /* use up to 10 ms time, reclaim up to 128 MiB per 1 sec by default */
> + .ms = 10,
> + .sz = 0,
> + .reset_interval = 1000,
> + /* Within the quota, page out older regions first. */
> + .weight_sz = 0,
> + .weight_nr_accesses = 0,
> + .weight_age = 1
You may want to prioritize hot memory region under the quota. If so, you would
need to set weight_nr_acceses to non-zero.
> +};
> +DEFINE_DAMON_MODULES_DAMOS_TIME_QUOTA(damon_hugepage_quota);
> +
> +static struct damos_watermarks damon_hugepage_wmarks = {
> + .metric = DAMOS_WMARK_FREE_MEM_RATE,
> + .interval = 5000000, /* 5 seconds */
> + .high = 900, /* 90 percent */
> + .mid = 800, /* 80 percent */
> + .low = 50, /* 5 percent */
> +};
> +DEFINE_DAMON_MODULES_WMARKS_PARAMS(damon_hugepage_wmarks);
In the RFC v1 discussion, you also mentioned you will remove the above, but
seems it is forgotten?
Also, my understadning of your reply on the previous discussion was that you
don't really want to use watermarks in this module, and therefore you want to
remove it. Am I correct? If I'm not, maybe I'm still not understanding the
intention of the watermarks. Can you please enlighten me?
> +
> +static struct damon_attrs damon_hugepage_mon_attrs = {
> + .sample_interval = 5000, /* 5 ms */
> + .aggr_interval = 100000, /* 100 ms */
> + .ops_update_interval = 0,
Is ops_update_interval = 0 really your intention?
> + .min_nr_regions = 10,
> + .max_nr_regions = 1000,
> +};
> +DEFINE_DAMON_MODULES_MON_ATTRS_PARAMS(damon_hugepage_mon_attrs);
> +
> +struct hugepage_task {
> + struct damon_ctx *ctx;
> + int pid;
> + struct damon_target *target;
> + struct damon_call_control call_control;
> + struct list_head list;
> +};
> +
> +static struct damos *damon_hugepage_new_scheme(int min_access,
> + enum damos_action action)
> +{
> + struct damos_access_pattern pattern = {
> + /* Find regions having PAGE_SIZE or larger size */
s/PAGE_SIZE/PMD_SIZE/ ?
> + .min_sz_region = PMD_SIZE,
> + .max_sz_region = ULONG_MAX,
> + /* and not accessed at all */
Seems the above comment should be updated.
> + .min_nr_accesses = min_access,
> + .max_nr_accesses = 100,
Because you set sampling interval 5ms and aggregatin interval 100ms,
nr_accesses of each DAMON region can be up to only 20 (100ms / 5ms).
max_nr_accesses may better to be 20 to clarifyt that.
> + /* for min_age or more micro-seconds */
> + .min_age_region = 0,
> + .max_age_region = UINT_MAX,
> + };
> +
> + return damon_new_scheme(
> + &pattern,
> + /* synchrounous partial collapse as soon as found */
> + action, 0,
> + /* under the quota. */
> + &damon_hugepage_quota,
> + /* (De)activate this according to the watermarks. */
> + &damon_hugepage_wmarks, NUMA_NO_NODE);
Again, I'm not sure if you really want to use watermarks, and if so, what is
the intention.
> +}
> +
> +static int damon_hugepage_apply_parameters(
> + struct hugepage_task *monitored_task,
> + int min_access,
> + enum damos_action action)
> +{
> + struct damos *scheme;
> + struct damon_ctx *param_ctx;
> + struct damon_target *param_target;
> + struct damos_filter *filter;
> + int err;
> + struct pid *spid;
> +
> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
> + DAMON_OPS_VADDR);
> + if (err)
> + return err;
You should deallocate param_ctx before returning the error.
> +
> + spid = find_get_pid(monitored_task->pid);
> + if (!spid)
> + return err;
Again, please deallocate param_ctx before returning the error.
> +
> + param_target->pid = spid;
> +
> + err = damon_set_attrs(param_ctx, &damon_hugepage_mon_attrs);
> + if (err)
> + goto out;
> +
> + err = -ENOMEM;
> + scheme = damon_hugepage_new_scheme(min_access, action);
> + if (!scheme)
> + goto out;
> +
> + damon_set_schemes(param_ctx, &scheme, 1);
> +
> + filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, false);
> + if (!filter)
> + goto out;
> + damos_add_filter(scheme, filter);
What's the intention of the above filter?
> +
> + err = damon_commit_ctx(monitored_task->ctx, param_ctx);
> +out:
> + damon_destroy_ctx(param_ctx);
> + return err;
> +}
> +
> +static int damon_hugepage_damon_call_fn(void *arg)
> +{
> + struct hugepage_task *monitored_task = arg;
> + struct damon_ctx *ctx = monitored_task->ctx;
> + struct damos *scheme;
> + int err = 0;
> + int min_access;
> + struct damos_stat stat;
> +
> + damon_for_each_scheme(scheme, ctx)
> + stat = scheme->stat;
> + scheme = list_first_entry(&ctx->schemes, struct damos, list);
> +
> + if (ctx->passed_sample_intervals < scheme->next_apply_sis)
> + return err;
> +
> + if (stat.nr_applied)
> + return err;
> +
> + min_access = scheme->pattern.min_nr_accesses;
> +
> + if (min_access > HIGH_ACC_THRESHOLD) {
> + min_access = min_access - 10;
> + err = damon_hugepage_apply_parameters(
> + monitored_task, min_access, DAMOS_COLLAPSE);
> + } else if (min_access > MID_ACC_THRESHOLD) {
> + min_access = min_access - 5;
> + err = damon_hugepage_apply_parameters(
> + monitored_task, min_access, DAMOS_COLLAPSE);
> + } else if (min_access > LOW_ACC_THRESHOLD) {
> + min_access = min_access - 1;
> + err = damon_hugepage_apply_parameters(
> + monitored_task, min_access, DAMOS_COLLAPSE);
> + }
> + return err;
> +}
> +
> +static int damon_hugepage_init_task(struct hugepage_task *monitored_task)
> +{
> + int err = 0;
> + struct damon_ctx *ctx = monitored_task->ctx;
> + struct damon_target *target = monitored_task->target;
> + struct pid *spid;
> +
> + if (!ctx || !target)
> + damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_VADDR);
> +
> + if (damon_is_running(ctx))
> + return 0;
> +
> + spid = find_get_pid(monitored_task->pid);
> + if (!spid)
> + return err;
> +
> + target->pid = spid;
> +
> + monitored_task->call_control.fn = damon_hugepage_damon_call_fn;
> + monitored_task->call_control.repeat = true;
> + monitored_task->call_control.data = monitored_task;
> +
> + struct damos *scheme = damon_hugepage_new_scheme(
> + HIGHEST_MIN_ACCESS, DAMOS_COLLAPSE);
> + if (!scheme)
> + return -ENOMEM;
> +
> + damon_set_schemes(ctx, &scheme, 1);
> +
> + monitored_task->ctx = ctx;
> + err = damon_start(&monitored_task->ctx, 1, false);
> + if (err)
> + return err;
> +
> + return damon_call(monitored_task->ctx, &monitored_task->call_control);
> +}
> +
> +static int add_monitored_task(int pid, struct list_head *task_monitor)
> +{
> + struct hugepage_task *new_hugepage_task;
> + int err;
> +
> + new_hugepage_task = kzalloc_obj(*new_hugepage_task);
> + if (!new_hugepage_task)
> + return -ENOMEM;
> +
> + new_hugepage_task->pid = pid;
> + INIT_LIST_HEAD(&new_hugepage_task->list);
> + err = damon_hugepage_init_task(new_hugepage_task);
> + if (err)
> + return err;
> + list_add(&new_hugepage_task->list, task_monitor);
> + return 0;
> +}
> +
> +static int damon_hugepage_handle_commit_inputs(
> + struct list_head *monitored_tasks)
> +{
> + int i = 0;
> + int err = 0;
> + bool found;
> + struct hugepage_task *monitored_task, *tmp;
> +
> + if (!commit_inputs)
> + return 0;
> +
> + while (i < MAX_MONITORED_PIDS) {
> + if (!monitored_pids[i])
> + break;
> +
> + found = false;
> +
> + rcu_read_lock();
> + if (!find_vpid(monitored_pids[i])) {
> + rcu_read_unlock();
> + continue;
> + }
> +
> + rcu_read_unlock();
> +
> + list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
Please wrap lines for the 80 columns limit.
> + if (monitored_task->pid == monitored_pids[i]) {
> + list_move(&monitored_task->list, monitored_tasks);
> + found = true;
> + break;
> + }
> + }
> + if (!found) {
> + err = add_monitored_task(monitored_pids[i], monitored_tasks);
> + /* Skip failed tasks */
> + if (err)
> + continue;
> + }
> + i++;
> + }
> +
> + i = 0;
> + list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
> + i++;
> + if (i <= num_monitored_pids)
> + continue;
> +
> + err = damon_stop(&monitored_task->ctx, 1);
> + damon_destroy_ctx(monitored_task->ctx);
> + list_del(&monitored_task->list);
> + kfree(monitored_task);
> + }
> +
> + commit_inputs = false;
> + return err;
> +}
> +
> +static int damon_manager_monitor_thread(void *data)
> +{
> + int err = 0;
> + int i;
> + struct hugepage_task *entry, *tmp;
> +
> + LIST_HEAD(monitored_tasks);
> +
> + for (i = 0; i < MAX_MONITORED_PIDS; i++) {
> + if (!monitored_pids[i])
> + break;
> +
> + rcu_read_lock();
> + if (!find_vpid(monitored_pids[i])) {
> + rcu_read_unlock();
> + continue;
> + }
> + rcu_read_unlock();
> +
> + add_monitored_task(monitored_pids[i], &monitored_tasks);
> + }
> +
> +
> + while (!kthread_should_stop()) {
> + schedule_timeout_idle(usecs_to_jiffies(monitor_period));
> + err = damon_hugepage_handle_commit_inputs(&monitored_tasks);
> + if (err)
> + break;
> + }
> +
> + list_for_each_entry_safe(entry, tmp, &monitored_tasks, list) {
> + err = damon_stop(&entry->ctx, 1);
> + damon_destroy_ctx(entry->ctx);
> + }
> +
> + for (int i = 0; i < MAX_MONITORED_PIDS;) {
You can just resue i after initializing here, instead of defining it again.
> + monitored_pids[i] = 0;
> + i++;
> + }
> + return err;
> +}
> +
> +static int damon_hugepage_start_monitor_thread(void)
> +{
> + num_monitored_pids = 0;
> + monitor_thread = kthread_create(damon_manager_monitor_thread, NULL,
> + "damon_dynamic");
> +
> + if (IS_ERR(monitor_thread))
> + return PTR_ERR(monitor_thread);
> +
> + wake_up_process(monitor_thread);
> + return 0;
> +}
> +
> +static int damon_hugepage_turn(bool on)
> +{
> + int err = 0;
> +
> + mutex_lock(&enable_disable_lock);
> + if (!on) {
> + if (monitor_thread) {
> + kthread_stop(monitor_thread);
> + monitor_thread = NULL;
> + }
> + goto out;
> + }
> + err = damon_hugepage_start_monitor_thread();
> +out:
> + mutex_unlock(&enable_disable_lock);
> + return err;
> +}
> +
> +static int damon_hugepage_enabled_store(const char *val,
> + const struct kernel_param *kp)
> +{
> + bool is_enabled = enabled;
> + bool enable;
> + int err;
> +
> + err = kstrtobool(val, &enable);
> + if (err)
> + return err;
> +
> + if (is_enabled == enable)
> + return 0;
> +
> + err = damon_hugepage_turn(enable);
> + if (err)
> + return err;
> +
> + enabled = enable;
> + return err;
> +}
> +
> +static const struct kernel_param_ops enabled_param_ops = {
> + .set = damon_hugepage_enabled_store,
> + .get = param_get_bool,
> +};
> +
> +module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
> +MODULE_PARM_DESC(enabled,
> + "Enable or disable DAMON_DYNAMIC_HUGEPAGES (default: disabled)");
s/DYNAMIC_// ?
> +
> +static int __init damon_hugepage_init(void)
> +{
> + int err;
> +
> + /* 'enabled' has set before this function, probably via command line */
> + if (enabled)
> + err = damon_hugepage_turn(true);
> +
> + if (err && enabled)
> + enabled = false;
> + return err;
> +}
> +
> +module_init(damon_hugepage_init);
> --
> 2.43.0
[1] https://lore.kernel.org/00aa6914-8e52-49a2-9875-588efc096c5e@huawei-partners.com
Thanks,
SJ
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
` (3 preceding siblings ...)
2026-03-10 16:24 ` [RFC PATCH v2 4/4] DAMON_HOT_HUGEPAGE documentation gutierrez.asier
@ 2026-03-11 5:07 ` SeongJae Park
2026-03-11 13:08 ` Gutierrez Asier
4 siblings, 1 reply; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 5:07 UTC (permalink / raw)
To: gutierrez.asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
Hello Asier,
Thank you for continuing this work!
On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>
> Overview
> ----------
Let's make the legnth of the subject and the length of the underline same.
>
> This patch set introduces a new dynamic mechanism for detecting hot applications
> and hot regions in those applications.
Seems now you offload the hot applications detection to the user space. If I'm
not wrong, you should remove "hot applications and" on the above sentence.
>
> Motivation
> -----------
>
> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
> fragmentation and memory waste. For this reason, most application guides and
> system administrators suggest to disable THP.
>
>
> Solution
> -----------
>
> A new Linux kernel module that uses DAMON to detect hot regions and collapse
> those regions into huge pages. The user supplies a set of PIDs using a module
> parameter,
This sounds reasonable to me.
> and then, the module launches a new kdamond thread to monitor each
> of the tasks.
>
> In each kdamond, we start with a high min_access value. Our goal is to find the
> "maximum" min_access value at which point the DAMON action is applied. In each
> cycle, if no action is applied, we lower the min_access.
So, this patch series introduces a sort of auto-tuning of the hugepages
collapse hotness threshold, that implemented in the new module.
We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
quota auto-tuning [1]. Have you considered using that? Of course, it might
not be able to be used as is. Some extensions, e.g., introduction of new goal
metric, may be needed.
Yet another approach would be implementing the auto-tuning in the user-space.
Because DAMON parameters can be updated online, updating the min_access from
the user space should be doable? Given the fact the module anyway require
user-space control for feeding the list of applications to apply access-aware
huge pages collapsing, I find no problem at user space driven auto-tuning.
If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
are feasible, all the controls can be done using DAMON sysfs interface.
Introduction of the new kernel module might not really be needed in the case.
We have DAMON modules in addition to DAMON sysfs interface for users who want
to use DAMON for a given specific use case with only minimum or near-zero
user-space control. In this case, because it is already aimed to ask the
user-space to feed the list of applications to apply DAMOS-based hugepages
collapsing, it seems a new module is not really needed, to me.
But I guess your use case might have some special restrictions that really
require use of the module instead of offloading the auto-tuning to the
user-space or DAMON core. Is that the case? If so, can you share more details
about it?
>
> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
> collapse synchronously and avoid polluting khugepaged and other parts of the MM
> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
> which needs the correct vm_flags_t set.
This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
From my perspective, this patch series is introducing three things.
1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
changes are really needed. I will wait your answer.
Meanwhile, the third change seems reasonable and not necessarily need to be
blocked for the other two changes. I think separating the third change from
this patch series and upstreaming it first could also be a path forward.
Because the change is simple and sound, convincing me would be easy. I'd be
convinced if at least some reasonable test results can be shown. I'm not
saying we should drop the other two changes. We can keep discussing those in
parallel. Rather, upstreaming the third change first could help finding real
benefits of the other two changes, since the testing will be easier. The
decision is up to Asier, of course. I'm just sharing my two cents.
>
>
> -----------
> Changes in v2:
Let's keep calling this "RFC" here. When you drop the "RFC" tag, this might
confuse some people.
Also, when you add a changelog of a patch, adding a link to the previous
version [2] can help reviewing.
> - Previously there was a mechanism to automatically detect hot applications.
> Based on SeongJae Park's feedback [1], this was removed from the module, leaving
> it entirely to the user space.
> - All allocations now use kzalloc_obj.
> - Since the user space provides now the list of pids to monitor, a commit_input
> parameter is added to allow changing the pids while the module runs.
> - Renamed the module from dynamic_hugepages to hugepages
Thank you for doing this, Asier.
>
> [1]: https://lore.kernel.org/all/20260211150902.70066-1-sj@kernel.org/
>
> Asier Gutierrez (4):
> Damon_modules_new_paddr_ctx_target. This works only for physical
> contexts. In case of virtual addresses, we should duplicate the
> code.
> Support for huge pages collapse, which will be used by
> dynamic_hugepages module.
> This new module launches a new kdamond thread for each of them. The
> purpose is to detect hot regions in a given list of tasks and
> collapse them into huge pages.
> DAMON_HOT_HUGEPAGE documentation
>
> .../admin-guide/mm/damon/hugepage.rst (new) | 186 ++++++++
> include/linux/damon.h | 1 +
> mm/damon/Kconfig | 7 +
> mm/damon/Makefile | 1 +
> mm/damon/hugepage.c (new) | 441 ++++++++++++++++++
> mm/damon/lru_sort.c | 5 +-
> mm/damon/modules-common.c | 6 +-
> mm/damon/modules-common.h | 4 +-
> mm/damon/reclaim.c | 5 +-
> mm/damon/vaddr.c | 3 +
> 10 files changed, 650 insertions(+), 9 deletions(-)
> create mode 100644 Documentation/admin-guide/mm/damon/hugepage.rst
> create mode 100644 mm/damon/hugepage.c
>
> --
> 2.43.0
[1] https://origin.kernel.org/doc/html/latest/mm/damon/design.html#aim-oriented-feedback-driven-auto-tuning
[2] https://docs.kernel.org/process/submitting-patches.html#commentary
Thanks,
SJ
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-11 5:07 ` [RFC PATCH v2 0/4] mm/damon: Support hot application detections SeongJae Park
@ 2026-03-11 13:08 ` Gutierrez Asier
2026-03-11 14:39 ` SeongJae Park
0 siblings, 1 reply; 20+ messages in thread
From: Gutierrez Asier @ 2026-03-11 13:08 UTC (permalink / raw)
To: SeongJae Park
Cc: artem.kuzin, stepanov.anatoly, wangkefeng.wang, yanquanmin1,
zuoze1, damon, akpm, linux-mm, linux-kernel
Hi SeongJae,
On 3/11/2026 8:07 AM, SeongJae Park wrote:
> Hello Asier,
>
>
> Thank you for continuing this work!
>
> On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
>
>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>>
>> Overview
>> ----------
>
> Let's make the legnth of the subject and the length of the underline same.
>
>>
>> This patch set introduces a new dynamic mechanism for detecting hot applications
>> and hot regions in those applications.
>
> Seems now you offload the hot applications detection to the user space. If I'm
> not wrong, you should remove "hot applications and" on the above sentence.
You're right. I was not sure whether changing the RFC subject was right or not.
I will change it for the next RFC version.
>>
>> Motivation
>> -----------
>>
>> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
>> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
>> fragmentation and memory waste. For this reason, most application guides and
>> system administrators suggest to disable THP.
>>
>>
>> Solution
>> -----------
>>
>> A new Linux kernel module that uses DAMON to detect hot regions and collapse
>> those regions into huge pages. The user supplies a set of PIDs using a module
>> parameter,
>
> This sounds reasonable to me.
>
>> and then, the module launches a new kdamond thread to monitor each
>> of the tasks.
>>
>> In each kdamond, we start with a high min_access value. Our goal is to find the
>> "maximum" min_access value at which point the DAMON action is applied. In each
>> cycle, if no action is applied, we lower the min_access.
>
> So, this patch series introduces a sort of auto-tuning of the hugepages
> collapse hotness threshold, that implemented in the new module.
>
> We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
> quota auto-tuning [1]. Have you considered using that? Of course, it might
> not be able to be used as is. Some extensions, e.g., introduction of new goal
> metric, may be needed.
>
> Yet another approach would be implementing the auto-tuning in the user-space.
> Because DAMON parameters can be updated online, updating the min_access from
> the user space should be doable? Given the fact the module anyway require
> user-space control for feeding the list of applications to apply access-aware
> huge pages collapsing, I find no problem at user space driven auto-tuning.
>
> If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
> are feasible, all the controls can be done using DAMON sysfs interface.
> Introduction of the new kernel module might not really be needed in the case.
>
> We have DAMON modules in addition to DAMON sysfs interface for users who want
> to use DAMON for a given specific use case with only minimum or near-zero
> user-space control. In this case, because it is already aimed to ask the
> user-space to feed the list of applications to apply DAMOS-based hugepages
> collapsing, it seems a new module is not really needed, to me.
>
> But I guess your use case might have some special restrictions that really
> require use of the module instead of offloading the auto-tuning to the
> user-space or DAMON core. Is that the case? If so, can you share more details
> about it?
I haven't figured out how I can use goal autotune to change the min_access.
Your suggestion about moving this to the user space sound good.
The idea was to stop lowering the min_access as soon as collapses occur,
since we don't want to lower so much that we start collapsing regions that
are not very hot.
Maybe you can suggest a better way to do it. Maybe with autotuning.
>
>>
>> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
>> collapse synchronously and avoid polluting khugepaged and other parts of the MM
>> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
>> which needs the correct vm_flags_t set.
>
> This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
> DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
>
> From my perspective, this patch series is introducing three things.
> 1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
> the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
> changes are really needed. I will wait your answer.
>
> Meanwhile, the third change seems reasonable and not necessarily need to be
> blocked for the other two changes. I think separating the third change from
> this patch series and upstreaming it first could also be a path forward.
> Because the change is simple and sound, convincing me would be easy. I'd be
> convinced if at least some reasonable test results can be shown. I'm not
> saying we should drop the other two changes. We can keep discussing those in
> parallel. Rather, upstreaming the third change first could help finding real
> benefits of the other two changes, since the testing will be easier. The
> decision is up to Asier, of course. I'm just sharing my two cents.
>
>>
>>
>> -----------
>> Changes in v2:
>
> Let's keep calling this "RFC" here. When you drop the "RFC" tag, this might
> confuse some people.
>
> Also, when you add a changelog of a patch, adding a link to the previous
> version [2] can help reviewing.
Will do it.
>
>> - Previously there was a mechanism to automatically detect hot applications.
>> Based on SeongJae Park's feedback [1], this was removed from the module, leaving
>> it entirely to the user space.
>> - All allocations now use kzalloc_obj.
>> - Since the user space provides now the list of pids to monitor, a commit_input
>> parameter is added to allow changing the pids while the module runs.
>> - Renamed the module from dynamic_hugepages to hugepages
>
> Thank you for doing this, Asier.
>
>>
>> [1]: https://lore.kernel.org/all/20260211150902.70066-1-sj@kernel.org/
>>
>> Asier Gutierrez (4):
>> Damon_modules_new_paddr_ctx_target. This works only for physical
>> contexts. In case of virtual addresses, we should duplicate the
>> code.
>> Support for huge pages collapse, which will be used by
>> dynamic_hugepages module.
>> This new module launches a new kdamond thread for each of them. The
>> purpose is to detect hot regions in a given list of tasks and
>> collapse them into huge pages.
>> DAMON_HOT_HUGEPAGE documentation
>>
>> .../admin-guide/mm/damon/hugepage.rst (new) | 186 ++++++++
>> include/linux/damon.h | 1 +
>> mm/damon/Kconfig | 7 +
>> mm/damon/Makefile | 1 +
>> mm/damon/hugepage.c (new) | 441 ++++++++++++++++++
>> mm/damon/lru_sort.c | 5 +-
>> mm/damon/modules-common.c | 6 +-
>> mm/damon/modules-common.h | 4 +-
>> mm/damon/reclaim.c | 5 +-
>> mm/damon/vaddr.c | 3 +
>> 10 files changed, 650 insertions(+), 9 deletions(-)
>> create mode 100644 Documentation/admin-guide/mm/damon/hugepage.rst
>> create mode 100644 mm/damon/hugepage.c
>>
>> --
>> 2.43.0
>
> [1] https://origin.kernel.org/doc/html/latest/mm/damon/design.html#aim-oriented-feedback-driven-auto-tuning
> [2] https://docs.kernel.org/process/submitting-patches.html#commentary
>
>
> Thanks,
> SJ
>
--
Asier Gutierrez
Huawei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules
2026-03-11 0:57 ` SeongJae Park
@ 2026-03-11 13:10 ` Gutierrez Asier
2026-03-11 14:15 ` SeongJae Park
0 siblings, 1 reply; 20+ messages in thread
From: Gutierrez Asier @ 2026-03-11 13:10 UTC (permalink / raw)
To: SeongJae Park
Cc: artem.kuzin, stepanov.anatoly, wangkefeng.wang, yanquanmin1,
zuoze1, damon, akpm, linux-mm, linux-kernel
On 3/11/2026 3:57 AM, SeongJae Park wrote:
> On Tue, 10 Mar 2026 16:24:17 +0000 <gutierrez.asier@huawei-partners.com> wrote:
>
>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>>
>> It is more elegant to have a generic version of new context creation
>> which receives the mode as a parameter.
>>
>> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
>> ---
>> mm/damon/lru_sort.c | 5 +++--
>> mm/damon/modules-common.c | 6 +++---
>> mm/damon/modules-common.h | 4 ++--
>> mm/damon/reclaim.c | 5 +++--
>> 4 files changed, 11 insertions(+), 9 deletions(-)
>>
>> diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
>> index 7bc5c0b2aea3..143ee0b21da6 100644
>> --- a/mm/damon/lru_sort.c
>> +++ b/mm/damon/lru_sort.c
>> @@ -287,7 +287,8 @@ static int damon_lru_sort_apply_parameters(void)
>> unsigned int hot_thres, cold_thres;
>> int err;
>>
>> - err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
>> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
>> + DAMON_OPS_PADDR);
>
> I like the name of the function is becoming shorter. But I'm not happy with
> the fact the resulting calling code becomes longer.
>
> I understand you are doing this extension because you want a version of the
> function for vaddr. What about introducing another dedicated function, say,
> damon_modules_new_vaddr_ctx_target() ?
>
> And you can avoid duplicates between damon_modules_new_{p,v}addr_ctx_target()
> by implementing internal function, say, damon_modules_new_ctx_target() that
> receives the damon_ops_id. And damon_modules_new_{P,v}addr_ctx_target() will
> just wrappers of damon_modules_new_ctx_target().
Sure, I will do it.
Since this is some generic code not related to the module I am working on,
maybe I can move this to a different patch set that we can upstream. What do
you think?
>
>> if (err)
>> return err;
>>
>> @@ -479,7 +480,7 @@ static int __init damon_lru_sort_init(void)
>> err = -ENOMEM;
>> goto out;
>> }
>> - err = damon_modules_new_paddr_ctx_target(&ctx, &target);
>> + err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
>
> Ditto.
>
>> if (err)
>> goto out;
>>
>> diff --git a/mm/damon/modules-common.c b/mm/damon/modules-common.c
>> index 86d58f8c4f63..ae50b2fa3a86 100644
>> --- a/mm/damon/modules-common.c
>> +++ b/mm/damon/modules-common.c
>> @@ -14,8 +14,8 @@
>> * @ctxp: Pointer to save the point to the newly created context
>> * @targetp: Pointer to save the point to the newly created target
>> */
>> -int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
>> - struct damon_target **targetp)
>> +int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
>> + struct damon_target **targetp, enum damon_ops_id mode)
>
> Nit. I'd suggest 'ops_id' as the parameter name, instead of 'mode'.
>
>> {
>> struct damon_ctx *ctx;
>> struct damon_target *target;
>> @@ -24,7 +24,7 @@ int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
>> if (!ctx)
>> return -ENOMEM;
>>
>> - if (damon_select_ops(ctx, DAMON_OPS_PADDR)) {
>> + if (damon_select_ops(ctx, mode)) {
>> damon_destroy_ctx(ctx);
>> return -EINVAL;
>> }
>> diff --git a/mm/damon/modules-common.h b/mm/damon/modules-common.h
>> index f103ad556368..379b49c6a617 100644
>> --- a/mm/damon/modules-common.h
>> +++ b/mm/damon/modules-common.h
>> @@ -45,5 +45,5 @@
>> module_param_named(nr_##qt_exceed_name, stat.qt_exceeds, ulong, \
>> 0400);
>>
>> -int damon_modules_new_paddr_ctx_target(struct damon_ctx **ctxp,
>> - struct damon_target **targetp);
>> +int damon_modules_new_ctx_target(struct damon_ctx **ctxp,
>> + struct damon_target **targetp, enum damon_ops_id mode);
>> diff --git a/mm/damon/reclaim.c b/mm/damon/reclaim.c
>> index 43d76f5bed44..24786a58683a 100644
>> --- a/mm/damon/reclaim.c
>> +++ b/mm/damon/reclaim.c
>> @@ -197,7 +197,8 @@ static int damon_reclaim_apply_parameters(void)
>> struct damos_filter *filter;
>> int err;
>>
>> - err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
>> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
>> + DAMON_OPS_PADDR);
>> if (err)
>> return err;
>>
>> @@ -381,7 +382,7 @@ static int __init damon_reclaim_init(void)
>> err = -ENOMEM;
>> goto out;
>> }
>> - err = damon_modules_new_paddr_ctx_target(&ctx, &target);
>> + err = damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_PADDR);
>> if (err)
>> goto out;
>>
>> --
>> 2.43.0
>
>
> Thanks,
> SJ
>
--
Asier Gutierrez
Huawei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse
2026-03-11 1:02 ` SeongJae Park
@ 2026-03-11 13:11 ` Gutierrez Asier
2026-03-11 14:17 ` SeongJae Park
0 siblings, 1 reply; 20+ messages in thread
From: Gutierrez Asier @ 2026-03-11 13:11 UTC (permalink / raw)
To: SeongJae Park
Cc: artem.kuzin, stepanov.anatoly, wangkefeng.wang, yanquanmin1,
zuoze1, damon, akpm, linux-mm, linux-kernel
On 3/11/2026 4:02 AM, SeongJae Park wrote:
> On Tue, 10 Mar 2026 16:24:18 +0000 <gutierrez.asier@huawei-partners.com> wrote:
>
>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>
> Please add more descriptions of the change, including the motivation.
>
> I assume the motivation is similar to MADV_COLLAPSE that aims to make
> synchronous and therefore faster huge page collapsing impacts copared to
> MADV_HUGEPAGE? It would be nice to make it clear here. Also, if my assumption
> is not wrong, adding a test results showing the benefit of DAMOS_COLLAPSE over
> DAMOS_HUGEPAGE here would be nice.
You are right. I will make it more clear in the cover letter for the next
version.
>
>>
>> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
>> ---
>> include/linux/damon.h | 1 +
>> mm/damon/vaddr.c | 3 +++
>> 2 files changed, 4 insertions(+)
>>
>> diff --git a/include/linux/damon.h b/include/linux/damon.h
>> index a4fea23da857..a9cf17b9e8fa 100644
>> --- a/include/linux/damon.h
>> +++ b/include/linux/damon.h
>> @@ -142,6 +142,7 @@ enum damos_action {
>> DAMOS_LRU_DEPRIO,
>> DAMOS_MIGRATE_HOT,
>> DAMOS_MIGRATE_COLD,
>> + DAMOS_COLLAPSE,
>> DAMOS_STAT, /* Do nothing but only record the stat */
>> NR_DAMOS_ACTIONS,
>> };
>> diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
>> index 729b7ffd3565..36791a9a1094 100644
>> --- a/mm/damon/vaddr.c
>> +++ b/mm/damon/vaddr.c
>> @@ -969,6 +969,9 @@ static unsigned long damon_va_apply_scheme(struct damon_ctx *ctx,
>> case DAMOS_NOHUGEPAGE:
>> madv_action = MADV_NOHUGEPAGE;
>> break;
>> + case DAMOS_COLLAPSE:
>> + madv_action = MADV_COLLAPSE;
>> + break;
>> case DAMOS_MIGRATE_HOT:
>> case DAMOS_MIGRATE_COLD:
>> return damos_va_migrate(t, r, scheme, sz_filter_passed);
>> --
>> 2.43.0
>
> The code looks good to me.
>
>
> Thanks,
> SJ
>
> [...]
>
--
Asier Gutierrez
Huawei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 3/4] mm/damon: New module with hot application detection
2026-03-11 4:11 ` SeongJae Park
@ 2026-03-11 13:45 ` Gutierrez Asier
2026-03-11 14:32 ` SeongJae Park
0 siblings, 1 reply; 20+ messages in thread
From: Gutierrez Asier @ 2026-03-11 13:45 UTC (permalink / raw)
To: SeongJae Park
Cc: artem.kuzin, stepanov.anatoly, wangkefeng.wang, yanquanmin1,
zuoze1, damon, akpm, linux-mm, linux-kernel
On 3/11/2026 7:11 AM, SeongJae Park wrote:
> On Tue, 10 Mar 2026 16:24:19 +0000 <gutierrez.asier@huawei-partners.com> wrote:
>
>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>
> I'd like to discuss about this in a high level, but I'd like to do that on the
> cover letter. To this patch, I'm therefore adding comments for only details
> that stand out immeadiately to me.
I will update the cover letter to add more details for the next version.
>>
>> 1. It first launches a new kthread called damon_dynamic. This thread
>> will behave as a supervisor, launching new kdamond threads for all
>> the processes we want to montiored. The tasks are sorted
>> by utime delta. For the top N tasks, a new kdamond thread will be
>> launched.
>
> If I read the cover letter and the code of this patch correctly, seems the last
> two sentences of the above paragraph is outdated. Please correct me if I'm
> wrong.
Correct, I forgot to delete it.
>
>> Applications which turn cold will have their kdamond
>> stopped.
>>
>> The processes are supplied by the monitored_pids parameter. When the
>> module is enabled, it will go through all the monitored_pids, start
>> the supervisor and a new kdamond thread for each of the tasks. This
>> tasks can be modified and applied using the commit_input parameters.
>> In that case, we will stop any kdamond thread for tasks that are not
>> going to be monitored anymore, and start a new kdamond thread for each
>> new task to be monitored. For tasks that were monitored before and are
>> still monitored after commiting a new monitored_pids list, kdamond
>> threads are left intact.
>>
>> 2. Initially we don't know the min_access for each of the task. We
>> want to find the highest min_access when collapses start happening.
>> For that we have an initial threashold of 90, which we will lower
>> until a collpase occurs.
>>
>> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
>> ---
>> mm/damon/Kconfig | 7 +
>> mm/damon/Makefile | 1 +
>> mm/damon/hugepage.c (new) | 441 ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 449 insertions(+)
>>
>> diff --git a/mm/damon/Kconfig b/mm/damon/Kconfig
>> index 8c868f7035fc..2355aacb6d12 100644
>> --- a/mm/damon/Kconfig
>> +++ b/mm/damon/Kconfig
>> @@ -110,4 +110,11 @@ config DAMON_STAT_ENABLED_DEFAULT
>> Whether to enable DAMON_STAT by default. Users can disable it in
>> boot or runtime using its 'enabled' parameter.
>>
>> +config DAMON_HOT_HUGEPAGE
>
> I'd suggest renaming to DAMON_HUGEPAGE.
OK
>
>> + bool "Build DAMON-based collapse of hot regions (DAMON_HOT_HUGEPAGES)"
>> + depends on DAMON_VADDR
>> + help
>> + Collapse hot region into huge pages. Hot regions are determined by
>> + DAMON-based sampling
>> +
>> endmenu
>> diff --git a/mm/damon/Makefile b/mm/damon/Makefile
>> index d8d6bf5f8bff..ac3afbc81cc7 100644
>> --- a/mm/damon/Makefile
>> +++ b/mm/damon/Makefile
>> @@ -7,3 +7,4 @@ obj-$(CONFIG_DAMON_SYSFS) += sysfs-common.o sysfs-schemes.o sysfs.o
>> obj-$(CONFIG_DAMON_RECLAIM) += modules-common.o reclaim.o
>> obj-$(CONFIG_DAMON_LRU_SORT) += modules-common.o lru_sort.o
>> obj-$(CONFIG_DAMON_STAT) += modules-common.o stat.o
>> +obj-$(CONFIG_DAMON_HOT_HUGEPAGE) += modules-common.o hugepage.o
>> diff --git a/mm/damon/hugepage.c b/mm/damon/hugepage.c
>> new file mode 100644
>> index 000000000000..ccd31c48d391
>> --- /dev/null
>> +++ b/mm/damon/hugepage.c
>> @@ -0,0 +1,441 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (C) 2026 HUAWEI, Inc.
>> + * https://www.huawei.com
>> + *
>> + * Author: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>> + */
>> +
>> +#define pr_fmt(fmt) "damon-hugepage: " fmt
>> +
>> +#include <linux/damon.h>
>> +#include <linux/kstrtox.h>
>> +#include <linux/module.h>
>> +
>> +#include "modules-common.h"
>> +
>> +#ifdef MODULE_PARAM_PREFIX
>> +#undef MODULE_PARAM_PREFIX
>> +#endif
>> +#define MODULE_PARAM_PREFIX "damon_hugepage."
>> +
>> +#define MAX_MONITORED_PIDS 100
>> +#define HIGHEST_MIN_ACCESS 90
>> +#define HIGH_ACC_THRESHOLD 50
>> +#define MID_ACC_THRESHOLD 15
>> +#define LOW_ACC_THRESHOLD 2
>
> On your setup where the sampling interval is 5ms and the aggregation interval
> is 100ms, nr_accesses of each DAMON region can be up to only 20. So above
> thresholds may better to be lowered.
>
>> +
>> +static struct task_struct *monitor_thread;
>> +
>> +struct mutex enable_disable_lock;
>> +
>> +/*
>> + * Enable or disable DAMON_HUGEPAGE.
>> + *
>> + * You can enable DAMON_HUGEPAGE by setting the value of this parameter
>> + * as ``Y``. Setting it as ``N`` disables DAMON_HOT_HUGEPAGE. Note that
>> + * DAMON_HOT_HUGEPAGE could do no real monitoring and reclamation due to the
>
> s/DAMON_HOT_HUGEPAGE/DAMON_HUGEPAGE/ ?
I will change it.
>
>> + * watermarks-based activation condition. Refer to below descriptions for the
>> + * watermarks parameter for this.
>
> On RFC v1 discussion [1], you mentioned you will update this comment. But I
> find no change?
I will add links to future discuessions.
>
>> + */
>> +static bool enabled __read_mostly;
>> +
>> +/*
>> + * Make DAMON_HUGEPAGE reads the input parameters again, except ``enabled``.
>> + *
>> + * Input parameters that updated while DAMON_HUGEPAGE is running are not applied
>> + * by default. Once this parameter is set as ``Y``, DAMON_HUGEPAGE reads values
>> + * of parametrs except ``enabled`` again. Once the re-reading is done, this
>> + * parameter is set as ``N``. If invalid parameters are found while the
>> + * re-reading, DAMON_HUGEPAGE will be disabled.
>> + */
>> +static bool commit_inputs __read_mostly;
>> +module_param(commit_inputs, bool, 0600);
>> +
>> +/*
>> + * DAMON_HUGEPAGE monitoring period in microseconds.
>> + * 5000000 = 5s
>> + */
>> +static unsigned long monitor_period __read_mostly = 5000000;
>> +module_param(monitor_period, ulong, 0600);
>> +
>> +static long monitored_pids[MAX_MONITORED_PIDS];
>> +static int num_monitored_pids;
>> +module_param_array(monitored_pids, long, &num_monitored_pids, 0600);
>> +
>> +static struct damos_quota damon_hugepage_quota = {
>> + /* use up to 10 ms time, reclaim up to 128 MiB per 1 sec by default */
>> + .ms = 10,
>> + .sz = 0,
>> + .reset_interval = 1000,
>> + /* Within the quota, page out older regions first. */
>> + .weight_sz = 0,
>> + .weight_nr_accesses = 0,
>> + .weight_age = 1
>
> You may want to prioritize hot memory region under the quota. If so, you would
> need to set weight_nr_acceses to non-zero.
>
>> +};
>> +DEFINE_DAMON_MODULES_DAMOS_TIME_QUOTA(damon_hugepage_quota);
>> +
>> +static struct damos_watermarks damon_hugepage_wmarks = {
>> + .metric = DAMOS_WMARK_FREE_MEM_RATE,
>> + .interval = 5000000, /* 5 seconds */
>> + .high = 900, /* 90 percent */
>> + .mid = 800, /* 80 percent */
>> + .low = 50, /* 5 percent */
>> +};
>> +DEFINE_DAMON_MODULES_WMARKS_PARAMS(damon_hugepage_wmarks);
>
> In the RFC v1 discussion, you also mentioned you will remove the above, but
> seems it is forgotten?
>
> Also, my understadning of your reply on the previous discussion was that you
> don't really want to use watermarks in this module, and therefore you want to
> remove it. Am I correct? If I'm not, maybe I'm still not understanding the
> intention of the watermarks. Can you please enlighten me?
Since I refactored heavily the previous code, I forgot to delete this bit.
I will remove it now.
>> +
>> +static struct damon_attrs damon_hugepage_mon_attrs = {
>> + .sample_interval = 5000, /* 5 ms */
>> + .aggr_interval = 100000, /* 100 ms */
>> + .ops_update_interval = 0,
>
> Is ops_update_interval = 0 really your intention?
I didn't think about it. I will set it to 60 seconds, as in other modules.
>
>> + .min_nr_regions = 10,
>> + .max_nr_regions = 1000,
>> +};
>> +DEFINE_DAMON_MODULES_MON_ATTRS_PARAMS(damon_hugepage_mon_attrs);
>> +
>> +struct hugepage_task {
>> + struct damon_ctx *ctx;
>> + int pid;
>> + struct damon_target *target;
>> + struct damon_call_control call_control;
>> + struct list_head list;
>> +};
>> +
>> +static struct damos *damon_hugepage_new_scheme(int min_access,
>> + enum damos_action action)
>> +{
>> + struct damos_access_pattern pattern = {
>> + /* Find regions having PAGE_SIZE or larger size */
>
> s/PAGE_SIZE/PMD_SIZE/ ?
>
>> + .min_sz_region = PMD_SIZE,
>> + .max_sz_region = ULONG_MAX,
>> + /* and not accessed at all */
>
> Seems the above comment should be updated.
>
>> + .min_nr_accesses = min_access,
>> + .max_nr_accesses = 100,
>
> Because you set sampling interval 5ms and aggregatin interval 100ms,
> nr_accesses of each DAMON region can be up to only 20 (100ms / 5ms).
> max_nr_accesses may better to be 20 to clarifyt that.
>
>> + /* for min_age or more micro-seconds */
>> + .min_age_region = 0,
>> + .max_age_region = UINT_MAX,
>> + };
>> +
>> + return damon_new_scheme(
>> + &pattern,
>> + /* synchrounous partial collapse as soon as found */
>> + action, 0,
>> + /* under the quota. */
>> + &damon_hugepage_quota,
>> + /* (De)activate this according to the watermarks. */
>> + &damon_hugepage_wmarks, NUMA_NO_NODE);
>
> Again, I'm not sure if you really want to use watermarks, and if so, what is
> the intention.
Right, I will remove this code.
>> +}
>> +
>> +static int damon_hugepage_apply_parameters(
>> + struct hugepage_task *monitored_task,
>> + int min_access,
>> + enum damos_action action)
>> +{
>> + struct damos *scheme;
>> + struct damon_ctx *param_ctx;
>> + struct damon_target *param_target;
>> + struct damos_filter *filter;
>> + int err;
>> + struct pid *spid;
>> +
>> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
>> + DAMON_OPS_VADDR);
>> + if (err)
>> + return err;
>
> You should deallocate param_ctx before returning the error.
Not sure about this. As far as I know, damon_modules_new_paddr_ctx_target
will destroy the context in case there is an error. In fact, reclaim and
lru_sort modules just return error when damon_modules_new_paddr_ctx_target
fails, no cleanup used.
>
>> +
>> + spid = find_get_pid(monitored_task->pid);
>> + if (!spid)
>> + return err;
>
> Again, please deallocate param_ctx before returning the error.
OK
>
>> +
>> + param_target->pid = spid;
>> +
>> + err = damon_set_attrs(param_ctx, &damon_hugepage_mon_attrs);
>> + if (err)
>> + goto out;
>> +
>> + err = -ENOMEM;
>> + scheme = damon_hugepage_new_scheme(min_access, action);
>> + if (!scheme)
>> + goto out;
>> +
>> + damon_set_schemes(param_ctx, &scheme, 1);
>> +
>> + filter = damos_new_filter(DAMOS_FILTER_TYPE_ANON, true, false);
>> + if (!filter)
>> + goto out;
>> + damos_add_filter(scheme, filter);
>
> What's the intention of the above filter?
Also, I will remove it.
>> +
>> + err = damon_commit_ctx(monitored_task->ctx, param_ctx);
>> +out:
>> + damon_destroy_ctx(param_ctx);
>> + return err;
>> +}
>> +
>> +static int damon_hugepage_damon_call_fn(void *arg)
>> +{
>> + struct hugepage_task *monitored_task = arg;
>> + struct damon_ctx *ctx = monitored_task->ctx;
>> + struct damos *scheme;
>> + int err = 0;
>> + int min_access;
>> + struct damos_stat stat;
>> +
>> + damon_for_each_scheme(scheme, ctx)
>> + stat = scheme->stat;
>> + scheme = list_first_entry(&ctx->schemes, struct damos, list);
>> +
>> + if (ctx->passed_sample_intervals < scheme->next_apply_sis)
>> + return err;
>> +
>> + if (stat.nr_applied)
>> + return err;
>> +
>> + min_access = scheme->pattern.min_nr_accesses;
>> +
>> + if (min_access > HIGH_ACC_THRESHOLD) {
>> + min_access = min_access - 10;
>> + err = damon_hugepage_apply_parameters(
>> + monitored_task, min_access, DAMOS_COLLAPSE);
>> + } else if (min_access > MID_ACC_THRESHOLD) {
>> + min_access = min_access - 5;
>> + err = damon_hugepage_apply_parameters(
>> + monitored_task, min_access, DAMOS_COLLAPSE);
>> + } else if (min_access > LOW_ACC_THRESHOLD) {
>> + min_access = min_access - 1;
>> + err = damon_hugepage_apply_parameters(
>> + monitored_task, min_access, DAMOS_COLLAPSE);
>> + }
>> + return err;
>> +}
>> +
>> +static int damon_hugepage_init_task(struct hugepage_task *monitored_task)
>> +{
>> + int err = 0;
>> + struct damon_ctx *ctx = monitored_task->ctx;
>> + struct damon_target *target = monitored_task->target;
>> + struct pid *spid;
>> +
>> + if (!ctx || !target)
>> + damon_modules_new_ctx_target(&ctx, &target, DAMON_OPS_VADDR);
>> +
>> + if (damon_is_running(ctx))
>> + return 0;
>> +
>> + spid = find_get_pid(monitored_task->pid);
>> + if (!spid)
>> + return err;
>> +
>> + target->pid = spid;
>> +
>> + monitored_task->call_control.fn = damon_hugepage_damon_call_fn;
>> + monitored_task->call_control.repeat = true;
>> + monitored_task->call_control.data = monitored_task;
>> +
>> + struct damos *scheme = damon_hugepage_new_scheme(
>> + HIGHEST_MIN_ACCESS, DAMOS_COLLAPSE);
>> + if (!scheme)
>> + return -ENOMEM;
>> +
>> + damon_set_schemes(ctx, &scheme, 1);
>> +
>> + monitored_task->ctx = ctx;
>> + err = damon_start(&monitored_task->ctx, 1, false);
>> + if (err)
>> + return err;
>> +
>> + return damon_call(monitored_task->ctx, &monitored_task->call_control);
>> +}
>> +
>> +static int add_monitored_task(int pid, struct list_head *task_monitor)
>> +{
>> + struct hugepage_task *new_hugepage_task;
>> + int err;
>> +
>> + new_hugepage_task = kzalloc_obj(*new_hugepage_task);
>> + if (!new_hugepage_task)
>> + return -ENOMEM;
>> +
>> + new_hugepage_task->pid = pid;
>> + INIT_LIST_HEAD(&new_hugepage_task->list);
>> + err = damon_hugepage_init_task(new_hugepage_task);
>> + if (err)
>> + return err;
>> + list_add(&new_hugepage_task->list, task_monitor);
>> + return 0;
>> +}
>> +
>> +static int damon_hugepage_handle_commit_inputs(
>> + struct list_head *monitored_tasks)
>> +{
>> + int i = 0;
>> + int err = 0;
>> + bool found;
>> + struct hugepage_task *monitored_task, *tmp;
>> +
>> + if (!commit_inputs)
>> + return 0;
>> +
>> + while (i < MAX_MONITORED_PIDS) {
>> + if (!monitored_pids[i])
>> + break;
>> +
>> + found = false;
>> +
>> + rcu_read_lock();
>> + if (!find_vpid(monitored_pids[i])) {
>> + rcu_read_unlock();
>> + continue;
>> + }
>> +
>> + rcu_read_unlock();
>> +
>> + list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
>
> Please wrap lines for the 80 columns limit.
Interesting, when check it, i was less than 80 columns. Even if I copy this line
and paste it into any text editor, I still get less than 80 characters.
>
>> + if (monitored_task->pid == monitored_pids[i]) {
>> + list_move(&monitored_task->list, monitored_tasks);
>> + found = true;
>> + break;
>> + }
>> + }
>> + if (!found) {
>> + err = add_monitored_task(monitored_pids[i], monitored_tasks);
>> + /* Skip failed tasks */
>> + if (err)
>> + continue;
>> + }
>> + i++;
>> + }
>> +
>> + i = 0;
>> + list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
>> + i++;
>> + if (i <= num_monitored_pids)
>> + continue;
>> +
>> + err = damon_stop(&monitored_task->ctx, 1);
>> + damon_destroy_ctx(monitored_task->ctx);
>> + list_del(&monitored_task->list);
>> + kfree(monitored_task);
>> + }
>> +
>> + commit_inputs = false;
>> + return err;
>> +}
>> +
>> +static int damon_manager_monitor_thread(void *data)
>> +{
>> + int err = 0;
>> + int i;
>> + struct hugepage_task *entry, *tmp;
>> +
>> + LIST_HEAD(monitored_tasks);
>> +
>> + for (i = 0; i < MAX_MONITORED_PIDS; i++) {
>> + if (!monitored_pids[i])
>> + break;
>> +
>> + rcu_read_lock();
>> + if (!find_vpid(monitored_pids[i])) {
>> + rcu_read_unlock();
>> + continue;
>> + }
>> + rcu_read_unlock();
>> +
>> + add_monitored_task(monitored_pids[i], &monitored_tasks);
>> + }
>> +
>> +
>> + while (!kthread_should_stop()) {
>> + schedule_timeout_idle(usecs_to_jiffies(monitor_period));
>> + err = damon_hugepage_handle_commit_inputs(&monitored_tasks);
>> + if (err)
>> + break;
>> + }
>> +
>> + list_for_each_entry_safe(entry, tmp, &monitored_tasks, list) {
>> + err = damon_stop(&entry->ctx, 1);
>> + damon_destroy_ctx(entry->ctx);
>> + }
>> +
>> + for (int i = 0; i < MAX_MONITORED_PIDS;) {
>
> You can just resue i after initializing here, instead of defining it again.
Again, left overs from the previous refactor. My bad.
>
>> + monitored_pids[i] = 0;
>> + i++;
>> + }
>> + return err;
>> +}
>> +
>> +static int damon_hugepage_start_monitor_thread(void)
>> +{
>> + num_monitored_pids = 0;
>> + monitor_thread = kthread_create(damon_manager_monitor_thread, NULL,
>> + "damon_dynamic");
>> +
>> + if (IS_ERR(monitor_thread))
>> + return PTR_ERR(monitor_thread);
>> +
>> + wake_up_process(monitor_thread);
>> + return 0;
>> +}
>> +
>> +static int damon_hugepage_turn(bool on)
>> +{
>> + int err = 0;
>> +
>> + mutex_lock(&enable_disable_lock);
>> + if (!on) {
>> + if (monitor_thread) {
>> + kthread_stop(monitor_thread);
>> + monitor_thread = NULL;
>> + }
>> + goto out;
>> + }
>> + err = damon_hugepage_start_monitor_thread();
>> +out:
>> + mutex_unlock(&enable_disable_lock);
>> + return err;
>> +}
>> +
>> +static int damon_hugepage_enabled_store(const char *val,
>> + const struct kernel_param *kp)
>> +{
>> + bool is_enabled = enabled;
>> + bool enable;
>> + int err;
>> +
>> + err = kstrtobool(val, &enable);
>> + if (err)
>> + return err;
>> +
>> + if (is_enabled == enable)
>> + return 0;
>> +
>> + err = damon_hugepage_turn(enable);
>> + if (err)
>> + return err;
>> +
>> + enabled = enable;
>> + return err;
>> +}
>> +
>> +static const struct kernel_param_ops enabled_param_ops = {
>> + .set = damon_hugepage_enabled_store,
>> + .get = param_get_bool,
>> +};
>> +
>> +module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
>> +MODULE_PARM_DESC(enabled,
>> + "Enable or disable DAMON_DYNAMIC_HUGEPAGES (default: disabled)");
>
> s/DYNAMIC_// ?
OK
>
>> +
>> +static int __init damon_hugepage_init(void)
>> +{
>> + int err;
>> +
>> + /* 'enabled' has set before this function, probably via command line */
>> + if (enabled)
>> + err = damon_hugepage_turn(true);
>> +
>> + if (err && enabled)
>> + enabled = false;
>> + return err;
>> +}
>> +
>> +module_init(damon_hugepage_init);
>> --
>> 2.43.0
>
> [1] https://lore.kernel.org/00aa6914-8e52-49a2-9875-588efc096c5e@huawei-partners.com
>
>
> Thanks,
> SJ
>
--
Asier Gutierrez
Huawei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules
2026-03-11 13:10 ` Gutierrez Asier
@ 2026-03-11 14:15 ` SeongJae Park
0 siblings, 0 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 14:15 UTC (permalink / raw)
To: Gutierrez Asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Wed, 11 Mar 2026 16:10:19 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
>
> On 3/11/2026 3:57 AM, SeongJae Park wrote:
> > On Tue, 10 Mar 2026 16:24:17 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> >
> >> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >>
> >> It is more elegant to have a generic version of new context creation
> >> which receives the mode as a parameter.
> >>
> >> Signed-off-by: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >> Co-developed-by: Anatoly Stepanov <stepanov.anatoly@huawei.com>
> >> ---
> >> mm/damon/lru_sort.c | 5 +++--
> >> mm/damon/modules-common.c | 6 +++---
> >> mm/damon/modules-common.h | 4 ++--
> >> mm/damon/reclaim.c | 5 +++--
> >> 4 files changed, 11 insertions(+), 9 deletions(-)
> >>
> >> diff --git a/mm/damon/lru_sort.c b/mm/damon/lru_sort.c
> >> index 7bc5c0b2aea3..143ee0b21da6 100644
> >> --- a/mm/damon/lru_sort.c
> >> +++ b/mm/damon/lru_sort.c
> >> @@ -287,7 +287,8 @@ static int damon_lru_sort_apply_parameters(void)
> >> unsigned int hot_thres, cold_thres;
> >> int err;
> >>
> >> - err = damon_modules_new_paddr_ctx_target(¶m_ctx, ¶m_target);
> >> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
> >> + DAMON_OPS_PADDR);
> >
> > I like the name of the function is becoming shorter. But I'm not happy with
> > the fact the resulting calling code becomes longer.
> >
> > I understand you are doing this extension because you want a version of the
> > function for vaddr. What about introducing another dedicated function, say,
> > damon_modules_new_vaddr_ctx_target() ?
> >
> > And you can avoid duplicates between damon_modules_new_{p,v}addr_ctx_target()
> > by implementing internal function, say, damon_modules_new_ctx_target() that
> > receives the damon_ops_id. And damon_modules_new_{P,v}addr_ctx_target() will
> > just wrappers of damon_modules_new_ctx_target().
>
> Sure, I will do it.
Thanks for accepting my suggestion.
>
> Since this is some generic code not related to the module I am working on,
> maybe I can move this to a different patch set that we can upstream. What do
> you think?
Please feel free to do so :)
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse
2026-03-11 13:11 ` Gutierrez Asier
@ 2026-03-11 14:17 ` SeongJae Park
0 siblings, 0 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 14:17 UTC (permalink / raw)
To: Gutierrez Asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Wed, 11 Mar 2026 16:11:12 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
>
> On 3/11/2026 4:02 AM, SeongJae Park wrote:
> > On Tue, 10 Mar 2026 16:24:18 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> >
> >> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >
> > Please add more descriptions of the change, including the motivation.
> >
> > I assume the motivation is similar to MADV_COLLAPSE that aims to make
> > synchronous and therefore faster huge page collapsing impacts copared to
> > MADV_HUGEPAGE? It would be nice to make it clear here. Also, if my assumption
> > is not wrong, adding a test results showing the benefit of DAMOS_COLLAPSE over
> > DAMOS_HUGEPAGE here would be nice.
>
> You are right. I will make it more clear in the cover letter for the next
> version.
Sounds good. But please add a brief commit message in addition to the subject
here, too. Some people complains blank commit message looks odd.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 3/4] mm/damon: New module with hot application detection
2026-03-11 13:45 ` Gutierrez Asier
@ 2026-03-11 14:32 ` SeongJae Park
0 siblings, 0 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 14:32 UTC (permalink / raw)
To: Gutierrez Asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Wed, 11 Mar 2026 16:45:06 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
>
> On 3/11/2026 7:11 AM, SeongJae Park wrote:
> > On Tue, 10 Mar 2026 16:24:19 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> >
> >> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >
> > I'd like to discuss about this in a high level, but I'd like to do that on the
> > cover letter. To this patch, I'm therefore adding comments for only details
> > that stand out immeadiately to me.
>
> I will update the cover letter to add more details for the next version.
>
> >>
> >> 1. It first launches a new kthread called damon_dynamic. This thread
> >> will behave as a supervisor, launching new kdamond threads for all
> >> the processes we want to montiored. The tasks are sorted
> >> by utime delta. For the top N tasks, a new kdamond thread will be
> >> launched.
> >
> > If I read the cover letter and the code of this patch correctly, seems the last
> > two sentences of the above paragraph is outdated. Please correct me if I'm
> > wrong.
>
> Correct, I forgot to delete it.
Thank you for confirming that, and accepting my suggestions below. Most of
your answers to my comments make sense, so I'm cutting most of the part except
places where I want to clarify my points or answer your questions below.
[...]
> >> +};
> >> +DEFINE_DAMON_MODULES_DAMOS_TIME_QUOTA(damon_hugepage_quota);
> >> +
> >> +static struct damos_watermarks damon_hugepage_wmarks = {
> >> + .metric = DAMOS_WMARK_FREE_MEM_RATE,
> >> + .interval = 5000000, /* 5 seconds */
> >> + .high = 900, /* 90 percent */
> >> + .mid = 800, /* 80 percent */
> >> + .low = 50, /* 5 percent */
> >> +};
> >> +DEFINE_DAMON_MODULES_WMARKS_PARAMS(damon_hugepage_wmarks);
> >
> > In the RFC v1 discussion, you also mentioned you will remove the above, but
> > seems it is forgotten?
> >
> > Also, my understadning of your reply on the previous discussion was that you
> > don't really want to use watermarks in this module, and therefore you want to
> > remove it. Am I correct? If I'm not, maybe I'm still not understanding the
> > intention of the watermarks. Can you please enlighten me?
>
> Since I refactored heavily the previous code, I forgot to delete this bit.
> I will remove it now.
Thank you for clarifying this :)
>
> >> +
> >> +static struct damon_attrs damon_hugepage_mon_attrs = {
> >> + .sample_interval = 5000, /* 5 ms */
> >> + .aggr_interval = 100000, /* 100 ms */
> >> + .ops_update_interval = 0,
> >
> > Is ops_update_interval = 0 really your intention?
>
> I didn't think about it. I will set it to 60 seconds, as in other modules.
Sounds good.
When 'vaddr' operation set is used, for every ops_update_interval, 'vaddr'
updates monitoring target regions boundary to cover all virtual address
mappings. If it is '0', it will do the update on every iteration of the
kdamond main loop. It can result in unnecessary overhead. So I was asking the
above question. Setting it to 60 seconds sounds good to me.
[...]
> >> + err = damon_modules_new_ctx_target(¶m_ctx, ¶m_target,
> >> + DAMON_OPS_VADDR);
> >> + if (err)
> >> + return err;
> >
> > You should deallocate param_ctx before returning the error.
>
> Not sure about this. As far as I know, damon_modules_new_paddr_ctx_target
> will destroy the context in case there is an error. In fact, reclaim and
> lru_sort modules just return error when damon_modules_new_paddr_ctx_target
> fails, no cleanup used.
You're correct, I was trying to comment only below, but somehow confused the
place. Sorry for the confusion.
[...]
> >> +
> >> + list_for_each_entry_safe(monitored_task, tmp, monitored_tasks, list) {
> >
> > Please wrap lines for the 80 columns limit.
>
> Interesting, when check it, i was less than 80 columns. Even if I copy this line
> and paste it into any text editor, I still get less than 80 characters.
Oh, you must be correct. Maybe my mailing tool was showing it incorrectly.
Please keep it as is if it doesn't exceed 80 columns.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-11 13:08 ` Gutierrez Asier
@ 2026-03-11 14:39 ` SeongJae Park
2026-03-11 23:55 ` SeongJae Park
2026-03-12 14:42 ` Gutierrez Asier
0 siblings, 2 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 14:39 UTC (permalink / raw)
To: Gutierrez Asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Wed, 11 Mar 2026 16:08:56 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
> Hi SeongJae,
>
> On 3/11/2026 8:07 AM, SeongJae Park wrote:
> > Hello Asier,
> >
> >
> > Thank you for continuing this work!
> >
> > On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> >
> >> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >>
> >> Overview
> >> ----------
> >
> > Let's make the legnth of the subject and the length of the underline same.
> >
> >>
> >> This patch set introduces a new dynamic mechanism for detecting hot applications
> >> and hot regions in those applications.
> >
> > Seems now you offload the hot applications detection to the user space. If I'm
> > not wrong, you should remove "hot applications and" on the above sentence.
>
> You're right. I was not sure whether changing the RFC subject was right or not.
> I will change it for the next RFC version.
It's fine to change the subject. Please feel free to do so in the next version
:)
>
> >>
> >> Motivation
> >> -----------
> >>
> >> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
> >> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
> >> fragmentation and memory waste. For this reason, most application guides and
> >> system administrators suggest to disable THP.
> >>
> >>
> >> Solution
> >> -----------
> >>
> >> A new Linux kernel module that uses DAMON to detect hot regions and collapse
> >> those regions into huge pages. The user supplies a set of PIDs using a module
> >> parameter,
> >
> > This sounds reasonable to me.
> >
> >> and then, the module launches a new kdamond thread to monitor each
> >> of the tasks.
> >>
> >> In each kdamond, we start with a high min_access value. Our goal is to find the
> >> "maximum" min_access value at which point the DAMON action is applied. In each
> >> cycle, if no action is applied, we lower the min_access.
> >
> > So, this patch series introduces a sort of auto-tuning of the hugepages
> > collapse hotness threshold, that implemented in the new module.
> >
> > We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
> > quota auto-tuning [1]. Have you considered using that? Of course, it might
> > not be able to be used as is. Some extensions, e.g., introduction of new goal
> > metric, may be needed.
> >
> > Yet another approach would be implementing the auto-tuning in the user-space.
> > Because DAMON parameters can be updated online, updating the min_access from
> > the user space should be doable? Given the fact the module anyway require
> > user-space control for feeding the list of applications to apply access-aware
> > huge pages collapsing, I find no problem at user space driven auto-tuning.
> >
> > If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
> > are feasible, all the controls can be done using DAMON sysfs interface.
> > Introduction of the new kernel module might not really be needed in the case.
> >
> > We have DAMON modules in addition to DAMON sysfs interface for users who want
> > to use DAMON for a given specific use case with only minimum or near-zero
> > user-space control. In this case, because it is already aimed to ask the
> > user-space to feed the list of applications to apply DAMOS-based hugepages
> > collapsing, it seems a new module is not really needed, to me.
> >
> > But I guess your use case might have some special restrictions that really
> > require use of the module instead of offloading the auto-tuning to the
> > user-space or DAMON core. Is that the case? If so, can you share more details
> > about it?
>
> I haven't figured out how I can use goal autotune to change the min_access.
Indeed, it is not a very straightforward feature.
> Your suggestion about moving this to the user space sound good.
If it works for you, maybe that is best for you :)
>
> The idea was to stop lowering the min_access as soon as collapses occur,
> since we don't want to lower so much that we start collapsing regions that
> are not very hot.
>
> Maybe you can suggest a better way to do it. Maybe with autotuning.
I will add more detailed suggestion soon, by tomorrow or a day after.
>
> >
> >>
> >> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
> >> collapse synchronously and avoid polluting khugepaged and other parts of the MM
> >> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
> >> which needs the correct vm_flags_t set.
> >
> > This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
> > DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
> >
> > From my perspective, this patch series is introducing three things.
> > 1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
> > the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
> > changes are really needed. I will wait your answer.
Please answer the above questions when you get a chance.
> >
> > Meanwhile, the third change seems reasonable and not necessarily need to be
> > blocked for the other two changes. I think separating the third change from
> > this patch series and upstreaming it first could also be a path forward.
> > Because the change is simple and sound, convincing me would be easy. I'd be
> > convinced if at least some reasonable test results can be shown. I'm not
> > saying we should drop the other two changes. We can keep discussing those in
> > parallel. Rather, upstreaming the third change first could help finding real
> > benefits of the other two changes, since the testing will be easier. The
> > decision is up to Asier, of course. I'm just sharing my two cents.
I'm also curious what you think about this.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-11 14:39 ` SeongJae Park
@ 2026-03-11 23:55 ` SeongJae Park
2026-03-12 14:42 ` Gutierrez Asier
1 sibling, 0 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-11 23:55 UTC (permalink / raw)
To: SeongJae Park
Cc: Gutierrez Asier, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Wed, 11 Mar 2026 07:39:12 -0700 SeongJae Park <sj@kernel.org> wrote:
> On Wed, 11 Mar 2026 16:08:56 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
> > Hi SeongJae,
> >
> > On 3/11/2026 8:07 AM, SeongJae Park wrote:
> > > Hello Asier,
> > >
> > >
> > > Thank you for continuing this work!
> > >
> > > On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> > >
> > >> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> > >>
> > >> Overview
> > >> ----------
> > >
> > > Let's make the legnth of the subject and the length of the underline same.
> > >
> > >>
> > >> This patch set introduces a new dynamic mechanism for detecting hot applications
> > >> and hot regions in those applications.
> > >
> > > Seems now you offload the hot applications detection to the user space. If I'm
> > > not wrong, you should remove "hot applications and" on the above sentence.
> >
> > You're right. I was not sure whether changing the RFC subject was right or not.
> > I will change it for the next RFC version.
>
> It's fine to change the subject. Please feel free to do so in the next version
> :)
>
> >
> > >>
> > >> Motivation
> > >> -----------
> > >>
> > >> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
> > >> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
> > >> fragmentation and memory waste. For this reason, most application guides and
> > >> system administrators suggest to disable THP.
> > >>
> > >>
> > >> Solution
> > >> -----------
> > >>
> > >> A new Linux kernel module that uses DAMON to detect hot regions and collapse
> > >> those regions into huge pages. The user supplies a set of PIDs using a module
> > >> parameter,
> > >
> > > This sounds reasonable to me.
> > >
> > >> and then, the module launches a new kdamond thread to monitor each
> > >> of the tasks.
> > >>
> > >> In each kdamond, we start with a high min_access value. Our goal is to find the
> > >> "maximum" min_access value at which point the DAMON action is applied. In each
> > >> cycle, if no action is applied, we lower the min_access.
> > >
> > > So, this patch series introduces a sort of auto-tuning of the hugepages
> > > collapse hotness threshold, that implemented in the new module.
> > >
> > > We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
> > > quota auto-tuning [1]. Have you considered using that? Of course, it might
> > > not be able to be used as is. Some extensions, e.g., introduction of new goal
> > > metric, may be needed.
> > >
> > > Yet another approach would be implementing the auto-tuning in the user-space.
> > > Because DAMON parameters can be updated online, updating the min_access from
> > > the user space should be doable? Given the fact the module anyway require
> > > user-space control for feeding the list of applications to apply access-aware
> > > huge pages collapsing, I find no problem at user space driven auto-tuning.
> > >
> > > If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
> > > are feasible, all the controls can be done using DAMON sysfs interface.
> > > Introduction of the new kernel module might not really be needed in the case.
> > >
> > > We have DAMON modules in addition to DAMON sysfs interface for users who want
> > > to use DAMON for a given specific use case with only minimum or near-zero
> > > user-space control. In this case, because it is already aimed to ask the
> > > user-space to feed the list of applications to apply DAMOS-based hugepages
> > > collapsing, it seems a new module is not really needed, to me.
> > >
> > > But I guess your use case might have some special restrictions that really
> > > require use of the module instead of offloading the auto-tuning to the
> > > user-space or DAMON core. Is that the case? If so, can you share more details
> > > about it?
> >
> > I haven't figured out how I can use goal autotune to change the min_access.
>
> Indeed, it is not a very straightforward feature.
>
> > Your suggestion about moving this to the user space sound good.
>
> If it works for you, maybe that is best for you :)
>
> >
> > The idea was to stop lowering the min_access as soon as collapses occur,
> > since we don't want to lower so much that we start collapsing regions that
> > are not very hot.
> >
> > Maybe you can suggest a better way to do it. Maybe with autotuning.
>
> I will add more detailed suggestion soon, by tomorrow or a day after.
First of all, as I mentioned on the above reply, if the approach of this patch
series (starting from high min_access and lowering down until some pages really
be collapsed) works for your use case, and you are ok at doing it in user space
approach, I think that should be the best for you, and I'd recommend going on
the direction.
But if you want to use the aim-oriented DAMOS quota goal auto-tuning, maybe I
can suggest following options.
Let me start from the basic background. Using aim-oriented auto-tuning, the
user can set the aimed goal of a given DAMOS scheme. Then, DAMOS automatically
increases the quota if the goal is under-achieved. If the goal is
over-achieved, DAMOS decreases the quota. More details are available on the
documentation [1].
So what you need is finding a proper goal. In the hugepage use case, I expect
the goal is an amount of hugepages for the application. Say, the goal can be
"making X% of the application memory hugepage". DAMOS quota goal feature
supports multiple types of goals. Unfortunately, there is no one for exactly
this example goal type. There can be two options.
First, using 'user_input' goal type. It allows users to directly feed the
current goal achievement to DAMON. You can measure how much of the
applicastion's memory is hugepage and feed that inofrmation with 'user_input'
goal type. If user-space approach is ok for you, this should also work.
Second, implementing yet another goal type for the use case. No single quota
goal fits all, and therefore we are adding new quota goal whenever it is
needed.
But, again, if the approach of this patch series is proven to work for your use
case, and it is ok to implement it in user space, that should be the best and
fastest option for you.
Also I don't know your real use case. Hence my quota goal based approach
suggestion might make no sense at all for your use case. If you want, I will
be happy to learn more about your use case and suggest another option.
Nonetheless, I'm also only struggling at finding the best way for utilizing
DAMON for hugepages, and therefore trying to get some community feedback in
LSF/MM/BPF [2].
[1] https://docs.kernel.org/mm/damon/design.html#aim-oriented-feedback-driven-auto-tuning
[2] https://lore.kernel.org/all/20260211050729.69719-1-sj@kernel.org/
Thanks,
SJ
>
> >
> > >
> > >>
> > >> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
> > >> collapse synchronously and avoid polluting khugepaged and other parts of the MM
> > >> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
> > >> which needs the correct vm_flags_t set.
> > >
> > > This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
> > > DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
> > >
> > > From my perspective, this patch series is introducing three things.
> > > 1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
> > > the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
> > > changes are really needed. I will wait your answer.
>
> Please answer the above questions when you get a chance.
>
> > >
> > > Meanwhile, the third change seems reasonable and not necessarily need to be
> > > blocked for the other two changes. I think separating the third change from
> > > this patch series and upstreaming it first could also be a path forward.
> > > Because the change is simple and sound, convincing me would be easy. I'd be
> > > convinced if at least some reasonable test results can be shown. I'm not
> > > saying we should drop the other two changes. We can keep discussing those in
> > > parallel. Rather, upstreaming the third change first could help finding real
> > > benefits of the other two changes, since the testing will be easier. The
> > > decision is up to Asier, of course. I'm just sharing my two cents.
>
> I'm also curious what you think about this.
>
>
> Thanks,
> SJ
>
> [...]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-11 14:39 ` SeongJae Park
2026-03-11 23:55 ` SeongJae Park
@ 2026-03-12 14:42 ` Gutierrez Asier
2026-03-13 0:08 ` SeongJae Park
1 sibling, 1 reply; 20+ messages in thread
From: Gutierrez Asier @ 2026-03-12 14:42 UTC (permalink / raw)
To: SeongJae Park
Cc: artem.kuzin, stepanov.anatoly, wangkefeng.wang, yanquanmin1,
zuoze1, damon, akpm, linux-mm, linux-kernel
On 3/11/2026 5:39 PM, SeongJae Park wrote:
> On Wed, 11 Mar 2026 16:08:56 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
>> Hi SeongJae,
>>
>> On 3/11/2026 8:07 AM, SeongJae Park wrote:
>>> Hello Asier,
>>>
>>>
>>> Thank you for continuing this work!
>>>
>>> On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
>>>
>>>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
>>>>
>>>> Overview
>>>> ----------
>>>
>>> Let's make the legnth of the subject and the length of the underline same.
>>>
>>>>
>>>> This patch set introduces a new dynamic mechanism for detecting hot applications
>>>> and hot regions in those applications.
>>>
>>> Seems now you offload the hot applications detection to the user space. If I'm
>>> not wrong, you should remove "hot applications and" on the above sentence.
>>
>> You're right. I was not sure whether changing the RFC subject was right or not.
>> I will change it for the next RFC version.
>
> It's fine to change the subject. Please feel free to do so in the next version
> :)
>
>>
>>>>
>>>> Motivation
>>>> -----------
>>>>
>>>> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
>>>> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
>>>> fragmentation and memory waste. For this reason, most application guides and
>>>> system administrators suggest to disable THP.
>>>>
>>>>
>>>> Solution
>>>> -----------
>>>>
>>>> A new Linux kernel module that uses DAMON to detect hot regions and collapse
>>>> those regions into huge pages. The user supplies a set of PIDs using a module
>>>> parameter,
>>>
>>> This sounds reasonable to me.
>>>
>>>> and then, the module launches a new kdamond thread to monitor each
>>>> of the tasks.
>>>>
>>>> In each kdamond, we start with a high min_access value. Our goal is to find the
>>>> "maximum" min_access value at which point the DAMON action is applied. In each
>>>> cycle, if no action is applied, we lower the min_access.
>>>
>>> So, this patch series introduces a sort of auto-tuning of the hugepages
>>> collapse hotness threshold, that implemented in the new module.
>>>
>>> We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
>>> quota auto-tuning [1]. Have you considered using that? Of course, it might
>>> not be able to be used as is. Some extensions, e.g., introduction of new goal
>>> metric, may be needed.
>>>
>>> Yet another approach would be implementing the auto-tuning in the user-space.
>>> Because DAMON parameters can be updated online, updating the min_access from
>>> the user space should be doable? Given the fact the module anyway require
>>> user-space control for feeding the list of applications to apply access-aware
>>> huge pages collapsing, I find no problem at user space driven auto-tuning.
>>>
>>> If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
>>> are feasible, all the controls can be done using DAMON sysfs interface.
>>> Introduction of the new kernel module might not really be needed in the case.
>>>
>>> We have DAMON modules in addition to DAMON sysfs interface for users who want
>>> to use DAMON for a given specific use case with only minimum or near-zero
>>> user-space control. In this case, because it is already aimed to ask the
>>> user-space to feed the list of applications to apply DAMOS-based hugepages
>>> collapsing, it seems a new module is not really needed, to me.
>>>
>>> But I guess your use case might have some special restrictions that really
>>> require use of the module instead of offloading the auto-tuning to the
>>> user-space or DAMON core. Is that the case? If so, can you share more details
>>> about it?
>>
>> I haven't figured out how I can use goal autotune to change the min_access.
>
> Indeed, it is not a very straightforward feature.
>
>> Your suggestion about moving this to the user space sound good.
>
> If it works for you, maybe that is best for you :)
>
>>
>> The idea was to stop lowering the min_access as soon as collapses occur,
>> since we don't want to lower so much that we start collapsing regions that
>> are not very hot.
>>
>> Maybe you can suggest a better way to do it. Maybe with autotuning.
>
> I will add more detailed suggestion soon, by tomorrow or a day after.
>
>>
>>>
>>>>
>>>> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
>>>> collapse synchronously and avoid polluting khugepaged and other parts of the MM
>>>> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
>>>> which needs the correct vm_flags_t set.
>>>
>>> This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
>>> DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
>>>
>>> From my perspective, this patch series is introducing three things.
>>> 1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
>>> the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
>>> changes are really needed. I will wait your answer.
Yes, I tried to introduce those 3 things. The problem is that I initially found
goal autotuning quite confusing, so I kind of implemented something that behaves
like autotuning, but doesn't use DAMON's core algorithm.
>
>>>
>>> Meanwhile, the third change seems reasonable and not necessarily need to be
>>> blocked for the other two changes. I think separating the third change from
>>> this patch series and upstreaming it first could also be a path forward.
>>> Because the change is simple and sound, convincing me would be easy. I'd be
>>> convinced if at least some reasonable test results can be shown. I'm not
>>> saying we should drop the other two changes. We can keep discussing those in
>>> parallel. Rather, upstreaming the third change first could help finding real
>>> benefits of the other two changes, since the testing will be easier. The
>>> decision is up to Asier, of course. I'm just sharing my two cents.
>
> I'm also curious what you think about this.
Sure, we can upstream the third change. I will prepare a new patch for with just
that diff.
>
> Thanks,
> SJ
>
> [...]
>
The use case that I had in mind is pretty simple. Few admins use huge pages in
production, since it leads to memory fragmentation and waste. On the other hand,
amount of memory increases faster than entries in the TLB, which means more
TLB misses and more cycles waste. My goal is to balance this. Improve performance
in applications while keeping the amount of memory waste due to fragmentation to
a minimum.
Imagine a database server. The sysadmin would like to collapse only hot regions
of the database task, improving CPU utilization but without wasting too much
memory.
Today I sat down and review the damon code. Given all your feedback, I think
this I didn't use the right approach or I didn't understand you initially.
My suggestions:
1. Implement a new goal type for autotuning that uses huge pages.
2. Implement a module that uses this new goal type.
Would this make sense to you?
--
Asier Gutierrez
Huawei
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [RFC PATCH v2 0/4] mm/damon: Support hot application detections
2026-03-12 14:42 ` Gutierrez Asier
@ 2026-03-13 0:08 ` SeongJae Park
0 siblings, 0 replies; 20+ messages in thread
From: SeongJae Park @ 2026-03-13 0:08 UTC (permalink / raw)
To: Gutierrez Asier
Cc: SeongJae Park, artem.kuzin, stepanov.anatoly, wangkefeng.wang,
yanquanmin1, zuoze1, damon, akpm, linux-mm, linux-kernel
On Thu, 12 Mar 2026 17:42:35 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
>
>
> On 3/11/2026 5:39 PM, SeongJae Park wrote:
> > On Wed, 11 Mar 2026 16:08:56 +0300 Gutierrez Asier <gutierrez.asier@huawei-partners.com> wrote:
> >
> >> Hi SeongJae,
> >>
> >> On 3/11/2026 8:07 AM, SeongJae Park wrote:
> >>> Hello Asier,
> >>>
> >>>
> >>> Thank you for continuing this work!
> >>>
> >>> On Tue, 10 Mar 2026 16:24:16 +0000 <gutierrez.asier@huawei-partners.com> wrote:
> >>>
> >>>> From: Asier Gutierrez <gutierrez.asier@huawei-partners.com>
> >>>>
> >>>> Overview
> >>>> ----------
> >>>
> >>> Let's make the legnth of the subject and the length of the underline same.
> >>>
> >>>>
> >>>> This patch set introduces a new dynamic mechanism for detecting hot applications
> >>>> and hot regions in those applications.
> >>>
> >>> Seems now you offload the hot applications detection to the user space. If I'm
> >>> not wrong, you should remove "hot applications and" on the above sentence.
> >>
> >> You're right. I was not sure whether changing the RFC subject was right or not.
> >> I will change it for the next RFC version.
> >
> > It's fine to change the subject. Please feel free to do so in the next version
> > :)
> >
> >>
> >>>>
> >>>> Motivation
> >>>> -----------
> >>>>
> >>>> Since TLB is a bottleneck for many systems, a way to optimize TLB misses (or
> >>>> hits) is to use huge pages. Unfortunately, using "always" in THP leads to memory
> >>>> fragmentation and memory waste. For this reason, most application guides and
> >>>> system administrators suggest to disable THP.
> >>>>
> >>>>
> >>>> Solution
> >>>> -----------
> >>>>
> >>>> A new Linux kernel module that uses DAMON to detect hot regions and collapse
> >>>> those regions into huge pages. The user supplies a set of PIDs using a module
> >>>> parameter,
> >>>
> >>> This sounds reasonable to me.
> >>>
> >>>> and then, the module launches a new kdamond thread to monitor each
> >>>> of the tasks.
> >>>>
> >>>> In each kdamond, we start with a high min_access value. Our goal is to find the
> >>>> "maximum" min_access value at which point the DAMON action is applied. In each
> >>>> cycle, if no action is applied, we lower the min_access.
> >>>
> >>> So, this patch series introduces a sort of auto-tuning of the hugepages
> >>> collapse hotness threshold, that implemented in the new module.
> >>>
> >>> We already have a sort of DAMOS auto-tuning feature, namely goal-based DAMOS
> >>> quota auto-tuning [1]. Have you considered using that? Of course, it might
> >>> not be able to be used as is. Some extensions, e.g., introduction of new goal
> >>> metric, may be needed.
> >>>
> >>> Yet another approach would be implementing the auto-tuning in the user-space.
> >>> Because DAMON parameters can be updated online, updating the min_access from
> >>> the user space should be doable? Given the fact the module anyway require
> >>> user-space control for feeding the list of applications to apply access-aware
> >>> huge pages collapsing, I find no problem at user space driven auto-tuning.
> >>>
> >>> If the goal-based DAMOS quota auto-tuning or the user-space based auto-tuning
> >>> are feasible, all the controls can be done using DAMON sysfs interface.
> >>> Introduction of the new kernel module might not really be needed in the case.
> >>>
> >>> We have DAMON modules in addition to DAMON sysfs interface for users who want
> >>> to use DAMON for a given specific use case with only minimum or near-zero
> >>> user-space control. In this case, because it is already aimed to ask the
> >>> user-space to feed the list of applications to apply DAMOS-based hugepages
> >>> collapsing, it seems a new module is not really needed, to me.
> >>>
> >>> But I guess your use case might have some special restrictions that really
> >>> require use of the module instead of offloading the auto-tuning to the
> >>> user-space or DAMON core. Is that the case? If so, can you share more details
> >>> about it?
> >>
> >> I haven't figured out how I can use goal autotune to change the min_access.
> >
> > Indeed, it is not a very straightforward feature.
> >
> >> Your suggestion about moving this to the user space sound good.
> >
> > If it works for you, maybe that is best for you :)
> >
> >>
> >> The idea was to stop lowering the min_access as soon as collapses occur,
> >> since we don't want to lower so much that we start collapsing regions that
> >> are not very hot.
> >>
> >> Maybe you can suggest a better way to do it. Maybe with autotuning.
> >
> > I will add more detailed suggestion soon, by tomorrow or a day after.
> >
> >>
> >>>
> >>>>
> >>>> Regarding the action, we introduce a new action: DAMOS_COLLAPSE. This allows us
> >>>> collapse synchronously and avoid polluting khugepaged and other parts of the MM
> >>>> subsystem with DAMON stuff. DAMOS_HUGEPAGE eventually calls hugepage_madvise,
> >>>> which needs the correct vm_flags_t set.
> >>>
> >>> This makes sense to me. I expect DAMOS_COLLAPSE to have some advantages over
> >>> DAMOS_HUGEPAGE for some use cases, similar to MADV_COLLAPSE vs MADV_HUGEPAGE.
> >>>
> >>> From my perspective, this patch series is introducing three things.
> >>> 1) hugepage collapsing hotness threshold auto-tuning, 2) the module for running
> >>> the auto-tuning, and 3) DAMOS_COLLAPSE. To me, it is unclear if the first two
> >>> changes are really needed. I will wait your answer.
> Yes, I tried to introduce those 3 things. The problem is that I initially found
> goal autotuning quite confusing, so I kind of implemented something that behaves
> like autotuning, but doesn't use DAMON's core algorithm.
Sorry for the confusing autotuning. I will try to make it better documented
and simplified.
> >
> >>>
> >>> Meanwhile, the third change seems reasonable and not necessarily need to be
> >>> blocked for the other two changes. I think separating the third change from
> >>> this patch series and upstreaming it first could also be a path forward.
> >>> Because the change is simple and sound, convincing me would be easy. I'd be
> >>> convinced if at least some reasonable test results can be shown. I'm not
> >>> saying we should drop the other two changes. We can keep discussing those in
> >>> parallel. Rather, upstreaming the third change first could help finding real
> >>> benefits of the other two changes, since the testing will be easier. The
> >>> decision is up to Asier, of course. I'm just sharing my two cents.
> >
> > I'm also curious what you think about this.
>
> Sure, we can upstream the third change. I will prepare a new patch for with just
> that diff.
Thank you!
>
> >
> > Thanks,
> > SJ
> >
> > [...]
> >
>
> The use case that I had in mind is pretty simple. Few admins use huge pages in
> production, since it leads to memory fragmentation and waste. On the other hand,
> amount of memory increases faster than entries in the TLB, which means more
> TLB misses and more cycles waste. My goal is to balance this. Improve performance
> in applications while keeping the amount of memory waste due to fragmentation to
> a minimum.
>
> Imagine a database server. The sysadmin would like to collapse only hot regions
> of the database task, improving CPU utilization but without wasting too much
> memory.
This makes perfect sense to me, thank you for clarifying.
Nonetheless, I think there could be devils in the details. For example,
1) How we find the application to collapse hot memory for?
2) What should be the hotness threshold for the collapsing?
3) Should the collapse be done asynchronously like MADV_HUGEPAGE, or
synchronously, like MADV_COLLAPSE?
And I understand now we are aligned with below answers.
1) User-space may know and existing DAMON sysfs interface supports that.
2) Users-space may know and existing DAMON sysfs interface supports that.
3) Should be synchronous, but DAMON doesn't support that; DAMOS_COLLAPSE need
to be upstreamed.
As I mentioned above, I think this makes sense. Looking forward to your
DAMOS_COLLAPSE patch!
>
>
> Today I sat down and review the damon code. Given all your feedback, I think
> this I didn't use the right approach or I didn't understand you initially.
> My suggestions:
>
> 1. Implement a new goal type for autotuning that uses huge pages.
> 2. Implement a module that uses this new goal type.
>
> Would this make sense to you?
Yes that sounds like a nice step-by-step approach. We might need to discuss
more about the details for each step, but I think this is the good direction to
go: merge obviously beneficial part first and discuss more/revisit next thing
one by one.
Thanks,
SJ
[...]
^ permalink raw reply [flat|nested] 20+ messages in thread
end of thread, other threads:[~2026-03-13 0:08 UTC | newest]
Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-10 16:24 [RFC PATCH v2 0/4] mm/damon: Support hot application detections gutierrez.asier
2026-03-10 16:24 ` [RFC PATCH v2 1/4] mm/damon: Generic context creation for modules gutierrez.asier
2026-03-11 0:57 ` SeongJae Park
2026-03-11 13:10 ` Gutierrez Asier
2026-03-11 14:15 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 2/4] mm/damon: Support for synchrounous huge pages collapse gutierrez.asier
2026-03-11 1:02 ` SeongJae Park
2026-03-11 13:11 ` Gutierrez Asier
2026-03-11 14:17 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 3/4] mm/damon: New module with hot application detection gutierrez.asier
2026-03-11 4:11 ` SeongJae Park
2026-03-11 13:45 ` Gutierrez Asier
2026-03-11 14:32 ` SeongJae Park
2026-03-10 16:24 ` [RFC PATCH v2 4/4] DAMON_HOT_HUGEPAGE documentation gutierrez.asier
2026-03-11 5:07 ` [RFC PATCH v2 0/4] mm/damon: Support hot application detections SeongJae Park
2026-03-11 13:08 ` Gutierrez Asier
2026-03-11 14:39 ` SeongJae Park
2026-03-11 23:55 ` SeongJae Park
2026-03-12 14:42 ` Gutierrez Asier
2026-03-13 0:08 ` SeongJae Park
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox