mm/damon: Fix fake /proc/loadavg reports
Subsystems (4)
SeongJae Park
maintainerv3 cover mm/damon: Fix fake /proc/loadavg reports
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.
I think these need to be applied on v5.15.y, but the second patch cannot cleanly applied there as is. I will back-port this on v5.15.y and post later once this is merged in the mainline. If you think this is not appropriate for stable tree, please let me know.
Changelog
---------
From v2
(https://lore.kernel.org/linux-mm/[email protected]/)
- Cc Oleksandr (Oleksandr Natalenko)
- Add 'Suggested-by:' for Andrew Morton on the first patch
From v1
(https://lore.kernel.org/linux-mm/[email protected]/)
- Avoid copy-and-pasting usleep_delay() in DAMON code (Andrew Morton)
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 | 6 +++--- 3 files changed, 25 insertions(+), 11 deletions(-)
Signature · 1 line
2.17.1
SeongJae Park
maintainerPATCH v3 1/2 timers: Implement usleep_idle_range()
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/math.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
Re: [PATCH v3 1/2] timers: Implement usleep_idle_range()
Quoted 10 lines · SeongJae Park
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/loadavgreports fake load.To help such cases, this commit implements a variant of
usleep_range()calledusleep_idle_range(). It is same tousleep_range()but sets the state of the current task asTASK_IDLEwhile sleeping.Suggested-by Andrew Morton <[email protected]>Signed-off-by SeongJae Park <[email protected]>
Andrew, I assume you want to pick that up along with the mm fix, right?
SeongJae Park
maintainerPATCH v3 2/2 mm/damon/core: Fix fake load reports due to uninterruptible sleeps
In reply to SeongJae ParkBecause 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 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/damon/core.c +3 -3
@@ -979,9 +979,9 @@ static unsigned long damos_wmark_wait_us(struct damos *scheme)static void kdamond_usleep (unsigned long usecs) {if (usecs >100 *1000 ) -schedule_timeout_interruptible (usecs_to_jiffies (usecs)); +schedule_timeout_idle (usecs_to_jiffies (usecs));else -usleep_range (usecs, usecs +1 ); +usleep_idle_range (usecs, usecs +1 ); }/* Returns negative error code if it's not activated but should return */
@@ -1036,7 +1036,7 @@ static int kdamond_fn(void *data) ctx->callback.after_sampling(ctx)) done = true; -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
Hello.
Quoted 22 lines · On pátek 26. listopadu 2021 15:50:13 CET SeongJae Park wrote:
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.I think these need to be applied on v5.15.y, but the second patch cannot cleanly applied there as is. I will back-port this on v5.15.y and post later once this is merged in the mainline. If you think this is not appropriate for stable tree, please let me know.
Changelog
---------From v2
(https://lore.kernel.org/linux-mm/[email protected]/)
- Cc Oleksandr (Oleksandr Natalenko)
- Add 'Suggested-by:' for Andrew Morton on the first patchFrom v1
(https://lore.kernel.org/linux-mm/[email protected]/)
- Avoid copy-and-pastingusleep_delay()in DAMON code (Andrew Morton)
Quoted 8 lines
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 | 6 +++--- 3 files changed, 25 insertions(+), 11 deletions(-)
For the series:
Thank you.
Signature · 1 line
Oleksandr Natalenko (post-factum)