Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

mm/damon/stat: detect and use fresh enabled value

DAMON_STAT updates 'enabled' parameter value, which represents the running
status of its kdamond, when the user explicitly requests start/stop of the
kdamond. The kdamond can, however, be stopped even if the user explicitly
requested the stop, if ctx->regions_score_histogram allocation failure at
beginning of the execution of the kdamond. Hence, if the kdamond is
stopped by the allocation failure, the value of the parameter can be
stale.

Users could show the stale value and be confused. The problem will only
rarely happen in real and common setups because the allocation is arguably
too small to fail. Also, unlike the similar bugs that are now fixed in
DAMON_RECLAIM and DAMON_LRU_SORT, kdamond can be restarted in this case,
because DAMON_STAT force-updates the enabled parameter value for user
inputs. The bug is a bug, though.

The issue stems from the fact that there are multiple events that can
change the status, and following all the events is challenging.
Dynamically detect and use the fresh status for the parameters when those
are requested.

The issue was dicovered [1] by Sashiko.

Link: https://lore.kernel.org/20260419161003.79176-4-sj@kernel.org
Link: https://lore.kernel.org/20260416040602.88665-1-sj@kernel.org [1]
Fixes: 369c415e6073 ("mm/damon: introduce DAMON_STAT module")
Signed-off-by: SeongJae Park <sj@kernel.org>
Cc: Liew Rui Yan <aethernet65535@gmail.com>
Cc: <stable@vger.kernel.org> # 6.17.x
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

SeongJae Park and committed by
Andrew Morton
f98590bc b98b7ff6

+20 -10
+20 -10
mm/damon/stat.c
··· 19 19 static int damon_stat_enabled_store( 20 20 const char *val, const struct kernel_param *kp); 21 21 22 + static int damon_stat_enabled_load(char *buffer, 23 + const struct kernel_param *kp); 24 + 22 25 static const struct kernel_param_ops enabled_param_ops = { 23 26 .set = damon_stat_enabled_store, 24 - .get = param_get_bool, 27 + .get = damon_stat_enabled_load, 25 28 }; 26 29 27 30 static bool enabled __read_mostly = IS_ENABLED( 28 31 CONFIG_DAMON_STAT_ENABLED_DEFAULT); 29 - module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); 32 + module_param_cb(enabled, &enabled_param_ops, NULL, 0600); 30 33 MODULE_PARM_DESC(enabled, "Enable of disable DAMON_STAT"); 31 34 32 35 static unsigned long estimated_memory_bandwidth __read_mostly; ··· 276 273 damon_stat_context = NULL; 277 274 } 278 275 276 + static bool damon_stat_enabled(void) 277 + { 278 + if (!damon_stat_context) 279 + return false; 280 + return damon_is_running(damon_stat_context); 281 + } 282 + 279 283 static int damon_stat_enabled_store( 280 284 const char *val, const struct kernel_param *kp) 281 285 { 282 - bool is_enabled = enabled; 283 286 int err; 284 287 285 288 err = kstrtobool(val, &enabled); 286 289 if (err) 287 290 return err; 288 291 289 - if (is_enabled == enabled) 292 + if (damon_stat_enabled() == enabled) 290 293 return 0; 291 294 292 295 if (!damon_initialized()) ··· 302 293 */ 303 294 return 0; 304 295 305 - if (enabled) { 306 - err = damon_stat_start(); 307 - if (err) 308 - enabled = false; 309 - return err; 310 - } 296 + if (enabled) 297 + return damon_stat_start(); 311 298 damon_stat_stop(); 312 299 return 0; 300 + } 301 + 302 + static int damon_stat_enabled_load(char *buffer, const struct kernel_param *kp) 303 + { 304 + return sprintf(buffer, "%c\n", damon_stat_enabled() ? 'Y' : 'N'); 313 305 } 314 306 315 307 static int __init damon_stat_init(void)