The following cleanup reworks all the max_ptes_* handling into helper
functions. This increases the code readability and will later be used to
implement the mTHP handling of these variables.

With these changes we abstract all the madvise_collapse() special casing
(dont respect the sysctls) away from the functions that utilize them. And
will later in this series to cleanly restrict mTHP collapses behaviors.

Suggested-by: David Hildenbrand <[email protected]>
Signed-off-by: Nico Pache <[email protected]>
---
 mm/khugepaged.c | 114 +++++++++++++++++++++++++++++++++---------------
 1 file changed, 78 insertions(+), 36 deletions(-)

diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index afac6bc4e76d..f42b55421191 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -348,6 +348,58 @@ static bool pte_none_or_zero(pte_t pte)
        return pte_present(pte) && is_zero_pfn(pte_pfn(pte));
 }
 
+/**
+ * collapse_max_ptes_none - Calculate maximum allowed empty PTEs for collapse
+ * @cc: The collapse control struct
+ * @vma: The vma to check for userfaultfd
+ *
+ * If we are not in khugepaged mode use HPAGE_PMD_NR to allow any
+ * empty page.
+ *
+ * Return: Maximum number of empty PTEs allowed for the collapse operation
+ */
+static unsigned int collapse_max_ptes_none(struct collapse_control *cc,
+               struct vm_area_struct *vma)
+{
+       if (vma && userfaultfd_armed(vma))
+               return 0;
+       if (!cc->is_khugepaged)
+               return HPAGE_PMD_NR;
+       return khugepaged_max_ptes_none;
+}
+
+/**
+ * collapse_max_ptes_shared - Calculate maximum allowed shared PTEs for 
collapse
+ * @cc: The collapse control struct
+ *
+ * If we are not in khugepaged mode use HPAGE_PMD_NR to allow any
+ * shared page.
+ *
+ * Return: Maximum number of shared PTEs allowed for the collapse operation
+ */
+static unsigned int collapse_max_ptes_shared(struct collapse_control *cc)
+{
+       if (!cc->is_khugepaged)
+               return HPAGE_PMD_NR;
+       return khugepaged_max_ptes_shared;
+}
+
+/**
+ * collapse_max_ptes_swap - Calculate maximum allowed swap PTEs for collapse
+ * @cc: The collapse control struct
+ *
+ * If we are not in khugepaged mode use HPAGE_PMD_NR to allow any
+ * swap page.
+ *
+ * Return: Maximum number of swap PTEs allowed for the collapse operation
+ */
+static unsigned int collapse_max_ptes_swap(struct collapse_control *cc)
+{
+       if (!cc->is_khugepaged)
+               return HPAGE_PMD_NR;
+       return khugepaged_max_ptes_swap;
+}
+
 int hugepage_madvise(struct vm_area_struct *vma,
                     vm_flags_t *vm_flags, int advice)
 {
@@ -546,21 +598,19 @@ static enum scan_result 
__collapse_huge_page_isolate(struct vm_area_struct *vma,
        pte_t *_pte;
        int none_or_zero = 0, shared = 0, referenced = 0;
        enum scan_result result = SCAN_FAIL;
+       unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma);
+       unsigned int max_ptes_shared = collapse_max_ptes_shared(cc);
 
        for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
             _pte++, addr += PAGE_SIZE) {
                pte_t pteval = ptep_get(_pte);
                if (pte_none_or_zero(pteval)) {
-                       ++none_or_zero;
-                       if (!userfaultfd_armed(vma) &&
-                           (!cc->is_khugepaged ||
-                            none_or_zero <= khugepaged_max_ptes_none)) {
-                               continue;
-                       } else {
+                       if (++none_or_zero > max_ptes_none) {
                                result = SCAN_EXCEED_NONE_PTE;
                                count_vm_event(THP_SCAN_EXCEED_NONE_PTE);
                                goto out;
                        }
+                       continue;
                }
                if (!pte_present(pteval)) {
                        result = SCAN_PTE_NON_PRESENT;
@@ -591,9 +641,7 @@ static enum scan_result __collapse_huge_page_isolate(struct 
vm_area_struct *vma,
 
                /* See collapse_scan_pmd(). */
                if (folio_maybe_mapped_shared(folio)) {
-                       ++shared;
-                       if (cc->is_khugepaged &&
-                           shared > khugepaged_max_ptes_shared) {
+                       if (++shared > max_ptes_shared) {
                                result = SCAN_EXCEED_SHARED_PTE;
                                count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
                                goto out;
@@ -1270,6 +1318,9 @@ static enum scan_result collapse_scan_pmd(struct 
mm_struct *mm,
        unsigned long addr;
        spinlock_t *ptl;
        int node = NUMA_NO_NODE, unmapped = 0;
+       unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma);
+       unsigned int max_ptes_shared = collapse_max_ptes_shared(cc);
+       unsigned int max_ptes_swap = collapse_max_ptes_swap(cc);
 
        VM_BUG_ON(start_addr & ~HPAGE_PMD_MASK);
 
@@ -1294,36 +1345,29 @@ static enum scan_result collapse_scan_pmd(struct 
mm_struct *mm,
 
                pte_t pteval = ptep_get(_pte);
                if (pte_none_or_zero(pteval)) {
-                       ++none_or_zero;
-                       if (!userfaultfd_armed(vma) &&
-                           (!cc->is_khugepaged ||
-                            none_or_zero <= khugepaged_max_ptes_none)) {
-                               continue;
-                       } else {
+                       if (++none_or_zero > max_ptes_none) {
                                result = SCAN_EXCEED_NONE_PTE;
                                count_vm_event(THP_SCAN_EXCEED_NONE_PTE);
                                goto out_unmap;
                        }
+                       continue;
                }
                if (!pte_present(pteval)) {
-                       ++unmapped;
-                       if (!cc->is_khugepaged ||
-                           unmapped <= khugepaged_max_ptes_swap) {
-                               /*
-                                * Always be strict with uffd-wp
-                                * enabled swap entries.  Please see
-                                * comment below for pte_uffd_wp().
-                                */
-                               if (pte_swp_uffd_wp_any(pteval)) {
-                                       result = SCAN_PTE_UFFD_WP;
-                                       goto out_unmap;
-                               }
-                               continue;
-                       } else {
+                       if (++unmapped > max_ptes_swap) {
                                result = SCAN_EXCEED_SWAP_PTE;
                                count_vm_event(THP_SCAN_EXCEED_SWAP_PTE);
                                goto out_unmap;
                        }
+                       /*
+                        * Always be strict with uffd-wp
+                        * enabled swap entries.  Please see
+                        * comment below for pte_uffd_wp().
+                        */
+                       if (pte_swp_uffd_wp_any(pteval)) {
+                               result = SCAN_PTE_UFFD_WP;
+                               goto out_unmap;
+                       }
+                       continue;
                }
                if (pte_uffd_wp(pteval)) {
                        /*
@@ -1366,9 +1410,7 @@ static enum scan_result collapse_scan_pmd(struct 
mm_struct *mm,
                 * is shared.
                 */
                if (folio_maybe_mapped_shared(folio)) {
-                       ++shared;
-                       if (cc->is_khugepaged &&
-                           shared > khugepaged_max_ptes_shared) {
+                       if (++shared > max_ptes_shared) {
                                result = SCAN_EXCEED_SHARED_PTE;
                                count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
                                goto out_unmap;
@@ -2329,6 +2371,8 @@ static enum scan_result collapse_scan_file(struct 
mm_struct *mm,
        int present, swap;
        int node = NUMA_NO_NODE;
        enum scan_result result = SCAN_SUCCEED;
+       unsigned int max_ptes_none = collapse_max_ptes_none(cc, NULL);
+       unsigned int max_ptes_swap = collapse_max_ptes_swap(cc);
 
        present = 0;
        swap = 0;
@@ -2341,8 +2385,7 @@ static enum scan_result collapse_scan_file(struct 
mm_struct *mm,
 
                if (xa_is_value(folio)) {
                        swap += 1 << xas_get_order(&xas);
-                       if (cc->is_khugepaged &&
-                           swap > khugepaged_max_ptes_swap) {
+                       if (swap > max_ptes_swap) {
                                result = SCAN_EXCEED_SWAP_PTE;
                                count_vm_event(THP_SCAN_EXCEED_SWAP_PTE);
                                break;
@@ -2413,8 +2456,7 @@ static enum scan_result collapse_scan_file(struct 
mm_struct *mm,
                cc->progress += HPAGE_PMD_NR;
 
        if (result == SCAN_SUCCEED) {
-               if (cc->is_khugepaged &&
-                   present < HPAGE_PMD_NR - khugepaged_max_ptes_none) {
+               if (present < HPAGE_PMD_NR - max_ptes_none) {
                        result = SCAN_EXCEED_NONE_PTE;
                        count_vm_event(THP_SCAN_EXCEED_NONE_PTE);
                } else {
-- 
2.53.0


Reply via email to