Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc/pseries/cmm: fix managed page counts when migrating pages between zones

Commit 63341ab03706 (virtio-balloon: fix managed page counts when migrating
pages between zones) fixed a long existing BUG in the virtio-balloon
driver when pages would get migrated between zones. I did not try to
reproduce on powerpc, but looking at the code, the same should apply to
powerpc/cmm ever since it started using the balloon compaction
infrastructure (luckily just recently).

In case we have to migrate a ballon page to a newpage of another zone, the
managed page count of both zones is wrong. Paired with memory offlining
(which will adjust the managed page count), we can trigger kernel crashes
and all kinds of different symptoms.

Fix it by properly adjusting the managed page count when migrating if
the zone changed.

We'll temporarily modify the totalram page count. If this ever becomes a
problem, we can fine tune by providing helpers that don't touch
the totalram pages (e.g., adjust_zone_managed_page_count()).

Fixes: fe030c9b85e6 ("powerpc/pseries/cmm: Implement balloon compaction")
Signed-off-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://lore.kernel.org/r/20191216103058.4958-1-david@redhat.com

authored by

David Hildenbrand and committed by
Michael Ellerman
e352f576 0601546f

+10
+10
arch/powerpc/platforms/pseries/cmm.c
··· 539 539 /* balloon page list reference */ 540 540 get_page(newpage); 541 541 542 + /* 543 + * When we migrate a page to a different zone, we have to fixup the 544 + * count of both involved zones as we adjusted the managed page count 545 + * when inflating. 546 + */ 547 + if (page_zone(page) != page_zone(newpage)) { 548 + adjust_managed_page_count(page, 1); 549 + adjust_managed_page_count(newpage, -1); 550 + } 551 + 542 552 spin_lock_irqsave(&b_dev_info->pages_lock, flags); 543 553 balloon_page_insert(b_dev_info, newpage); 544 554 balloon_page_delete(page);