From b6349b7ab1fd746d57846c0ec83179a82490b7f9 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Tue, 8 Jun 2021 10:27:13 -0400 Subject: [PATCH] Fixes for 5.12 Signed-off-by: Sasha Levin --- ...imple-resv_huge_pages-underflow-on-u.patch | 82 +++++++++++++++++++ queue-5.12/series | 1 + 2 files changed, 83 insertions(+) create mode 100644 queue-5.12/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch diff --git a/queue-5.12/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch b/queue-5.12/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch new file mode 100644 index 00000000000..781736031ef --- /dev/null +++ b/queue-5.12/mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch @@ -0,0 +1,82 @@ +From a8039ed7edde7c2550da6158e68dd4142efd3be7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 4 Jun 2021 20:01:36 -0700 +Subject: mm, hugetlb: fix simple resv_huge_pages underflow on UFFDIO_COPY + +From: Mina Almasry + +[ Upstream commit d84cf06e3dd8c5c5b547b5d8931015fc536678e5 ] + +The userfaultfd hugetlb tests cause a resv_huge_pages underflow. This +happens when hugetlb_mcopy_atomic_pte() is called with !is_continue on +an index for which we already have a page in the cache. When this +happens, we allocate a second page, double consuming the reservation, +and then fail to insert the page into the cache and return -EEXIST. + +To fix this, we first check if there is a page in the cache which +already consumed the reservation, and return -EEXIST immediately if so. + +There is still a rare condition where we fail to copy the page contents +AND race with a call for hugetlb_no_page() for this index and again we +will underflow resv_huge_pages. That is fixed in a more complicated +patch not targeted for -stable. + +Test: + + Hacked the code locally such that resv_huge_pages underflows produce a + warning, then: + + ./tools/testing/selftests/vm/userfaultfd hugetlb_shared 10 + 2 /tmp/kokonut_test/huge/userfaultfd_test && echo test success + ./tools/testing/selftests/vm/userfaultfd hugetlb 10 + 2 /tmp/kokonut_test/huge/userfaultfd_test && echo test success + +Both tests succeed and produce no warnings. After the test runs number +of free/resv hugepages is correct. + +[mike.kravetz@oracle.com: changelog fixes] + +Link: https://lkml.kernel.org/r/20210528004649.85298-1-almasrymina@google.com +Fixes: 8fb5debc5fcd ("userfaultfd: hugetlbfs: add hugetlb_mcopy_atomic_pte for userfaultfd support") +Signed-off-by: Mina Almasry +Reviewed-by: Mike Kravetz +Cc: Axel Rasmussen +Cc: Peter Xu +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + mm/hugetlb.c | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/mm/hugetlb.c b/mm/hugetlb.c +index 96b722af092e..ce63ec0187c5 100644 +--- a/mm/hugetlb.c ++++ b/mm/hugetlb.c +@@ -4705,10 +4705,20 @@ int hugetlb_mcopy_atomic_pte(struct mm_struct *dst_mm, + struct page *page; + + if (!*pagep) { +- ret = -ENOMEM; ++ /* If a page already exists, then it's UFFDIO_COPY for ++ * a non-missing case. Return -EEXIST. ++ */ ++ if (vm_shared && ++ hugetlbfs_pagecache_present(h, dst_vma, dst_addr)) { ++ ret = -EEXIST; ++ goto out; ++ } ++ + page = alloc_huge_page(dst_vma, dst_addr, 0); +- if (IS_ERR(page)) ++ if (IS_ERR(page)) { ++ ret = -ENOMEM; + goto out; ++ } + + ret = copy_huge_page_from_user(page, + (const void __user *) src_addr, +-- +2.30.2 + diff --git a/queue-5.12/series b/queue-5.12/series index 58a165ea248..ec0ce1df67b 100644 --- a/queue-5.12/series +++ b/queue-5.12/series @@ -145,3 +145,4 @@ btrfs-check-error-value-from-btrfs_update_inode-in-tree-log.patch btrfs-fixup-error-handling-in-fixup_inode_link_counts.patch btrfs-abort-in-rename_exchange-if-we-fail-to-insert-the-second-ref.patch btrfs-fix-deadlock-when-cloning-inline-extents-and-low-on-available-space.patch +mm-hugetlb-fix-simple-resv_huge_pages-underflow-on-u.patch -- 2.47.3