Skip to content

Commit 31810bb

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 ca85515 commit 31810bb

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;
@@ -273,17 +276,23 @@ static void damon_stat_stop(void)
273276
damon_stat_context = NULL;
274277
}
275278

279+
static bool damon_stat_enabled(void)
280+
{
281+
if (!damon_stat_context)
282+
return false;
283+
return damon_is_running(damon_stat_context);
284+
}
285+
276286
static int damon_stat_enabled_store(
277287
const char *val, const struct kernel_param *kp)
278288
{
279-
bool is_enabled = enabled;
280289
int err;
281290

282291
err = kstrtobool(val, &enabled);
283292
if (err)
284293
return err;
285294

286-
if (is_enabled == enabled)
295+
if (damon_stat_enabled() == enabled)
287296
return 0;
288297

289298
if (!damon_initialized())
@@ -293,16 +302,17 @@ static int damon_stat_enabled_store(
293302
*/
294303
return 0;
295304

296-
if (enabled) {
297-
err = damon_stat_start();
298-
if (err)
299-
enabled = false;
300-
return err;
301-
}
305+
if (enabled)
306+
return damon_stat_start();
302307
damon_stat_stop();
303308
return 0;
304309
}
305310

311+
static int damon_stat_enabled_load(char *buffer, const struct kernel_param *kp)
312+
{
313+
return sprintf(buffer, "%c\n", damon_stat_enabled() ? 'Y' : 'N');
314+
}
315+
306316
static int __init damon_stat_init(void)
307317
{
308318
int err = 0;

0 commit comments

Comments
 (0)