[PATCH] idea

From: Lorenzo Stoakes (Oracle)

Date: Wed Mar 04 2026 - 11:37:20 EST


Signed-off-by: Lorenzo Stoakes (Oracle) <ljs@xxxxxxxxxx>
---
mm/huge_memory.c | 74 ++++++++++++++++++++++++++++++------------------
1 file changed, 46 insertions(+), 28 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 0df1f4a17430..97dabbeb9112 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -515,46 +515,64 @@ static ssize_t anon_enabled_show(struct kobject *kobj,
return sysfs_emit(buf, "%s\n", output);
}

+enum huge_mode {
+ HUGE_ALWAYS,
+ HUGE_INHERIT,
+ HUGE_MADVISE,
+ HUGE_NUM_MODES,
+ HUGE_NEVER,
+};
+
+static bool change_anon_orders(int order, enum huge_mode mode)
+{
+ static unsigned long *orders[] = {
+ &huge_anon_orders_always,
+ &huge_anon_orders_inherit,
+ &huge_anon_orders_madvise,
+ };
+ bool changed = false;
+ int i;
+
+ spin_lock(&huge_anon_orders_lock);
+ for (i = 0; i < HUGE_NUM_MODES; i++) {
+ if (i == mode)
+ changed |= !test_and_set_bit(order, orders[mode]);
+ else
+ changed |= test_and_clear_bit(order, orders[mode]);
+ }
+ spin_unlock(&huge_anon_orders_lock);
+
+ return changed;
+}
+
static ssize_t anon_enabled_store(struct kobject *kobj,
struct kobj_attribute *attr,
const char *buf, size_t count)
{
int order = to_thpsize(kobj)->order;
ssize_t ret = count;
+ bool changed;
+
+ if (sysfs_streq(buf, "always"))
+ changed = change_anon_orders(order, HUGE_ALWAYS);
+ else if (sysfs_streq(buf, "inherit"))
+ changed = change_anon_orders(order, HUGE_INHERIT);
+ else if (sysfs_streq(buf, "madvise"))
+ changed = change_anon_orders(order, HUGE_MADVISE);
+ else if (sysfs_streq(buf, "never"))
+ changed = change_anon_orders(order, HUGE_NEVER);
+ else
+ return -EINVAL;

- if (sysfs_streq(buf, "always")) {
- spin_lock(&huge_anon_orders_lock);
- clear_bit(order, &huge_anon_orders_inherit);
- clear_bit(order, &huge_anon_orders_madvise);
- set_bit(order, &huge_anon_orders_always);
- spin_unlock(&huge_anon_orders_lock);
- } else if (sysfs_streq(buf, "inherit")) {
- spin_lock(&huge_anon_orders_lock);
- clear_bit(order, &huge_anon_orders_always);
- clear_bit(order, &huge_anon_orders_madvise);
- set_bit(order, &huge_anon_orders_inherit);
- spin_unlock(&huge_anon_orders_lock);
- } else if (sysfs_streq(buf, "madvise")) {
- spin_lock(&huge_anon_orders_lock);
- clear_bit(order, &huge_anon_orders_always);
- clear_bit(order, &huge_anon_orders_inherit);
- set_bit(order, &huge_anon_orders_madvise);
- spin_unlock(&huge_anon_orders_lock);
- } else if (sysfs_streq(buf, "never")) {
- spin_lock(&huge_anon_orders_lock);
- clear_bit(order, &huge_anon_orders_always);
- clear_bit(order, &huge_anon_orders_inherit);
- clear_bit(order, &huge_anon_orders_madvise);
- spin_unlock(&huge_anon_orders_lock);
- } else
- ret = -EINVAL;
-
- if (ret > 0) {
+ if (changed) {
int err;

err = start_stop_khugepaged();
if (err)
ret = err;
+ } else {
+ /* Users expect this even if unchanged. TODO: Put in header... */
+ //set_recommended_min_free_kbytes();
}
return ret;
}
--
2.53.0