From: Greg Kroah-Hartman Date: Tue, 16 Jun 2026 12:06:46 +0000 (+0530) Subject: 6.1-stable patches X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bfd96c6b3f06049bbb4300b35d311fd20647a709;p=thirdparty%2Fkernel%2Fstable-queue.git 6.1-stable patches added patches: drm-v3d-reject-empty-multisync-extension-to-prevent-infinite-loop.patch ipmi-ssif-null-thread-on-error.patch ipmi-ssif-remove-unnecessary-indention.patch mm-damon-core-implement-damon_kdamond_pid.patch mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch --- diff --git a/queue-6.1/drm-v3d-reject-empty-multisync-extension-to-prevent-infinite-loop.patch b/queue-6.1/drm-v3d-reject-empty-multisync-extension-to-prevent-infinite-loop.patch new file mode 100644 index 0000000000..773d7e5454 --- /dev/null +++ b/queue-6.1/drm-v3d-reject-empty-multisync-extension-to-prevent-infinite-loop.patch @@ -0,0 +1,56 @@ +From fb44d589bf3148e13452185a6e772a7efbf2d684 Mon Sep 17 00:00:00 2001 +From: Ashutosh Desai +Date: Wed, 15 Apr 2026 05:00:00 +0000 +Subject: drm/v3d: Reject empty multisync extension to prevent infinite loop +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ashutosh Desai + +commit fb44d589bf3148e13452185a6e772a7efbf2d684 upstream. + +v3d_get_extensions() walks a userspace-provided singly-linked list of +ioctl extensions without any bound on the chain length. A local user +can craft a self-referential extension (ext->next == &ext) with zero +in_sync_count and out_sync_count, which bypasses the existing duplicate- +extension guard: + + if (se->in_sync_count || se->out_sync_count) + return -EINVAL; + +The guard never fires because v3d_get_multisync_post_deps() returns +immediately when count is zero, leaving both fields at zero on every +iteration. The result is an infinite loop in kernel context, blocking +the calling thread and pegging a CPU core indefinitely. + +Fix this by rejecting a multisync extension where both in_sync_count +and out_sync_count are zero in v3d_get_multisync_submit_deps(). An +empty multisync carries no synchronization information and serves no +useful purpose, so returning -EINVAL for such an extension is the +correct defense against this attack vector. + +Fixes: e4165ae8304e ("drm/v3d: add multiple syncobjs support") +Cc: stable@vger.kernel.org +Signed-off-by: Ashutosh Desai +Link: https://patch.msgid.link/20260415050000.3816128-1-ashutoshdesai993@gmail.com +Signed-off-by: Maíra Canal +Signed-off-by: Greg Kroah-Hartman +--- + drivers/gpu/drm/v3d/v3d_gem.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/gpu/drm/v3d/v3d_gem.c ++++ b/drivers/gpu/drm/v3d/v3d_gem.c +@@ -649,6 +649,11 @@ v3d_get_multisync_submit_deps(struct drm + if (multisync.pad) + return -EINVAL; + ++ if (!multisync.in_sync_count && !multisync.out_sync_count) { ++ DRM_DEBUG("Empty multisync extension\n"); ++ return -EINVAL; ++ } ++ + ret = v3d_get_multisync_post_deps(file_priv, data, multisync.out_sync_count, + multisync.out_syncs); + if (ret) diff --git a/queue-6.1/ipmi-ssif-null-thread-on-error.patch b/queue-6.1/ipmi-ssif-null-thread-on-error.patch new file mode 100644 index 0000000000..456ea74b7b --- /dev/null +++ b/queue-6.1/ipmi-ssif-null-thread-on-error.patch @@ -0,0 +1,34 @@ +From a8aebe93a4938c0ca1941eeaae821738f869be3d Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Tue, 21 Apr 2026 06:50:22 -0500 +Subject: ipmi:ssif: NULL thread on error + +From: Corey Minyard + +commit a8aebe93a4938c0ca1941eeaae821738f869be3d upstream. + +Cleanup code was checking the thread for NULL, but it was possibly +a PTR_ERR() in one spot. + +Spotted with static analysis. + +Link: https://sourceforge.net/p/openipmi/mailman/message/59324676/ +Fixes: 75c486cb1bca ("ipmi:ssif: Clean up kthread on errors") +Cc: # 91eb7ec72612: ipmi:ssif: Remove unnecessary indention +Cc: stable@vger.kernel.org +Signed-off-by: Corey Minyard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/ipmi/ipmi_ssif.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -1886,6 +1886,7 @@ static int ssif_probe(struct i2c_client + "kssif%4.4x", thread_num); + if (IS_ERR(ssif_info->thread)) { + rv = PTR_ERR(ssif_info->thread); ++ ssif_info->thread = NULL; + dev_notice(&ssif_info->client->dev, + "Could not start kernel thread: error %d\n", + rv); diff --git a/queue-6.1/ipmi-ssif-remove-unnecessary-indention.patch b/queue-6.1/ipmi-ssif-remove-unnecessary-indention.patch new file mode 100644 index 0000000000..2a07c45c8d --- /dev/null +++ b/queue-6.1/ipmi-ssif-remove-unnecessary-indention.patch @@ -0,0 +1,62 @@ +From 91eb7ec7261254b6875909df767185838598e21e Mon Sep 17 00:00:00 2001 +From: Corey Minyard +Date: Mon, 13 Apr 2026 07:09:15 -0500 +Subject: ipmi:ssif: Remove unnecessary indention + +From: Corey Minyard + +commit 91eb7ec7261254b6875909df767185838598e21e upstream. + +A section was in {} that didn't need to be, move the variable +definition to the top and set th eindentino properly. + +Signed-off-by: Corey Minyard +Signed-off-by: Greg Kroah-Hartman +--- + drivers/char/ipmi/ipmi_ssif.c | 28 ++++++++++++---------------- + 1 file changed, 12 insertions(+), 16 deletions(-) + +--- a/drivers/char/ipmi/ipmi_ssif.c ++++ b/drivers/char/ipmi/ipmi_ssif.c +@@ -1670,6 +1670,7 @@ static int ssif_probe(struct i2c_client + int len = 0; + int i; + u8 slave_addr = 0; ++ unsigned int thread_num; + struct ssif_addr_info *addr_info = NULL; + + mutex_lock(&ssif_infos_mutex); +@@ -1878,22 +1879,17 @@ static int ssif_probe(struct i2c_client + ssif_info->handlers.request_events = request_events; + ssif_info->handlers.set_need_watch = ssif_set_need_watch; + +- { +- unsigned int thread_num; +- +- thread_num = ((i2c_adapter_id(ssif_info->client->adapter) +- << 8) | +- ssif_info->client->addr); +- init_completion(&ssif_info->wake_thread); +- ssif_info->thread = kthread_run(ipmi_ssif_thread, ssif_info, +- "kssif%4.4x", thread_num); +- if (IS_ERR(ssif_info->thread)) { +- rv = PTR_ERR(ssif_info->thread); +- dev_notice(&ssif_info->client->dev, +- "Could not start kernel thread: error %d\n", +- rv); +- goto out; +- } ++ thread_num = ((i2c_adapter_id(ssif_info->client->adapter) << 8) | ++ ssif_info->client->addr); ++ init_completion(&ssif_info->wake_thread); ++ ssif_info->thread = kthread_run(ipmi_ssif_thread, ssif_info, ++ "kssif%4.4x", thread_num); ++ if (IS_ERR(ssif_info->thread)) { ++ rv = PTR_ERR(ssif_info->thread); ++ dev_notice(&ssif_info->client->dev, ++ "Could not start kernel thread: error %d\n", ++ rv); ++ goto out; + } + + dev_set_drvdata(&ssif_info->client->dev, ssif_info); diff --git a/queue-6.1/mm-damon-core-implement-damon_kdamond_pid.patch b/queue-6.1/mm-damon-core-implement-damon_kdamond_pid.patch new file mode 100644 index 0000000000..2c2bbf4d4b --- /dev/null +++ b/queue-6.1/mm-damon-core-implement-damon_kdamond_pid.patch @@ -0,0 +1,86 @@ +From 4262c53236977de3ceaa3bf2aefdf772c9b874dd Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Thu, 15 Jan 2026 07:20:41 -0800 +Subject: mm/damon/core: implement damon_kdamond_pid() + +From: SeongJae Park + +commit 4262c53236977de3ceaa3bf2aefdf772c9b874dd upstream. + +Patch series "mm/damon: hide kdamond and kdamond_lock from API callers". + +'kdamond' and 'kdamond_lock' fields initially exposed to DAMON API callers +for flexible synchronization and use cases. As DAMON API became somewhat +complicated compared to the early days, Keeping those exposed could only +encourage the API callers to invent more creative but complicated and +difficult-to-debug use cases. + +Fortunately DAMON API callers didn't invent that many creative use cases. +There exist only two use cases of 'kdamond' and 'kdamond_lock'. Finding +whether the kdamond is actively running, and getting the pid of the +kdamond. For the first use case, a dedicated API function, namely +'damon_is_running()' is provided, and all DAMON API callers are using the +function for the use case. Hence only the second use case is where the +fields are directly being used by DAMON API callers. + +To prevent future invention of complicated and erroneous use cases of the +fields, hide the fields from the API callers. For that, provide new +dedicated DAMON API functions for the remaining use case, namely +damon_kdamond_pid(), migrate DAMON API callers to use the new function, +and mark the fields as private fields. + + +This patch (of 5): + +'kdamond' and 'kdamond_lock' are directly being used by DAMON API callers +for getting the pid of the corresponding kdamond. To discourage invention +of creative but complicated and erroneous new usages of the fields that +require careful synchronization, implement a new API function that can +simply be used without the manual synchronizations. + +Link: https://lkml.kernel.org/r/20260115152047.68415-1-sj@kernel.org +Link: https://lkml.kernel.org/r/20260115152047.68415-2-sj@kernel.org +Signed-off-by: SeongJae Park +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/damon.h | 1 + + mm/damon/core.c | 17 +++++++++++++++++ + 2 files changed, 18 insertions(+) + +--- a/include/linux/damon.h ++++ b/include/linux/damon.h +@@ -572,6 +572,7 @@ static inline unsigned int damon_max_nr_ + + int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive); + int damon_stop(struct damon_ctx **ctxs, int nr_ctxs); ++int damon_kdamond_pid(struct damon_ctx *ctx); + + int damon_set_region_biggest_system_ram_default(struct damon_target *t, + unsigned long *start, unsigned long *end); +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -643,6 +643,23 @@ static bool damon_check_reset_time_inter + return true; + } + ++/** ++ * damon_kdamond_pid() - Return pid of a given DAMON context's worker thread. ++ * @ctx: The DAMON context of the question. ++ * ++ * Return: pid if @ctx is running, negative error code otherwise. ++ */ ++int damon_kdamond_pid(struct damon_ctx *ctx) ++{ ++ int pid = -EINVAL; ++ ++ mutex_lock(&ctx->kdamond_lock); ++ if (ctx->kdamond) ++ pid = ctx->kdamond->pid; ++ mutex_unlock(&ctx->kdamond_lock); ++ return pid; ++} ++ + /* + * Check whether it is time to flush the aggregated information + */ diff --git a/queue-6.1/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch b/queue-6.1/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch new file mode 100644 index 0000000000..7cb8752572 --- /dev/null +++ b/queue-6.1/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch @@ -0,0 +1,249 @@ +From b98b7ff6025ae82570d4915e083f0cbd8d48b3cf Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Sun, 19 Apr 2026 09:10:01 -0700 +Subject: mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values + +From: SeongJae Park + +commit b98b7ff6025ae82570d4915e083f0cbd8d48b3cf upstream. + +DAMON_LRU_SORT updates 'enabled' and 'kdamond_pid' parameter values, which +represents the running status of its kdamond, when the user explicitly +requests start/stop of the kdamond. The kdamond can, however, be stopped +in events other than the explicit user request in the following three +events. + +1. ctx->regions_score_histogram allocation failure at beginning of the + execution, +2. damon_commit_ctx() failure due to invalid user input, and +3. damon_commit_ctx() failure due to its internal allocation failures. + +Hence, if the kdamond is stopped by the above three events, the values of +the status parameters can be stale. Users could show the stale values and +be confused. This is already bad, but the real consequence is worse. +DAMON_LRU_SORT avoids unnecessary damon_start() and damon_stop() calls +based on the 'enabled' parameter value. And the update of 'enabled' +parameter value depends on the damon_start() and damon_stop() call +results. Hence, once the kdamond has stopped by the unintentional events, +the user cannot restart the kdamond before the system reboot. For +example, the issue can be reproduced via below steps. + + # cd /sys/module/damon_lru_sort/parameters + # + # # start DAMON_LRU_SORT + # echo Y > enabled + # ps -ef | grep kdamond + root 806 2 0 17:53 ? 00:00:00 [kdamond.0] + root 808 803 0 17:53 pts/4 00:00:00 grep kdamond + # + # # commit wrong input to stop kdamond withou explicit stop request + # echo 3 > addr_unit + # echo Y > commit_inputs + bash: echo: write error: Invalid argument + # + # # confirm kdamond is stopped + # ps -ef | grep kdamond + root 811 803 0 17:53 pts/4 00:00:00 grep kdamond + # + # # users casn now show stable status + # cat enabled + Y + # cat kdamond_pid + 806 + # + # # even after fixing the wrong parameter, + # # kdamond cannot be restarted. + # echo 1 > addr_unit + # echo Y > enabled + # ps -ef | grep kdamond + root 815 803 0 17:54 pts/4 00:00:00 grep kdamond + +The problem will only rarely happen in real and common setups for the +following reasons. The allocation failures are unlikely in such setups +since those allocations are arguably too small to fail. Also sane users +on real production environments may not commit wrong input parameters. +But once it happens, the consequence is quite bad. And the bug is a bug. + +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. + +Link: https://lore.kernel.org/20260419161003.79176-3-sj@kernel.org +Fixes: 40e983cca927 ("mm/damon: introduce DAMON-based LRU-lists Sorting") +Co-developed-by: Liew Rui Yan +Signed-off-by: Liew Rui Yan +Signed-off-by: SeongJae Park +Cc: # 6.0.x +Signed-off-by: Andrew Morton +Signed-off-by: SeongJae Park +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/damon.h | 1 + mm/damon/core.c | 16 +++++++++ + mm/damon/lru_sort.c | 84 +++++++++++++++++++++++++++++++++----------------- + 3 files changed, 73 insertions(+), 28 deletions(-) + +--- a/include/linux/damon.h ++++ b/include/linux/damon.h +@@ -572,6 +572,7 @@ static inline unsigned int damon_max_nr_ + + int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive); + int damon_stop(struct damon_ctx **ctxs, int nr_ctxs); ++bool damon_is_running(struct damon_ctx *ctx); + int damon_kdamond_pid(struct damon_ctx *ctx); + + int damon_set_region_biggest_system_ram_default(struct damon_target *t, +--- a/mm/damon/core.c ++++ b/mm/damon/core.c +@@ -644,6 +644,22 @@ static bool damon_check_reset_time_inter + } + + /** ++ * damon_is_running() - Returns if a given DAMON context is running. ++ * @ctx: The DAMON context to see if running. ++ * ++ * Return: true if @ctx is running, false otherwise. ++ */ ++bool damon_is_running(struct damon_ctx *ctx) ++{ ++ bool running; ++ ++ mutex_lock(&ctx->kdamond_lock); ++ running = ctx->kdamond != NULL; ++ mutex_unlock(&ctx->kdamond_lock); ++ return running; ++} ++ ++/** + * damon_kdamond_pid() - Return pid of a given DAMON context's worker thread. + * @ctx: The DAMON context of the question. + * +--- a/mm/damon/lru_sort.c ++++ b/mm/damon/lru_sort.c +@@ -113,15 +113,6 @@ module_param(monitor_region_start, ulong + static unsigned long monitor_region_end __read_mostly; + module_param(monitor_region_end, ulong, 0600); + +-/* +- * PID of the DAMON thread +- * +- * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread. +- * Else, -1. +- */ +-static int kdamond_pid __read_mostly = -1; +-module_param(kdamond_pid, int, 0400); +- + static struct damos_stat damon_lru_sort_hot_stat; + DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat, + lru_sort_tried_hot_regions, lru_sorted_hot_regions, +@@ -249,37 +240,32 @@ static int damon_lru_sort_turn(bool on) + { + int err; + +- if (!on) { +- err = damon_stop(&ctx, 1); +- if (!err) +- kdamond_pid = -1; +- return err; +- } ++ if (!on) ++ return damon_stop(&ctx, 1); + + err = damon_lru_sort_apply_parameters(); + if (err) + return err; + +- err = damon_start(&ctx, 1, true); +- if (err) +- return err; +- kdamond_pid = ctx->kdamond->pid; +- return 0; ++ return damon_start(&ctx, 1, true); ++} ++ ++static bool damon_lru_sort_enabled(void) ++{ ++ if (!ctx) ++ return false; ++ return damon_is_running(ctx); + } + + static struct delayed_work damon_lru_sort_timer; + static void damon_lru_sort_timer_fn(struct work_struct *work) + { +- static bool last_enabled; + bool now_enabled; + + now_enabled = enabled; +- if (last_enabled != now_enabled) { +- if (!damon_lru_sort_turn(now_enabled)) +- last_enabled = now_enabled; +- else +- enabled = last_enabled; +- } ++ if (damon_lru_sort_enabled() == now_enabled) ++ return; ++ damon_lru_sort_turn(now_enabled); + } + static DECLARE_DELAYED_WORK(damon_lru_sort_timer, damon_lru_sort_timer_fn); + +@@ -301,15 +287,57 @@ static int damon_lru_sort_enabled_store( + return 0; + } + ++static int damon_lru_sort_enabled_load(char *buffer, ++ const struct kernel_param *kp) ++{ ++ return sprintf(buffer, "%c\n", damon_lru_sort_enabled() ? 'Y' : 'N'); ++} ++ + static const struct kernel_param_ops enabled_param_ops = { + .set = damon_lru_sort_enabled_store, +- .get = param_get_bool, ++ .get = damon_lru_sort_enabled_load, + }; + + module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); + MODULE_PARM_DESC(enabled, + "Enable or disable DAMON_LRU_SORT (default: disabled)"); + ++static int damon_lru_sort_kdamond_pid_store(const char *val, ++ const struct kernel_param *kp) ++{ ++ /* ++ * kdamond_pid is read-only, but kernel command line could write it. ++ * Do nothing here. ++ */ ++ return 0; ++} ++ ++static int damon_lru_sort_kdamond_pid_load(char *buffer, ++ const struct kernel_param *kp) ++{ ++ int kdamond_pid = -1; ++ ++ if (ctx) { ++ kdamond_pid = damon_kdamond_pid(ctx); ++ if (kdamond_pid < 0) ++ kdamond_pid = -1; ++ } ++ return sprintf(buffer, "%d\n", kdamond_pid); ++} ++ ++static const struct kernel_param_ops kdamond_pid_param_ops = { ++ .set = damon_lru_sort_kdamond_pid_store, ++ .get = damon_lru_sort_kdamond_pid_load, ++}; ++ ++/* ++ * PID of the DAMON thread ++ * ++ * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread. ++ * Else, -1. ++ */ ++module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400); ++ + static int damon_lru_sort_handle_commit_inputs(void) + { + int err; diff --git a/queue-6.1/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch b/queue-6.1/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch new file mode 100644 index 0000000000..a65d51caa8 --- /dev/null +++ b/queue-6.1/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch @@ -0,0 +1,233 @@ +From 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339 Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Sun, 19 Apr 2026 09:10:00 -0700 +Subject: mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values + +From: SeongJae Park + +commit 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339 upstream. + +Patch series "mm/damon/modules: detect and use fresh status", v3. + +DAMON modules including DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT +commonly expose the kdamond running status via their parameters. Under +certain scenarios including wrong user inputs and memory allocation +failures, those parameter values can be stale. It can confuse users. For +DAMON_RECLAIM and DAMON_LRU_SORT, it even makes the kdamond unable to be +restarted before the system reboot. + +The problem comes from the fact that there are multiple events for the +status changes and it is difficult to follow up all the scenarios. Fix +the issue by detecting and using the status on demand, instead of using a +cached status that is difficult to be updated. + +Patches 1-3 fix the bugs in DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT +in the order. + + +This patch (of 3): + +DAMON_RECLAIM updates 'enabled' and 'kdamond_pid' parameter values, which +represents the running status of its kdamond, when the user explicitly +requests start/stop of the kdamond. The kdamond can, however, be stopped +in events other than the explicit user request in the following three +events. + +1. ctx->regions_score_histogram allocation failure at beginning of the + execution, +2. damon_commit_ctx() failure due to invalid user input, and +3. damon_commit_ctx() failure due to its internal allocation failures. + +Hence, if the kdamond is stopped by the above three events, the values of +the status parameters can be stale. Users could show the stale values and +be confused. This is already bad, but the real consequence is worse. +DAMON_RECLAIM avoids unnecessary damon_start() and damon_stop() calls +based on the 'enabled' parameter value. And the update of 'enabled' +parameter value depends on the damon_start() and damon_stop() call +results. Hence, once the kdamond has stopped by the unintentional events, +the user cannot restart the kdamond before the system reboot. For +example, the issue can be reproduced via below steps. + + # cd /sys/module/damon_reclaim/parameters + # + # # start DAMON_RECLAIM + # echo Y > enabled + # ps -ef | grep kdamond + root 806 2 0 17:53 ? 00:00:00 [kdamond.0] + root 808 803 0 17:53 pts/4 00:00:00 grep kdamond + # + # # commit wrong input to stop kdamond withou explicit stop request + # echo 3 > addr_unit + # echo Y > commit_inputs + bash: echo: write error: Invalid argument + # + # # confirm kdamond is stopped + # ps -ef | grep kdamond + root 811 803 0 17:53 pts/4 00:00:00 grep kdamond + # + # # users casn now show stable status + # cat enabled + Y + # cat kdamond_pid + 806 + # + # # even after fixing the wrong parameter, + # # kdamond cannot be restarted. + # echo 1 > addr_unit + # echo Y > enabled + # ps -ef | grep kdamond + root 815 803 0 17:54 pts/4 00:00:00 grep kdamond + +The problem will only rarely happen in real and common setups for the +following reasons. The allocation failures are unlikely in such setups +since those allocations are arguably too small to fail. Also sane users +on real production environments may not commit wrong input parameters. +But once it happens, the consequence is quite bad. And the bug is a bug. + +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. + +Link: https://lore.kernel.org/20260419161003.79176-1-sj@kernel.org +Link: https://lore.kernel.org/20260419161003.79176-2-sj@kernel.org +Fixes: e035c280f6df ("mm/damon/reclaim: support online inputs update") +Co-developed-by: Liew Rui Yan +Signed-off-by: Liew Rui Yan +Signed-off-by: SeongJae Park +Cc: # 5.19.x +Signed-off-by: Andrew Morton +Signed-off-by: SeongJae Park +Signed-off-by: Greg Kroah-Hartman +--- + mm/damon/reclaim.c | 84 +++++++++++++++++++++++++++++++++++------------------ + 1 file changed, 56 insertions(+), 28 deletions(-) + +--- a/mm/damon/reclaim.c ++++ b/mm/damon/reclaim.c +@@ -100,15 +100,6 @@ module_param(monitor_region_start, ulong + static unsigned long monitor_region_end __read_mostly; + module_param(monitor_region_end, ulong, 0600); + +-/* +- * PID of the DAMON thread +- * +- * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. +- * Else, -1. +- */ +-static int kdamond_pid __read_mostly = -1; +-module_param(kdamond_pid, int, 0400); +- + static struct damos_stat damon_reclaim_stat; + DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_reclaim_stat, + reclaim_tried_regions, reclaimed_regions, quota_exceeds); +@@ -184,37 +175,32 @@ static int damon_reclaim_turn(bool on) + { + int err; + +- if (!on) { +- err = damon_stop(&ctx, 1); +- if (!err) +- kdamond_pid = -1; +- return err; +- } ++ if (!on) ++ return damon_stop(&ctx, 1); + + err = damon_reclaim_apply_parameters(); + if (err) + return err; + +- err = damon_start(&ctx, 1, true); +- if (err) +- return err; +- kdamond_pid = ctx->kdamond->pid; +- return 0; ++ return damon_start(&ctx, 1, true); ++} ++ ++static bool damon_reclaim_enabled(void) ++{ ++ if (!ctx) ++ return false; ++ return damon_is_running(ctx); + } + + static struct delayed_work damon_reclaim_timer; + static void damon_reclaim_timer_fn(struct work_struct *work) + { +- static bool last_enabled; + bool now_enabled; + + now_enabled = enabled; +- if (last_enabled != now_enabled) { +- if (!damon_reclaim_turn(now_enabled)) +- last_enabled = now_enabled; +- else +- enabled = last_enabled; +- } ++ if (damon_reclaim_enabled() != now_enabled) ++ return; ++ damon_reclaim_turn(now_enabled); + } + static DECLARE_DELAYED_WORK(damon_reclaim_timer, damon_reclaim_timer_fn); + +@@ -236,15 +222,57 @@ static int damon_reclaim_enabled_store(c + return 0; + } + ++static int damon_reclaim_enabled_load(char *buffer, ++ const struct kernel_param *kp) ++{ ++ return sprintf(buffer, "%c\n", damon_reclaim_enabled() ? 'Y' : 'N'); ++} ++ + static const struct kernel_param_ops enabled_param_ops = { + .set = damon_reclaim_enabled_store, +- .get = param_get_bool, ++ .get = damon_reclaim_enabled_load, + }; + + module_param_cb(enabled, &enabled_param_ops, &enabled, 0600); + MODULE_PARM_DESC(enabled, + "Enable or disable DAMON_RECLAIM (default: disabled)"); + ++static int damon_reclaim_kdamond_pid_store(const char *val, ++ const struct kernel_param *kp) ++{ ++ /* ++ * kdamond_pid is read-only, but kernel command line could write it. ++ * Do nothing here. ++ */ ++ return 0; ++} ++ ++static int damon_reclaim_kdamond_pid_load(char *buffer, ++ const struct kernel_param *kp) ++{ ++ int kdamond_pid = -1; ++ ++ if (ctx) { ++ kdamond_pid = damon_kdamond_pid(ctx); ++ if (kdamond_pid < 0) ++ kdamond_pid = -1; ++ } ++ return sprintf(buffer, "%d\n", kdamond_pid); ++} ++ ++static const struct kernel_param_ops kdamond_pid_param_ops = { ++ .set = damon_reclaim_kdamond_pid_store, ++ .get = damon_reclaim_kdamond_pid_load, ++}; ++ ++/* ++ * PID of the DAMON thread ++ * ++ * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread. ++ * Else, -1. ++ */ ++module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400); ++ + static int damon_reclaim_handle_commit_inputs(void) + { + int err; diff --git a/queue-6.1/series b/queue-6.1/series index 8681530198..f8274a9967 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -504,3 +504,9 @@ mm-damon-core-use-time_in_range_open-for-damos-quota-window-start.patch mm-damon-core-disallow-time-quota-setting-zero-esz.patch usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch lib-crypto-mpi-fix-integer-underflow-in-mpi_read_raw_from_sgl.patch +ipmi-ssif-remove-unnecessary-indention.patch +ipmi-ssif-null-thread-on-error.patch +mm-damon-core-implement-damon_kdamond_pid.patch +mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch +mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch +drm-v3d-reject-empty-multisync-extension-to-prevent-infinite-loop.patch