summaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
authorVinayak Menon <vinmenon@codeaurora.org>2015-03-31 11:06:29 +0530
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-22 11:03:51 -0700
commit0a8bf43567ab42f45f17773e53d623d746961743 (patch)
tree9189ea4c59a2d6ab7f15979adfcd4d06c95912b2 /mm
parentfb880fe5d174329d2172c854033a3f6b99f52940 (diff)
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 successful, 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 <vinmenon@codeaurora.org> Change-Id: I6e643d29a9a1aa0814309253a8b690ad86ec0b13
Diffstat (limited to 'mm')
-rw-r--r--mm/vmpressure.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/mm/vmpressure.c b/mm/vmpressure.c
index 0801e12fc3b7..b843993a9a7c 100644
--- a/mm/vmpressure.c
+++ b/mm/vmpressure.c
@@ -24,6 +24,7 @@
#include <linux/printk.h>
#include <linux/notifier.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/vmpressure.h>
/*
@@ -51,6 +52,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);
@@ -157,6 +162,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;
@@ -272,6 +286,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;
@@ -282,6 +297,11 @@ void vmpressure_global(gfp_t gfp, unsigned long scanned,
spin_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;
spin_unlock(&vmpr->sr_lock);
@@ -292,9 +312,11 @@ void vmpressure_global(gfp_t gfp, unsigned long scanned,
spin_lock(&vmpr->sr_lock);
vmpr->scanned = 0;
vmpr->reclaimed = 0;
+ vmpr->stall = 0;
spin_unlock(&vmpr->sr_lock);
pressure = vmpressure_calc_pressure(scanned, reclaimed);
+ pressure = vmpressure_account_stall(pressure, stall, scanned);
vmpressure_notify(pressure);
}