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.