Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7732e1d9 authored by seungho1.park's avatar seungho1.park Committed by Vinayak Menon
Browse files

android: lowmemorykiller: add lmk parameters tunning code.

There are cases that LMK doesn't run, even when it must run.
It is due to LMK shrinker not considering memory status per zone.
So add LMK parameters(other_free, other_file) tunnig code to
consider target zone of LMK shrinker.

Change-Id: I6f1f8660d5da920a0e3af45a160499965032081d
Git-commit: 22d990a58fc17b3f0155e15eb2dc3efa037bea1c
Git-repo: https://android.googlesource.com/kernel/common/


[ohaugan@codeaurora.org: Fix compilation issues]
Signed-off-by: default avatarOlav Haugan <ohaugan@codeaurora.org>
Signed-off-by: default avatarLiam Mark <lmark@codeaurora.org>
[vinmenon@codeaurora.org: change for movement of lrus from
zone to node. KSWAPD_BALANCE_GAP_RATIO is no more available,
but use its value so as to not break the code]
Signed-off-by: default avatarVinayak Menon <vinmenon@codeaurora.org>
parent 4f1cdd2b
Loading
Loading
Loading
Loading
+92 −2
Original line number Diff line number Diff line
@@ -44,6 +44,13 @@
#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/swap.h>

#ifdef CONFIG_HIGHMEM
#define _ZONE ZONE_HIGHMEM
#else
#define _ZONE ZONE_NORMAL
#endif

#define CREATE_TRACE_POINTS
#include "trace/lowmemorykiller.h"
@@ -65,6 +72,7 @@ static int lowmem_minfree[6] = {
};

static int lowmem_minfree_size = 4;
static int lmk_fast_run = 1;

static unsigned long lowmem_deathpending_timeout;

@@ -117,6 +125,85 @@ static int test_task_lmk_waiting(struct task_struct *p)

static DEFINE_MUTEX(scan_mutex);

void tune_lmk_zone_param(struct zonelist *zonelist, int classzone_idx,
					int *other_free, int *other_file)
{
	struct zone *zone;
	struct zoneref *zoneref;
	int zone_idx;

	for_each_zone_zonelist(zone, zoneref, zonelist, MAX_NR_ZONES) {
		if ((zone_idx = zonelist_zone_idx(zoneref)) == ZONE_MOVABLE)
			continue;

		if (zone_idx > classzone_idx) {
			if (other_free != NULL)
				*other_free -= zone_page_state(zone,
							       NR_FREE_PAGES);
			if (other_file != NULL)
				*other_file -= zone_page_state(zone,
					NR_ZONE_INACTIVE_FILE) +
					zone_page_state(zone,
					NR_ZONE_ACTIVE_FILE);
		} else if ((zone_idx < classzone_idx) && other_free) {
			if (zone_watermark_ok(zone, 0, 0, classzone_idx, 0))
				*other_free -=
				           zone->lowmem_reserve[classzone_idx];
			else
				*other_free -=
				           zone_page_state(zone, NR_FREE_PAGES);
		}
	}
}

void tune_lmk_param(int *other_free, int *other_file, struct shrink_control *sc)
{
	gfp_t gfp_mask;
	struct zone *preferred_zone;
	struct zoneref *zref;
	struct zonelist *zonelist;
	enum zone_type high_zoneidx, classzone_idx;
	unsigned long balance_gap;

	gfp_mask = sc->gfp_mask;
	zonelist = node_zonelist(0, gfp_mask);
	high_zoneidx = gfp_zone(gfp_mask);
	zref = first_zones_zonelist(zonelist, high_zoneidx, NULL);
	preferred_zone = zref->zone;
	classzone_idx = zone_idx(preferred_zone);

	balance_gap = min(low_wmark_pages(preferred_zone),
			  (preferred_zone->present_pages +
			   100-1) /
			   100);

	if (likely(current_is_kswapd() && zone_watermark_ok(preferred_zone, 0,
			  high_wmark_pages(preferred_zone) + SWAP_CLUSTER_MAX +
			  balance_gap, 0, 0))) {
		if (lmk_fast_run)
			tune_lmk_zone_param(zonelist, classzone_idx, other_free,
				       other_file);
		else
			tune_lmk_zone_param(zonelist, classzone_idx, other_free,
				       NULL);

		if (zone_watermark_ok(preferred_zone, 0, 0, _ZONE, 0))
			*other_free -=
			           preferred_zone->lowmem_reserve[_ZONE];
		else
			*other_free -= zone_page_state(preferred_zone,
						      NR_FREE_PAGES);
		lowmem_print(4, "lowmem_shrink of kswapd tunning for highmem "
			     "ofree %d, %d\n", *other_free, *other_file);
	} else {
		tune_lmk_zone_param(zonelist, classzone_idx, other_free,
			       other_file);

		lowmem_print(4, "lowmem_shrink tunning for others ofree %d, "
			     "%d\n", *other_free, *other_file);
	}
}

static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
{
	struct task_struct *tsk;
@@ -141,6 +228,8 @@ static unsigned long lowmem_scan(struct shrinker *s, struct shrink_control *sc)
					global_node_page_state(NR_UNEVICTABLE) -
					total_swapcache_pages();

	tune_lmk_param(&other_free, &other_file, sc);

	if (lowmem_adj_size < array_size)
		array_size = lowmem_adj_size;
	if (lowmem_minfree_size < array_size)
@@ -354,6 +443,7 @@ __MODULE_PARM_TYPE(adj, "array of short");
module_param_array_named(adj, lowmem_adj, short, &lowmem_adj_size, 0644);
#endif
module_param_array_named(minfree, lowmem_minfree, uint, &lowmem_minfree_size,
			 0644);
module_param_named(debug_level, lowmem_debug_level, uint, 0644);
			 S_IRUGO | S_IWUSR);
module_param_named(debug_level, lowmem_debug_level, uint, S_IRUGO | S_IWUSR);
module_param_named(lmk_fast_run, lmk_fast_run, int, S_IRUGO | S_IWUSR);