Skip to content

Commit cb825c2

Browse files
sjp38gregkh
authored andcommitted
mm/damon/stat: detect and use fresh enabled value
commit f98590b upstream. 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: 369c415 ("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> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent bb17039 commit cb825c2

1 file changed

Lines changed: 20 additions & 10 deletions

File tree

mm/damon/stat.c

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,17 @@
1919
static int damon_stat_enabled_store(
2020
const char *val, const struct kernel_param *kp);
2121

22+
static int damon_stat_enabled_load(char *buffer,
23+
const struct kernel_param *kp);
24+
2225
static const struct kernel_param_ops enabled_param_ops = {
2326
.set = damon_stat_enabled_store,
24-
.get = param_get_bool,
27+
.get = damon_stat_enabled_load,
2528
};
2629

2730
static bool enabled __read_mostly = IS_ENABLED(
2831
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);
3033
MODULE_PARM_DESC(enabled, "Enable of disable DAMON_STAT");
3134

3235
static unsigned long estimated_memory_bandwidth __read_mostly;
@@ -265,17 +268,23 @@ static void damon_stat_stop(void)
265268
damon_stat_context = NULL;
266269
}
267270

271+
static bool damon_stat_enabled(void)
272+
{
273+
if (!damon_stat_context)
274+
return false;
275+
return damon_is_running(damon_stat_context);
276+
}
277+
268278
static int damon_stat_enabled_store(
269279
const char *val, const struct kernel_param *kp)
270280
{
271-
bool is_enabled = enabled;
272281
int err;
273282

274283
err = kstrtobool(val, &enabled);
275284
if (err)
276285
return err;
277286

278-
if (is_enabled == enabled)
287+
if (damon_stat_enabled() == enabled)
279288
return 0;
280289

281290
if (!damon_initialized())
@@ -285,16 +294,17 @@ static int damon_stat_enabled_store(
285294
*/
286295
return 0;
287296

288-
if (enabled) {
289-
err = damon_stat_start();
290-
if (err)
291-
enabled = false;
292-
return err;
293-
}
297+
if (enabled)
298+
return damon_stat_start();
294299
damon_stat_stop();
295300
return 0;
296301
}
297302

303+
static int damon_stat_enabled_load(char *buffer, const struct kernel_param *kp)
304+
{
305+
return sprintf(buffer, "%c\n", damon_stat_enabled() ? 'Y' : 'N');
306+
}
307+
298308
static int __init damon_stat_init(void)
299309
{
300310
int err = 0;

0 commit comments

Comments
 (0)