[Devel] [PATCH RHEL7 COMMIT] mm/memcontrol/numa_migrate: split transparent huge pages before migrating
Konstantin Khorenko
khorenko at virtuozzo.com
Fri Nov 25 05:53:12 PST 2016
The commit is pushed to "branch-rh7-3.10.0-327.36.1.vz7.20.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-327.36.1.vz7.20.3
------>
commit 67312c839211c56181d05434ba5fc719ef79aff2
Author: Andrey Ryabinin <aryabinin at virtuozzo.com>
Date: Fri Nov 25 17:53:12 2016 +0400
mm/memcontrol/numa_migrate: split transparent huge pages before migrating
When migrate_pages() steps on transparent huge page it splits the page and
migrates only a head page. Therefore after migration NR_ISOLATED_ANON counter
is dropped by one.
When memcg_numa_isolate_pages() isolates huge page it increase NR_ISOLATED_ANON
counter by the number of sub-pages in hugepage, which is never dropped by
migrate_pages() as above.
Eventually this leads to complete lockup, because every allocation will stuck
in too_many_isolated() loop.
This patch fixes this by splitting huge page before migration and adding
sub-pages to migration list.
https://jira.sw.ru/browse/PSBM-54455
Fixes: a2d6b96306e3 ("mm: memcontrol: add memory.numa_migrate file")
Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
---
mm/memcontrol.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index cdf1b48..6366cc0 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -5740,12 +5740,13 @@ static long memcg_numa_isolate_pages(struct lruvec *lruvec, enum lru_list lru,
{
struct list_head *src = &lruvec->lists[lru];
struct zone *zone = lruvec_zone(lruvec);
+ struct page *page;
long scanned = 0, taken = 0;
spin_lock_irq(&zone->lru_lock);
while (!list_empty(src) && scanned < nr_to_scan && taken < nr_to_scan) {
- struct page *page = list_last_entry(src, struct page, lru);
int nr_pages;
+ page = list_last_entry(src, struct page, lru);
scanned++;
@@ -5769,6 +5770,15 @@ static long memcg_numa_isolate_pages(struct lruvec *lruvec, enum lru_list lru,
__mod_zone_page_state(zone, NR_ISOLATED_ANON + is_file_lru(lru), taken);
spin_unlock_irq(&zone->lru_lock);
+ list_for_each_entry(page, dst, lru) {
+ if (PageTransHuge(page) && split_huge_page_to_list(page, dst)) {
+ list_del(&page->lru);
+ mod_zone_page_state(zone, NR_ISOLATED_ANON,
+ HPAGE_PMD_NR);
+ putback_lru_page(page);
+ }
+ }
+
return scanned;
}
More information about the Devel
mailing list