From 314cd43cdbdb0fb0772ee78bd943d798046fba2e Mon Sep 17 00:00:00 2001 From: Zelin Deng Date: Thu, 4 Dec 2025 13:39:02 +0800 Subject: [PATCH] anolis: mm: Fix unexpected kidled_reset even kidled is disabled ANBZ: #27405 Update scan period (non-zero -> non-zero/zero) will wake up kidled to do kidled_reset() asynchronously -- non-zero -> zero also disables kidled. zero (assumption is that kidled is disabled) -> zero/non-zero won't trigger kidled_reset(). Typically if scan period is non-zero the kidled is enabled, so that mglru cannot be enabled at this moment. However there's a special case: scan period is non-zero but kidled is disabled. The time line to trigger this case is: echo non-zero --> kidled enabled --> [kidled] run (1) --> echo zero --> [kidled] do kidled_reset (2) --> echo non->zero --> kidled enabled --> [kidled] kidled_reset(2) is done, disable kidled --> kidled disabled --> echo zero --> [kidled] do kidled_reset (3) Between (2) & (3) mglru get a chance to be enabled, as (3) can reset pages' flags, pages's lru gen can get messed. Make kidled_reset() only be involked when kidled is enabled, and limit kidled disabling (write zero) when last disabling is not done. Signed-off-by: Zelin Deng --- mm/kidled.c | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/mm/kidled.c b/mm/kidled.c index 141f3fbd2096..f702c4d1c4b7 100644 --- a/mm/kidled.c +++ b/mm/kidled.c @@ -69,6 +69,7 @@ #endif DEFINE_STATIC_KEY_FALSE(kidled_enabled_key); +static atomic_t kidled_disabling; unsigned int kidled_scan_target __read_mostly = KIDLED_SCAN_PAGE; struct kidled_scan_control kidled_scan_control; @@ -779,15 +780,22 @@ static inline bool kidled_should_run(struct kidled_scan_control *p, struct kidled_scan_control scan_control; scan_control = kidled_get_current_scan_control(); - if (p->duration) { + /* + * Both disabling or updating requires kidled is enabled. + * If kidled has been disabled already, don't do reset. + */ + if (is_kidled_enabled() && p->duration) { #ifdef KIDLED_AGE_NOT_IN_PAGE_FLAGS kidled_reset(!scan_control.duration); #else kidled_reset(); #endif } - if (!scan_control.duration) + if (!scan_control.duration) { static_branch_disable(&kidled_enabled_key); + if (atomic_cmpxchg(&kidled_disabling, 1, 0) != 1) + pr_warn_ratelimited("%s: kidled_disabling may be not set correctly when disabling kidled\n", __func__); + } *p = scan_control; *new = true; @@ -1118,8 +1126,19 @@ static ssize_t kidled_scan_period_store(struct kobject *kobj, * To avoid situation like lru_gen >= 0 && kidled disabled, disable * enabled_key after reset. */ - if (secs) + if (secs) { + if (atomic_read(&kidled_disabling)) { + pr_warn("%s: Failed to enable kidled due to kidled is disabling\n", __func__); + ret = -EINVAL; + goto out; + } static_branch_enable(&kidled_enabled_key); + } else { + if (atomic_cmpxchg(&kidled_disabling, 0, 1) != 0) { + pr_debug("%s: kidled is still being disabled, ignore this time\n", __func__); + goto out; + } + } kidled_set_scan_duration(secs); wake_up_interruptible(&kidled_wait); -- Gitee