All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20161230172358.GA4266@dhcp22.suse.cz>

diff --git a/a/1.txt b/N1/1.txt
index a8d51be..7f13b0b 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -31,3 +31,279 @@ as far as I remember.
 
 Just this one should be sufficient
 ---
+>From 209710f27de0016cad68cb4ff448f294bc0ff95a Mon Sep 17 00:00:00 2001
+From: Michal Hocko <mhocko@suse.com>
+Date: Fri, 23 Dec 2016 15:11:54 +0100
+Subject: [PATCH] mm, memcg: fix the active list aging for lowmem requests when
+ memcg is enabled
+
+Nils Holland has reported unexpected OOM killer invocations with 32b
+kernel starting with 4.8 kernels
+
+	kworker/u4:5 invoked oom-killer: gfp_mask=0x2400840(GFP_NOFS|__GFP_NOFAIL), nodemask=0, order=0, oom_score_adj=0
+	kworker/u4:5 cpuset=/ mems_allowed=0
+	CPU: 1 PID: 2603 Comm: kworker/u4:5 Not tainted 4.9.0-gentoo #2
+	[...]
+	Mem-Info:
+	active_anon:58685 inactive_anon:90 isolated_anon:0
+	 active_file:274324 inactive_file:281962 isolated_file:0
+	 unevictable:0 dirty:649 writeback:0 unstable:0
+	 slab_reclaimable:40662 slab_unreclaimable:17754
+	 mapped:7382 shmem:202 pagetables:351 bounce:0
+	 free:206736 free_pcp:332 free_cma:0
+	Node 0 active_anon:234740kB inactive_anon:360kB active_file:1097296kB inactive_file:1127848kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:29528kB dirty:2596kB writeback:0kB shmem:0kB shmem_thp: 0kB shmem_pmdmapped: 184320kB anon_thp: 808kB writeback_tmp:0kB unstable:0kB pages_scanned:0 all_unreclaimable? no
+	DMA free:3952kB min:788kB low:984kB high:1180kB active_anon:0kB inactive_anon:0kB active_file:7316kB inactive_file:0kB unevictable:0kB writepending:96kB present:15992kB managed:15916kB mlocked:0kB slab_reclaimable:3200kB slab_unreclaimable:1408kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB
+	lowmem_reserve[]: 0 813 3474 3474
+	Normal free:41332kB min:41368kB low:51708kB high:62048kB active_anon:0kB inactive_anon:0kB active_file:532748kB inactive_file:44kB unevictable:0kB writepending:24kB present:897016kB managed:836248kB mlocked:0kB slab_reclaimable:159448kB slab_unreclaimable:69608kB kernel_stack:1112kB pagetables:1404kB bounce:0kB free_pcp:528kB local_pcp:340kB free_cma:0kB
+	lowmem_reserve[]: 0 0 21292 21292
+	HighMem free:781660kB min:512kB low:34356kB high:68200kB active_anon:234740kB inactive_anon:360kB active_file:557232kB inactive_file:1127804kB unevictable:0kB writepending:2592kB present:2725384kB managed:2725384kB mlocked:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:800kB local_pcp:608kB free_cma:0kB
+
+the oom killer is clearly pre-mature because there there is still a
+lot of page cache in the zone Normal which should satisfy this lowmem
+request. Further debugging has shown that the reclaim cannot make any
+forward progress because the page cache is hidden in the active list
+which doesn't get rotated because inactive_list_is_low is not memcg
+aware.
+It simply subtracts per-zone highmem counters from the respective
+memcg's lru sizes which doesn't make any sense. We can simply end up
+always seeing the resulting active and inactive counts 0 and return
+false. This issue is not limited to 32b kernels but in practice the
+effect on systems without CONFIG_HIGHMEM would be much harder to notice
+because we do not invoke the OOM killer for allocations requests
+targeting < ZONE_NORMAL.
+
+Fix the issue by tracking per zone lru page counts in mem_cgroup_per_node
+and subtract per-memcg highmem counts when memcg is enabled. Introduce
+helper lruvec_zone_lru_size which redirects to either zone counters or
+mem_cgroup_get_zone_lru_size when appropriate.
+
+We are losing empty LRU but non-zero lru size detection introduced by
+ca707239e8a7 ("mm: update_lru_size warn and reset bad lru_size") because
+of the inherent zone vs. node discrepancy.
+
+Fixes: f8d1a31163fc ("mm: consider whether to decivate based on eligible zones inactive ratio")
+Cc: stable # 4.8+
+Acked-by: Minchan Kim <minchan@kernel.org>
+Acked-by: Mel Gorman <mgorman@suse.de>
+Reported-and-tested-by: Nils Holland <nholland@tisys.org>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+---
+ include/linux/memcontrol.h | 26 +++++++++++++++++++++++---
+ include/linux/mm_inline.h  |  2 +-
+ mm/memcontrol.c            | 18 ++++++++----------
+ mm/vmscan.c                | 27 +++++++++++++++++----------
+ 4 files changed, 49 insertions(+), 24 deletions(-)
+
+diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h
+index 61d20c17f3b7..254698856b8f 100644
+--- a/include/linux/memcontrol.h
++++ b/include/linux/memcontrol.h
+@@ -120,7 +120,7 @@ struct mem_cgroup_reclaim_iter {
+  */
+ struct mem_cgroup_per_node {
+ 	struct lruvec		lruvec;
+-	unsigned long		lru_size[NR_LRU_LISTS];
++	unsigned long		lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS];
+ 
+ 	struct mem_cgroup_reclaim_iter	iter[DEF_PRIORITY + 1];
+ 
+@@ -432,7 +432,7 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)
+ int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);
+ 
+ void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
+-		int nr_pages);
++		int zid, int nr_pages);
+ 
+ unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
+ 					   int nid, unsigned int lru_mask);
+@@ -441,9 +441,23 @@ static inline
+ unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
+ {
+ 	struct mem_cgroup_per_node *mz;
++	unsigned long nr_pages = 0;
++	int zid;
+ 
+ 	mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
+-	return mz->lru_size[lru];
++	for (zid = 0; zid < MAX_NR_ZONES; zid++)
++		nr_pages += mz->lru_zone_size[zid][lru];
++	return nr_pages;
++}
++
++static inline
++unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
++		enum lru_list lru, int zone_idx)
++{
++	struct mem_cgroup_per_node *mz;
++
++	mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
++	return mz->lru_zone_size[zone_idx][lru];
+ }
+ 
+ void mem_cgroup_handle_over_high(void);
+@@ -671,6 +685,12 @@ mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)
+ {
+ 	return 0;
+ }
++static inline
++unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,
++		enum lru_list lru, int zone_idx)
++{
++	return 0;
++}
+ 
+ static inline unsigned long
+ mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
+diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
+index 71613e8a720f..41d376e7116d 100644
+--- a/include/linux/mm_inline.h
++++ b/include/linux/mm_inline.h
+@@ -39,7 +39,7 @@ static __always_inline void update_lru_size(struct lruvec *lruvec,
+ {
+ 	__update_lru_size(lruvec, lru, zid, nr_pages);
+ #ifdef CONFIG_MEMCG
+-	mem_cgroup_update_lru_size(lruvec, lru, nr_pages);
++	mem_cgroup_update_lru_size(lruvec, lru, zid, nr_pages);
+ #endif
+ }
+ 
+diff --git a/mm/memcontrol.c b/mm/memcontrol.c
+index 91dfc7c5ce8f..b59676026272 100644
+--- a/mm/memcontrol.c
++++ b/mm/memcontrol.c
+@@ -625,8 +625,8 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,
+ unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
+ 					   int nid, unsigned int lru_mask)
+ {
++	struct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);
+ 	unsigned long nr = 0;
+-	struct mem_cgroup_per_node *mz;
+ 	enum lru_list lru;
+ 
+ 	VM_BUG_ON((unsigned)nid >= nr_node_ids);
+@@ -634,8 +634,7 @@ unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,
+ 	for_each_lru(lru) {
+ 		if (!(BIT(lru) & lru_mask))
+ 			continue;
+-		mz = mem_cgroup_nodeinfo(memcg, nid);
+-		nr += mz->lru_size[lru];
++		nr += mem_cgroup_get_lru_size(lruvec, lru);
+ 	}
+ 	return nr;
+ }
+@@ -1002,6 +1001,7 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct pglist_data *pgd
+  * mem_cgroup_update_lru_size - account for adding or removing an lru page
+  * @lruvec: mem_cgroup per zone lru vector
+  * @lru: index of lru list the page is sitting on
++ * @zid: zone id of the accounted pages
+  * @nr_pages: positive when adding or negative when removing
+  *
+  * This function must be called under lru_lock, just before a page is added
+@@ -1009,27 +1009,25 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct pglist_data *pgd
+  * so as to allow it to check that lru_size 0 is consistent with list_empty).
+  */
+ void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,
+-				int nr_pages)
++				int zid, int nr_pages)
+ {
+ 	struct mem_cgroup_per_node *mz;
+ 	unsigned long *lru_size;
+ 	long size;
+-	bool empty;
+ 
+ 	if (mem_cgroup_disabled())
+ 		return;
+ 
+ 	mz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);
+-	lru_size = mz->lru_size + lru;
+-	empty = list_empty(lruvec->lists + lru);
++	lru_size = &mz->lru_zone_size[zid][lru];
+ 
+ 	if (nr_pages < 0)
+ 		*lru_size += nr_pages;
+ 
+ 	size = *lru_size;
+-	if (WARN_ONCE(size < 0 || empty != !size,
+-		"%s(%p, %d, %d): lru_size %ld but %sempty\n",
+-		__func__, lruvec, lru, nr_pages, size, empty ? "" : "not ")) {
++	if (WARN_ONCE(size < 0,
++		"%s(%p, %d, %d): lru_size %ld\n",
++		__func__, lruvec, lru, nr_pages, size)) {
+ 		VM_BUG_ON(1);
+ 		*lru_size = 0;
+ 	}
+diff --git a/mm/vmscan.c b/mm/vmscan.c
+index c4abf08861d2..fa30010a5277 100644
+--- a/mm/vmscan.c
++++ b/mm/vmscan.c
+@@ -242,6 +242,16 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru)
+ 	return node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru);
+ }
+ 
++unsigned long lruvec_zone_lru_size(struct lruvec *lruvec, enum lru_list lru,
++				   int zone_idx)
++{
++	if (!mem_cgroup_disabled())
++		return mem_cgroup_get_zone_lru_size(lruvec, lru, zone_idx);
++
++	return zone_page_state(&lruvec_pgdat(lruvec)->node_zones[zone_idx],
++			       NR_ZONE_LRU_BASE + lru);
++}
++
+ /*
+  * Add a shrinker callback to be called from the vm.
+  */
+@@ -1382,8 +1392,7 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode)
+  * be complete before mem_cgroup_update_lru_size due to a santity check.
+  */
+ static __always_inline void update_lru_sizes(struct lruvec *lruvec,
+-			enum lru_list lru, unsigned long *nr_zone_taken,
+-			unsigned long nr_taken)
++			enum lru_list lru, unsigned long *nr_zone_taken)
+ {
+ 	int zid;
+ 
+@@ -1392,11 +1401,11 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec,
+ 			continue;
+ 
+ 		__update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);
+-	}
+-
+ #ifdef CONFIG_MEMCG
+-	mem_cgroup_update_lru_size(lruvec, lru, -nr_taken);
++		mem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);
+ #endif
++	}
++
+ }
+ 
+ /*
+@@ -1501,7 +1510,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
+ 	*nr_scanned = scan;
+ 	trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan, scan,
+ 				    nr_taken, mode, is_file_lru(lru));
+-	update_lru_sizes(lruvec, lru, nr_zone_taken, nr_taken);
++	update_lru_sizes(lruvec, lru, nr_zone_taken);
+ 	return nr_taken;
+ }
+ 
+@@ -2047,10 +2056,8 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,
+ 		if (!managed_zone(zone))
+ 			continue;
+ 
+-		inactive_zone = zone_page_state(zone,
+-				NR_ZONE_LRU_BASE + (file * LRU_FILE));
+-		active_zone = zone_page_state(zone,
+-				NR_ZONE_LRU_BASE + (file * LRU_FILE) + LRU_ACTIVE);
++		inactive_zone = lruvec_zone_lru_size(lruvec, file * LRU_FILE, zid);
++		active_zone = lruvec_zone_lru_size(lruvec, (file * LRU_FILE) + LRU_ACTIVE, zid);
+ 
+ 		inactive -= min(inactive, inactive_zone);
+ 		active -= min(active, active_zone);
+-- 
+2.10.2
+
+
+-- 
+Michal Hocko
+SUSE Labs
diff --git a/a/content_digest b/N1/content_digest
index 282f2b0..41a723b 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -43,6 +43,282 @@
  "> Which of the 3 patches is the one? All 3 or just one.\n"
  "\n"
  "Just this one should be sufficient\n"
- ---
+ "---\n"
+ ">From 209710f27de0016cad68cb4ff448f294bc0ff95a Mon Sep 17 00:00:00 2001\n"
+ "From: Michal Hocko <mhocko@suse.com>\n"
+ "Date: Fri, 23 Dec 2016 15:11:54 +0100\n"
+ "Subject: [PATCH] mm, memcg: fix the active list aging for lowmem requests when\n"
+ " memcg is enabled\n"
+ "\n"
+ "Nils Holland has reported unexpected OOM killer invocations with 32b\n"
+ "kernel starting with 4.8 kernels\n"
+ "\n"
+ "\tkworker/u4:5 invoked oom-killer: gfp_mask=0x2400840(GFP_NOFS|__GFP_NOFAIL), nodemask=0, order=0, oom_score_adj=0\n"
+ "\tkworker/u4:5 cpuset=/ mems_allowed=0\n"
+ "\tCPU: 1 PID: 2603 Comm: kworker/u4:5 Not tainted 4.9.0-gentoo #2\n"
+ "\t[...]\n"
+ "\tMem-Info:\n"
+ "\tactive_anon:58685 inactive_anon:90 isolated_anon:0\n"
+ "\t active_file:274324 inactive_file:281962 isolated_file:0\n"
+ "\t unevictable:0 dirty:649 writeback:0 unstable:0\n"
+ "\t slab_reclaimable:40662 slab_unreclaimable:17754\n"
+ "\t mapped:7382 shmem:202 pagetables:351 bounce:0\n"
+ "\t free:206736 free_pcp:332 free_cma:0\n"
+ "\tNode 0 active_anon:234740kB inactive_anon:360kB active_file:1097296kB inactive_file:1127848kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:29528kB dirty:2596kB writeback:0kB shmem:0kB shmem_thp: 0kB shmem_pmdmapped: 184320kB anon_thp: 808kB writeback_tmp:0kB unstable:0kB pages_scanned:0 all_unreclaimable? no\n"
+ "\tDMA free:3952kB min:788kB low:984kB high:1180kB active_anon:0kB inactive_anon:0kB active_file:7316kB inactive_file:0kB unevictable:0kB writepending:96kB present:15992kB managed:15916kB mlocked:0kB slab_reclaimable:3200kB slab_unreclaimable:1408kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB\n"
+ "\tlowmem_reserve[]: 0 813 3474 3474\n"
+ "\tNormal free:41332kB min:41368kB low:51708kB high:62048kB active_anon:0kB inactive_anon:0kB active_file:532748kB inactive_file:44kB unevictable:0kB writepending:24kB present:897016kB managed:836248kB mlocked:0kB slab_reclaimable:159448kB slab_unreclaimable:69608kB kernel_stack:1112kB pagetables:1404kB bounce:0kB free_pcp:528kB local_pcp:340kB free_cma:0kB\n"
+ "\tlowmem_reserve[]: 0 0 21292 21292\n"
+ "\tHighMem free:781660kB min:512kB low:34356kB high:68200kB active_anon:234740kB inactive_anon:360kB active_file:557232kB inactive_file:1127804kB unevictable:0kB writepending:2592kB present:2725384kB managed:2725384kB mlocked:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB bounce:0kB free_pcp:800kB local_pcp:608kB free_cma:0kB\n"
+ "\n"
+ "the oom killer is clearly pre-mature because there there is still a\n"
+ "lot of page cache in the zone Normal which should satisfy this lowmem\n"
+ "request. Further debugging has shown that the reclaim cannot make any\n"
+ "forward progress because the page cache is hidden in the active list\n"
+ "which doesn't get rotated because inactive_list_is_low is not memcg\n"
+ "aware.\n"
+ "It simply subtracts per-zone highmem counters from the respective\n"
+ "memcg's lru sizes which doesn't make any sense. We can simply end up\n"
+ "always seeing the resulting active and inactive counts 0 and return\n"
+ "false. This issue is not limited to 32b kernels but in practice the\n"
+ "effect on systems without CONFIG_HIGHMEM would be much harder to notice\n"
+ "because we do not invoke the OOM killer for allocations requests\n"
+ "targeting < ZONE_NORMAL.\n"
+ "\n"
+ "Fix the issue by tracking per zone lru page counts in mem_cgroup_per_node\n"
+ "and subtract per-memcg highmem counts when memcg is enabled. Introduce\n"
+ "helper lruvec_zone_lru_size which redirects to either zone counters or\n"
+ "mem_cgroup_get_zone_lru_size when appropriate.\n"
+ "\n"
+ "We are losing empty LRU but non-zero lru size detection introduced by\n"
+ "ca707239e8a7 (\"mm: update_lru_size warn and reset bad lru_size\") because\n"
+ "of the inherent zone vs. node discrepancy.\n"
+ "\n"
+ "Fixes: f8d1a31163fc (\"mm: consider whether to decivate based on eligible zones inactive ratio\")\n"
+ "Cc: stable # 4.8+\n"
+ "Acked-by: Minchan Kim <minchan@kernel.org>\n"
+ "Acked-by: Mel Gorman <mgorman@suse.de>\n"
+ "Reported-and-tested-by: Nils Holland <nholland@tisys.org>\n"
+ "Signed-off-by: Michal Hocko <mhocko@suse.com>\n"
+ "---\n"
+ " include/linux/memcontrol.h | 26 +++++++++++++++++++++++---\n"
+ " include/linux/mm_inline.h  |  2 +-\n"
+ " mm/memcontrol.c            | 18 ++++++++----------\n"
+ " mm/vmscan.c                | 27 +++++++++++++++++----------\n"
+ " 4 files changed, 49 insertions(+), 24 deletions(-)\n"
+ "\n"
+ "diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h\n"
+ "index 61d20c17f3b7..254698856b8f 100644\n"
+ "--- a/include/linux/memcontrol.h\n"
+ "+++ b/include/linux/memcontrol.h\n"
+ "@@ -120,7 +120,7 @@ struct mem_cgroup_reclaim_iter {\n"
+ "  */\n"
+ " struct mem_cgroup_per_node {\n"
+ " \tstruct lruvec\t\tlruvec;\n"
+ "-\tunsigned long\t\tlru_size[NR_LRU_LISTS];\n"
+ "+\tunsigned long\t\tlru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS];\n"
+ " \n"
+ " \tstruct mem_cgroup_reclaim_iter\titer[DEF_PRIORITY + 1];\n"
+ " \n"
+ "@@ -432,7 +432,7 @@ static inline bool mem_cgroup_online(struct mem_cgroup *memcg)\n"
+ " int mem_cgroup_select_victim_node(struct mem_cgroup *memcg);\n"
+ " \n"
+ " void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,\n"
+ "-\t\tint nr_pages);\n"
+ "+\t\tint zid, int nr_pages);\n"
+ " \n"
+ " unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,\n"
+ " \t\t\t\t\t   int nid, unsigned int lru_mask);\n"
+ "@@ -441,9 +441,23 @@ static inline\n"
+ " unsigned long mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)\n"
+ " {\n"
+ " \tstruct mem_cgroup_per_node *mz;\n"
+ "+\tunsigned long nr_pages = 0;\n"
+ "+\tint zid;\n"
+ " \n"
+ " \tmz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);\n"
+ "-\treturn mz->lru_size[lru];\n"
+ "+\tfor (zid = 0; zid < MAX_NR_ZONES; zid++)\n"
+ "+\t\tnr_pages += mz->lru_zone_size[zid][lru];\n"
+ "+\treturn nr_pages;\n"
+ "+}\n"
+ "+\n"
+ "+static inline\n"
+ "+unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,\n"
+ "+\t\tenum lru_list lru, int zone_idx)\n"
+ "+{\n"
+ "+\tstruct mem_cgroup_per_node *mz;\n"
+ "+\n"
+ "+\tmz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);\n"
+ "+\treturn mz->lru_zone_size[zone_idx][lru];\n"
+ " }\n"
+ " \n"
+ " void mem_cgroup_handle_over_high(void);\n"
+ "@@ -671,6 +685,12 @@ mem_cgroup_get_lru_size(struct lruvec *lruvec, enum lru_list lru)\n"
+ " {\n"
+ " \treturn 0;\n"
+ " }\n"
+ "+static inline\n"
+ "+unsigned long mem_cgroup_get_zone_lru_size(struct lruvec *lruvec,\n"
+ "+\t\tenum lru_list lru, int zone_idx)\n"
+ "+{\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ " \n"
+ " static inline unsigned long\n"
+ " mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,\n"
+ "diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h\n"
+ "index 71613e8a720f..41d376e7116d 100644\n"
+ "--- a/include/linux/mm_inline.h\n"
+ "+++ b/include/linux/mm_inline.h\n"
+ "@@ -39,7 +39,7 @@ static __always_inline void update_lru_size(struct lruvec *lruvec,\n"
+ " {\n"
+ " \t__update_lru_size(lruvec, lru, zid, nr_pages);\n"
+ " #ifdef CONFIG_MEMCG\n"
+ "-\tmem_cgroup_update_lru_size(lruvec, lru, nr_pages);\n"
+ "+\tmem_cgroup_update_lru_size(lruvec, lru, zid, nr_pages);\n"
+ " #endif\n"
+ " }\n"
+ " \n"
+ "diff --git a/mm/memcontrol.c b/mm/memcontrol.c\n"
+ "index 91dfc7c5ce8f..b59676026272 100644\n"
+ "--- a/mm/memcontrol.c\n"
+ "+++ b/mm/memcontrol.c\n"
+ "@@ -625,8 +625,8 @@ static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg,\n"
+ " unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,\n"
+ " \t\t\t\t\t   int nid, unsigned int lru_mask)\n"
+ " {\n"
+ "+\tstruct lruvec *lruvec = mem_cgroup_lruvec(NODE_DATA(nid), memcg);\n"
+ " \tunsigned long nr = 0;\n"
+ "-\tstruct mem_cgroup_per_node *mz;\n"
+ " \tenum lru_list lru;\n"
+ " \n"
+ " \tVM_BUG_ON((unsigned)nid >= nr_node_ids);\n"
+ "@@ -634,8 +634,7 @@ unsigned long mem_cgroup_node_nr_lru_pages(struct mem_cgroup *memcg,\n"
+ " \tfor_each_lru(lru) {\n"
+ " \t\tif (!(BIT(lru) & lru_mask))\n"
+ " \t\t\tcontinue;\n"
+ "-\t\tmz = mem_cgroup_nodeinfo(memcg, nid);\n"
+ "-\t\tnr += mz->lru_size[lru];\n"
+ "+\t\tnr += mem_cgroup_get_lru_size(lruvec, lru);\n"
+ " \t}\n"
+ " \treturn nr;\n"
+ " }\n"
+ "@@ -1002,6 +1001,7 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct pglist_data *pgd\n"
+ "  * mem_cgroup_update_lru_size - account for adding or removing an lru page\n"
+ "  * @lruvec: mem_cgroup per zone lru vector\n"
+ "  * @lru: index of lru list the page is sitting on\n"
+ "+ * @zid: zone id of the accounted pages\n"
+ "  * @nr_pages: positive when adding or negative when removing\n"
+ "  *\n"
+ "  * This function must be called under lru_lock, just before a page is added\n"
+ "@@ -1009,27 +1009,25 @@ struct lruvec *mem_cgroup_page_lruvec(struct page *page, struct pglist_data *pgd\n"
+ "  * so as to allow it to check that lru_size 0 is consistent with list_empty).\n"
+ "  */\n"
+ " void mem_cgroup_update_lru_size(struct lruvec *lruvec, enum lru_list lru,\n"
+ "-\t\t\t\tint nr_pages)\n"
+ "+\t\t\t\tint zid, int nr_pages)\n"
+ " {\n"
+ " \tstruct mem_cgroup_per_node *mz;\n"
+ " \tunsigned long *lru_size;\n"
+ " \tlong size;\n"
+ "-\tbool empty;\n"
+ " \n"
+ " \tif (mem_cgroup_disabled())\n"
+ " \t\treturn;\n"
+ " \n"
+ " \tmz = container_of(lruvec, struct mem_cgroup_per_node, lruvec);\n"
+ "-\tlru_size = mz->lru_size + lru;\n"
+ "-\tempty = list_empty(lruvec->lists + lru);\n"
+ "+\tlru_size = &mz->lru_zone_size[zid][lru];\n"
+ " \n"
+ " \tif (nr_pages < 0)\n"
+ " \t\t*lru_size += nr_pages;\n"
+ " \n"
+ " \tsize = *lru_size;\n"
+ "-\tif (WARN_ONCE(size < 0 || empty != !size,\n"
+ "-\t\t\"%s(%p, %d, %d): lru_size %ld but %sempty\\n\",\n"
+ "-\t\t__func__, lruvec, lru, nr_pages, size, empty ? \"\" : \"not \")) {\n"
+ "+\tif (WARN_ONCE(size < 0,\n"
+ "+\t\t\"%s(%p, %d, %d): lru_size %ld\\n\",\n"
+ "+\t\t__func__, lruvec, lru, nr_pages, size)) {\n"
+ " \t\tVM_BUG_ON(1);\n"
+ " \t\t*lru_size = 0;\n"
+ " \t}\n"
+ "diff --git a/mm/vmscan.c b/mm/vmscan.c\n"
+ "index c4abf08861d2..fa30010a5277 100644\n"
+ "--- a/mm/vmscan.c\n"
+ "+++ b/mm/vmscan.c\n"
+ "@@ -242,6 +242,16 @@ unsigned long lruvec_lru_size(struct lruvec *lruvec, enum lru_list lru)\n"
+ " \treturn node_page_state(lruvec_pgdat(lruvec), NR_LRU_BASE + lru);\n"
+ " }\n"
+ " \n"
+ "+unsigned long lruvec_zone_lru_size(struct lruvec *lruvec, enum lru_list lru,\n"
+ "+\t\t\t\t   int zone_idx)\n"
+ "+{\n"
+ "+\tif (!mem_cgroup_disabled())\n"
+ "+\t\treturn mem_cgroup_get_zone_lru_size(lruvec, lru, zone_idx);\n"
+ "+\n"
+ "+\treturn zone_page_state(&lruvec_pgdat(lruvec)->node_zones[zone_idx],\n"
+ "+\t\t\t       NR_ZONE_LRU_BASE + lru);\n"
+ "+}\n"
+ "+\n"
+ " /*\n"
+ "  * Add a shrinker callback to be called from the vm.\n"
+ "  */\n"
+ "@@ -1382,8 +1392,7 @@ int __isolate_lru_page(struct page *page, isolate_mode_t mode)\n"
+ "  * be complete before mem_cgroup_update_lru_size due to a santity check.\n"
+ "  */\n"
+ " static __always_inline void update_lru_sizes(struct lruvec *lruvec,\n"
+ "-\t\t\tenum lru_list lru, unsigned long *nr_zone_taken,\n"
+ "-\t\t\tunsigned long nr_taken)\n"
+ "+\t\t\tenum lru_list lru, unsigned long *nr_zone_taken)\n"
+ " {\n"
+ " \tint zid;\n"
+ " \n"
+ "@@ -1392,11 +1401,11 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec,\n"
+ " \t\t\tcontinue;\n"
+ " \n"
+ " \t\t__update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);\n"
+ "-\t}\n"
+ "-\n"
+ " #ifdef CONFIG_MEMCG\n"
+ "-\tmem_cgroup_update_lru_size(lruvec, lru, -nr_taken);\n"
+ "+\t\tmem_cgroup_update_lru_size(lruvec, lru, zid, -nr_zone_taken[zid]);\n"
+ " #endif\n"
+ "+\t}\n"
+ "+\n"
+ " }\n"
+ " \n"
+ " /*\n"
+ "@@ -1501,7 +1510,7 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,\n"
+ " \t*nr_scanned = scan;\n"
+ " \ttrace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan, scan,\n"
+ " \t\t\t\t    nr_taken, mode, is_file_lru(lru));\n"
+ "-\tupdate_lru_sizes(lruvec, lru, nr_zone_taken, nr_taken);\n"
+ "+\tupdate_lru_sizes(lruvec, lru, nr_zone_taken);\n"
+ " \treturn nr_taken;\n"
+ " }\n"
+ " \n"
+ "@@ -2047,10 +2056,8 @@ static bool inactive_list_is_low(struct lruvec *lruvec, bool file,\n"
+ " \t\tif (!managed_zone(zone))\n"
+ " \t\t\tcontinue;\n"
+ " \n"
+ "-\t\tinactive_zone = zone_page_state(zone,\n"
+ "-\t\t\t\tNR_ZONE_LRU_BASE + (file * LRU_FILE));\n"
+ "-\t\tactive_zone = zone_page_state(zone,\n"
+ "-\t\t\t\tNR_ZONE_LRU_BASE + (file * LRU_FILE) + LRU_ACTIVE);\n"
+ "+\t\tinactive_zone = lruvec_zone_lru_size(lruvec, file * LRU_FILE, zid);\n"
+ "+\t\tactive_zone = lruvec_zone_lru_size(lruvec, (file * LRU_FILE) + LRU_ACTIVE, zid);\n"
+ " \n"
+ " \t\tinactive -= min(inactive, inactive_zone);\n"
+ " \t\tactive -= min(active, active_zone);\n"
+ "-- \n"
+ "2.10.2\n"
+ "\n"
+ "\n"
+ "-- \n"
+ "Michal Hocko\n"
+ SUSE Labs
 
-539933e39fcea5c3bd9797a61842b16756089de06187a743cdf07b63b41f6a4d
+8eec8f14224f1c49eb311b8fcd3be413ba9f9a156303cc6e992f53cc79982aa1

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.