diff --git a/include/linux/vmpressure.h b/include/linux/vmpressure.h index f62cf53b9d92..3838a24dd598 100644 --- a/include/linux/vmpressure.h +++ b/include/linux/vmpressure.h @@ -11,6 +11,7 @@ struct vmpressure { unsigned long scanned; unsigned long reclaimed; + unsigned long stall; /* The lock is used to keep the scanned/reclaimed above in sync. */ struct mutex sr_lock; diff --git a/mm/vmpressure.c b/mm/vmpressure.c index bcc32fab7807..e3f8d21489a4 100644 --- a/mm/vmpressure.c +++ b/mm/vmpressure.c @@ -23,6 +23,7 @@ #include #include #include +#include #include /* @@ -50,6 +51,10 @@ static const unsigned long vmpressure_win = SWAP_CLUSTER_MAX * 16; static const unsigned int vmpressure_level_med = 60; static const unsigned int vmpressure_level_critical = 95; +static unsigned long vmpressure_scale_max = 100; +module_param_named(vmpressure_scale_max, vmpressure_scale_max, + ulong, S_IRUGO | S_IWUSR); + static struct vmpressure global_vmpressure; BLOCKING_NOTIFIER_HEAD(vmpressure_notifier); @@ -166,6 +171,15 @@ static unsigned long vmpressure_calc_pressure(unsigned long scanned, return pressure; } +static unsigned long vmpressure_account_stall(unsigned long pressure, + unsigned long stall, unsigned long scanned) +{ + unsigned long scale = + ((vmpressure_scale_max - pressure) * stall) / scanned; + + return pressure + scale; +} + struct vmpressure_event { struct eventfd_ctx *efd; enum vmpressure_levels level; @@ -279,6 +293,7 @@ void vmpressure_global(gfp_t gfp, unsigned long scanned, { struct vmpressure *vmpr = &global_vmpressure; unsigned long pressure; + unsigned long stall; if (!(gfp & (__GFP_HIGHMEM | __GFP_MOVABLE | __GFP_IO | __GFP_FS))) return; @@ -289,6 +304,11 @@ void vmpressure_global(gfp_t gfp, unsigned long scanned, mutex_lock(&vmpr->sr_lock); vmpr->scanned += scanned; vmpr->reclaimed += reclaimed; + + if (!current_is_kswapd()) + vmpr->stall += scanned; + + stall = vmpr->stall; scanned = vmpr->scanned; reclaimed = vmpr->reclaimed; mutex_unlock(&vmpr->sr_lock); @@ -299,9 +319,11 @@ void vmpressure_global(gfp_t gfp, unsigned long scanned, mutex_lock(&vmpr->sr_lock); vmpr->scanned = 0; vmpr->reclaimed = 0; + vmpr->stall = 0; mutex_unlock(&vmpr->sr_lock); pressure = vmpressure_calc_pressure(scanned, reclaimed); + pressure = vmpressure_account_stall(pressure, stall, scanned); vmpressure_notify(pressure); }