Skip to content

Commit

Permalink
mm: vmpressure: scale pressure based on reclaim context
Browse files Browse the repository at this point in the history
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 <[email protected]>
Change-Id: I6e643d29a9a1aa0814309253a8b690ad86ec0b13
  • Loading branch information
Vinayak Menon authored and nilac8991 committed Oct 22, 2015
1 parent 80d9ce5 commit 77c958f
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 0 deletions.
1 change: 1 addition & 0 deletions include/linux/vmpressure.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
22 changes: 22 additions & 0 deletions mm/vmpressure.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/notifier.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/vmpressure.h>

/*
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -167,6 +172,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;
Expand Down Expand Up @@ -280,6 +294,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;
Expand All @@ -290,6 +305,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);
Expand All @@ -300,9 +320,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);
}

Expand Down

0 comments on commit 77c958f

Please sign in to comment.