mm/damon/core: Fix fake load reports due to uninterruptible sleeps
Subsystems (4)
SeongJae Park
maintainercover mm/damon/core: Fix fake load reports due to uninterruptible sleeps
This patchset is a backport of DAMON fixes that merged in the mainline, for v5.15.x stable series.
SeongJae Park (2):
timers: implement usleep_idle_range()
mm/damon/core: fix fake load reports due to uninterruptible sleeps
include/linux/delay.h | 14 +++++++++++++- kernel/time/timer.c | 16 +++++++++------- mm/damon/core.c | 14 +++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-)
Signature · 1 line
2.17.1
SeongJae Park
maintainerPATCH 1/2 timers: implement usleep_idle_range()
commit e4779015fd5d2fb8390c258268addff24d6077c7 upstream.
Patch series "mm/damon: Fix fake /proc/loadavg reports", v3.
This patchset fixes DAMON's fake load report issue. The first patch makes yet another variant of usleep_range() for this fix, and the second patch fixes the issue of DAMON by making it using the newly introduced function.
This patch (of 2):
Some kernel threads such as DAMON could need to repeatedly sleep in micro seconds level. Because usleep_range() sleeps in uninterruptible state, however, such threads would make /proc/loadavg reports fake load.
To help such cases, this commit implements a variant of usleep_range() called usleep_idle_range(). It is same to usleep_range() but sets the state of the current task as TASK_IDLE while sleeping.
--- include/linux/delay.h | 14 +++++++++++++- kernel/time/timer.c | 16 +++++++++------- 2 files changed, 22 insertions(+), 8 deletions(-)
include/linux/delay.h +13 -1
@@ -20,6 +20,7 @@*/ #include <linux/kernel.h> +#include <linux/sched.h> extern unsigned long loops_per_jiffy;
@@ -58,7 +59,18 @@ void calibrate_delay(void);void __attribute__((weak))calibration_delay_done (void );void msleep (unsigned int msecs);unsigned long msleep_interruptible (unsigned int msecs); -void usleep_range (unsigned long min,unsigned long max); +void usleep_range_state (unsigned long min,unsigned long max, +unsigned int state); + +static inline void usleep_range (unsigned long min,unsigned long max) +{ +usleep_range_state (min, max,TASK_UNINTERRUPTIBLE ); +} + +static inline void usleep_idle_range (unsigned long min,unsigned long max) +{ +usleep_range_state (min, max,TASK_IDLE ); +}static inline void ssleep (unsigned int seconds) {
kernel/time/timer.c +9 -7
@@ -2054,26 +2054,28 @@ unsigned long msleep_interruptible(unsigned int msecs)EXPORT_SYMBOL (msleep_interruptible);/** -* usleep_range - Sleep for an approximate time -* @min: Minimum time in usecs to sleep -* @max: Maximum time in usecs to sleep +* usleep_range_state - Sleep for an approximate time in a given state +* @min: Minimum time in usecs to sleep +* @max: Maximum time in usecs to sleep +* @state: State of the current task that will be while sleeping * * In non-atomic context where the exact wakeup time is flexible, use -* usleep_range() instead of udelay(). The sleep improves responsiveness +* usleep_range_state() instead of udelay(). The sleep improves responsiveness * by avoiding the CPU-hogging busy-wait of udelay(), and the range reduces * power usage by allowing hrtimers to take advantage of an already- * scheduled interrupt instead of scheduling a new one just for this sleep. */ -void __sched usleep_range(unsigned long min, unsigned long max) +void __sched usleep_range_state(unsigned long min, unsigned long max, +unsigned int state) {ktime_t exp =ktime_add_us (ktime_get (), min);u64 delta = (u64)(max - min) *NSEC_PER_USEC ;for (;;) { -__set_current_state (TASK_UNINTERRUPTIBLE ); +__set_current_state (state);/* Do not return before the requested sleep time has elapsed */ if (!schedule_hrtimeout_range (&exp, delta,HRTIMER_MODE_ABS ))break ; } } -EXPORT_SYMBOL (usleep_range); +EXPORT_SYMBOL (usleep_range_state);
Signature · 1 line
2.17.1
SeongJae Park
maintainerPATCH 2/2 mm/damon/core: fix fake load reports due to uninterruptible sleeps
In reply to SeongJae Parkcommit 70e9274805fccfd175d0431a947bfd11ee7df40e upstream.
Because DAMON sleeps in uninterruptible mode, /proc/loadavg reports fake load while DAMON is turned on, though it is doing nothing. This can confuse users[1]. To avoid the case, this commit makes DAMON sleeps in idle mode.
[1] https://lore.kernel.org/all/[email protected]/
--- mm/damon/core.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
mm/damon/core.c +11 -3
@@ -357,6 +357,15 @@ int damon_start(struct damon_ctx **ctxs, int nr_ctxs)return err; } +static void kdamond_usleep (unsigned long usecs) +{ +/* See Documentation/timers/timers-howto.rst for the thresholds */ +if (usecs >20 *1000 ) +schedule_timeout_idle (usecs_to_jiffies (usecs)); +else +usleep_idle_range (usecs, usecs +1 ); +} +/* * __damon_stop() - Stops monitoring of given context. * @ctx: monitoring context
@@ -370,8 +379,7 @@ static int __damon_stop(struct damon_ctx *ctx) ctx->kdamond_stop = true;mutex_unlock (&ctx->kdamond_lock);while (damon_kdamond_running (ctx)) -usleep_range (ctx->sample_interval, - ctx->sample_interval *2 ); +kdamond_usleep (ctx->sample_interval);return 0 ; }mutex_unlock (&ctx->kdamond_lock);
@@ -670,7 +678,7 @@ static int kdamond_fn(void *data) ctx->callback.after_sampling(ctx))set_kdamond_stop (ctx); -usleep_range (ctx->sample_interval, ctx->sample_interval +1 ); +kdamond_usleep (ctx->sample_interval);if (ctx->primitive.check_accesses) max_nr_accesses = ctx->primitive.check_accesses (ctx);
Signature · 1 line
2.17.1
Greg KH
maintainerQuoted 15 lines · SeongJae Park
This patchset is a backport of DAMON fixes that merged in the mainline, for v5.15.x stable series.
SeongJae Park (2):
timers: implementusleep_idle_range()
mm/damon/core: fix fake load reports due to uninterruptible sleepsinclude/linux/delay.h | 14 +++++++++++++- kernel/time/timer.c | 16 +++++++++------- mm/damon/core.c | 14 +++++++++++--- 3 files changed, 33 insertions(+), 11 deletions(-)Signature · 1 line
2.17.1
All now queued up, thanks!
greg k-h