lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Fri,  3 Apr 2020 14:40:45 +0900
From:   js1304@...il.com
To:     Andrew Morton <akpm@...ux-foundation.org>
Cc:     linux-mm@...ck.org, linux-kernel@...r.kernel.org,
        Johannes Weiner <hannes@...xchg.org>,
        Michal Hocko <mhocko@...nel.org>,
        Hugh Dickins <hughd@...gle.com>,
        Minchan Kim <minchan@...nel.org>,
        Vlastimil Babka <vbabka@...e.cz>,
        Mel Gorman <mgorman@...hsingularity.net>, kernel-team@....com,
        Joonsoo Kim <iamjoonsoo.kim@....com>
Subject: [PATCH v5 07/10] mm/workingset: support to remember the previous owner of the page

From: Joonsoo Kim <iamjoonsoo.kim@....com>

This patch supports to remember the previous owner of the page.
Since there is not enough spare bits in shadow entry for this information,
only a few bits of the memcg id of the page is stored. Although this
information is insufficient, it would provide enough level of the ability
to check the previous owner.

This patch is for the preparation of the following patch, "mm/swap:
do not readahead if the previous owner of the swap entry isn't me".

Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@....com>
---
 mm/workingset.c | 41 +++++++++++++++++++++++++++++++----------
 1 file changed, 31 insertions(+), 10 deletions(-)

diff --git a/mm/workingset.c b/mm/workingset.c
index 59415e0..871b867 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -168,8 +168,20 @@
  * refault distance will immediately activate the refaulting page.
  */
 
+/*
+ * memcg_tag will be used to check the previous owner of the page.
+ * Since we don't have enough spare bits in shadow entry, just a few
+ * bits are used to approximate the previous owner.
+ */
+#if BITS_PER_LONG == 32
+#define PAGE_MEMCG_TAG_SHIFT 4
+#else
+#define PAGE_MEMCG_TAG_SHIFT 8
+#endif
+
 #define EVICTION_SHIFT	((BITS_PER_LONG - BITS_PER_XA_VALUE) +	\
-			 1 + NODES_SHIFT + MEM_CGROUP_ID_SHIFT)
+			 1 + NODES_SHIFT + MEM_CGROUP_ID_SHIFT + \
+			 PAGE_MEMCG_TAG_SHIFT)
 #define EVICTION_MASK	(~0UL >> EVICTION_SHIFT)
 
 /*
@@ -182,11 +194,12 @@
  */
 static unsigned int bucket_order __read_mostly;
 
-static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long eviction,
-			 bool workingset)
+static void *pack_shadow(int memcgid, int page_memcg_tag, pg_data_t *pgdat,
+			unsigned long eviction, bool workingset)
 {
 	eviction >>= bucket_order;
 	eviction &= EVICTION_MASK;
+	eviction = (eviction << PAGE_MEMCG_TAG_SHIFT) | page_memcg_tag;
 	eviction = (eviction << MEM_CGROUP_ID_SHIFT) | memcgid;
 	eviction = (eviction << NODES_SHIFT) | pgdat->node_id;
 	eviction = (eviction << 1) | workingset;
@@ -194,11 +207,12 @@ static void *pack_shadow(int memcgid, pg_data_t *pgdat, unsigned long eviction,
 	return xa_mk_value(eviction);
 }
 
-static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
-			  unsigned long *evictionp, bool *workingsetp)
+static void unpack_shadow(void *shadow, int *memcgidp, int *page_memcg_tagp,
+			pg_data_t **pgdat, unsigned long *evictionp,
+			bool *workingsetp)
 {
 	unsigned long entry = xa_to_value(shadow);
-	int memcgid, nid;
+	int memcgid, page_memcg_tag, nid;
 	bool workingset;
 
 	workingset = entry & 1;
@@ -207,8 +221,11 @@ static void unpack_shadow(void *shadow, int *memcgidp, pg_data_t **pgdat,
 	entry >>= NODES_SHIFT;
 	memcgid = entry & ((1UL << MEM_CGROUP_ID_SHIFT) - 1);
 	entry >>= MEM_CGROUP_ID_SHIFT;
+	page_memcg_tag = entry & ((1UL << PAGE_MEMCG_TAG_SHIFT) - 1);
+	entry >>= PAGE_MEMCG_TAG_SHIFT;
 
 	*memcgidp = memcgid;
+	*page_memcg_tagp = page_memcg_tag;
 	*pgdat = NODE_DATA(nid);
 	*evictionp = entry << bucket_order;
 	*workingsetp = workingset;
@@ -248,9 +265,9 @@ void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg)
 {
 	struct pglist_data *pgdat = page_pgdat(page);
 	bool file = page_is_file_cache(page);
+	int memcgid, page_memcg_tag;
 	unsigned long eviction;
 	struct lruvec *lruvec;
-	int memcgid;
 
 	/* Page is fully exclusive and pins page->mem_cgroup */
 	VM_BUG_ON_PAGE(PageLRU(page), page);
@@ -262,8 +279,11 @@ void *workingset_eviction(struct page *page, struct mem_cgroup *target_memcg)
 	lruvec = mem_cgroup_lruvec(target_memcg, pgdat);
 	/* XXX: target_memcg can be NULL, go through lruvec */
 	memcgid = mem_cgroup_id(lruvec_memcg(lruvec));
+	page_memcg_tag = mem_cgroup_id(page_memcg(page));
+	page_memcg_tag &= (1UL << PAGE_MEMCG_TAG_SHIFT) - 1;
 	eviction = atomic_long_read(&lruvec->inactive_age[file]);
-	return pack_shadow(memcgid, pgdat, eviction, PageWorkingset(page));
+	return pack_shadow(memcgid, page_memcg_tag, pgdat, eviction,
+			PageWorkingset(page));
 }
 
 /**
@@ -281,6 +301,7 @@ void workingset_refault(struct page *page, void *shadow)
 	struct mem_cgroup *eviction_memcg;
 	struct lruvec *eviction_lruvec;
 	unsigned long refault_distance;
+	int memcgid, page_memcg_tag;
 	struct pglist_data *pgdat;
 	struct mem_cgroup *memcg;
 	unsigned long eviction;
@@ -288,9 +309,9 @@ void workingset_refault(struct page *page, void *shadow)
 	unsigned long refault;
 	unsigned long active;
 	bool workingset;
-	int memcgid;
 
-	unpack_shadow(shadow, &memcgid, &pgdat, &eviction, &workingset);
+	unpack_shadow(shadow, &memcgid, &page_memcg_tag,
+			&pgdat, &eviction, &workingset);
 
 	rcu_read_lock();
 	/*
-- 
2.7.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ