| From bce73e4842390f7b7309c8e253e139db71288ac3 Mon Sep 17 00:00:00 2001 |
| From: Christian Borntraeger <borntraeger@de.ibm.com> |
| Date: Fri, 13 Jul 2018 16:58:52 -0700 |
| Subject: mm: do not drop unused pages when userfaultd is running |
| |
| From: Christian Borntraeger <borntraeger@de.ibm.com> |
| |
| commit bce73e4842390f7b7309c8e253e139db71288ac3 upstream. |
| |
| KVM guests on s390 can notify the host of unused pages. This can result |
| in pte_unused callbacks to be true for KVM guest memory. |
| |
| If a page is unused (checked with pte_unused) we might drop this page |
| instead of paging it. This can have side-effects on userfaultd, when |
| the page in question was already migrated: |
| |
| The next access of that page will trigger a fault and a user fault |
| instead of faulting in a new and empty zero page. As QEMU does not |
| expect a userfault on an already migrated page this migration will fail. |
| |
| The most straightforward solution is to ignore the pte_unused hint if a |
| userfault context is active for this VMA. |
| |
| Link: http://lkml.kernel.org/r/20180703171854.63981-1-borntraeger@de.ibm.com |
| Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> |
| Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> |
| Cc: Andrea Arcangeli <aarcange@redhat.com> |
| Cc: Mike Rapoport <rppt@linux.vnet.ibm.com> |
| Cc: Janosch Frank <frankja@linux.ibm.com> |
| Cc: David Hildenbrand <david@redhat.com> |
| Cc: Cornelia Huck <cohuck@redhat.com> |
| Cc: <stable@vger.kernel.org> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| mm/rmap.c | 8 +++++++- |
| 1 file changed, 7 insertions(+), 1 deletion(-) |
| |
| --- a/mm/rmap.c |
| +++ b/mm/rmap.c |
| @@ -64,6 +64,7 @@ |
| #include <linux/backing-dev.h> |
| #include <linux/page_idle.h> |
| #include <linux/memremap.h> |
| +#include <linux/userfaultfd_k.h> |
| |
| #include <asm/tlbflush.h> |
| |
| @@ -1476,11 +1477,16 @@ static bool try_to_unmap_one(struct page |
| set_pte_at(mm, address, pvmw.pte, pteval); |
| } |
| |
| - } else if (pte_unused(pteval)) { |
| + } else if (pte_unused(pteval) && !userfaultfd_armed(vma)) { |
| /* |
| * The guest indicated that the page content is of no |
| * interest anymore. Simply discard the pte, vmscan |
| * will take care of the rest. |
| + * A future reference will then fault in a new zero |
| + * page. When userfaultfd is active, we must not drop |
| + * this page though, as its main user (postcopy |
| + * migration) will not expect userfaults on already |
| + * copied pages. |
| */ |
| dec_mm_counter(mm, mm_counter(page)); |
| } else if (IS_ENABLED(CONFIG_MIGRATION) && |