From a0baf92baeee2695fc29b067f7b87e6d85cfface Mon Sep 17 00:00:00 2001 From: Vinayak Menon Date: Tue, 31 Mar 2015 11:06:29 +0530 Subject: [PATCH] mm: vmpressure: scale pressure based on reclaim context The existing calculation of vmpressure takes into account only the ratio of reclaimed to scanned pages, but not the time spent or the difficulty in reclaiming those pages. For e.g. when there are quite a number of file pages in the system, an allocation request can be satisfied by reclaiming the file pages alone. If such a reclaim is succesful, the vmpressure value will remain low irrespective of the time spent by the reclaim code to free up the file pages. With a feature like lowmemorykiller, killing a task can be faster than reclaiming the file pages alone. So if the vmpressure values reflect the reclaim difficulty level, clients can make a decision based on that, for e.g. to kill a task early. This patch monitors the number of pages scanned in the direct reclaim path and scales the vmpressure level according to that. Signed-off-by: Vinayak Menon Change-Id: I6e643d29a9a1aa0814309253a8b690ad86ec0b13 --- include/linux/vmpressure.h | 1 + mm/vmpressure.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) 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); }