* default collapse hugepages if there is at least one pte mapped like
  * it would have happened if the vma was large enough during page
  * fault.
+ *
+ * Note that these are only respected if collapse was initiated by khugepaged.
  */
 static unsigned int khugepaged_max_ptes_none __read_mostly;
 static unsigned int khugepaged_max_ptes_swap __read_mostly;
 #define MAX_PTE_MAPPED_THP 8
 
 struct collapse_control {
+       bool is_khugepaged;
+
        /* Num pages scanned per node */
        u32 node_load[MAX_NUMNODES];
 
 static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
                                        unsigned long address,
                                        pte_t *pte,
+                                       struct collapse_control *cc,
                                        struct list_head *compound_pagelist)
 {
        struct page *page = NULL;
                pte_t pteval = *_pte;
                if (pte_none(pteval) || (pte_present(pteval) &&
                                is_zero_pfn(pte_pfn(pteval)))) {
+                       ++none_or_zero;
                        if (!userfaultfd_armed(vma) &&
-                           ++none_or_zero <= khugepaged_max_ptes_none) {
+                           (!cc->is_khugepaged ||
+                            none_or_zero <= khugepaged_max_ptes_none)) {
                                continue;
                        } else {
                                result = SCAN_EXCEED_NONE_PTE;
 
                VM_BUG_ON_PAGE(!PageAnon(page), page);
 
-               if (page_mapcount(page) > 1 &&
-                               ++shared > khugepaged_max_ptes_shared) {
-                       result = SCAN_EXCEED_SHARED_PTE;
-                       count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
-                       goto out;
+               if (page_mapcount(page) > 1) {
+                       ++shared;
+                       if (cc->is_khugepaged &&
+                           shared > khugepaged_max_ptes_shared) {
+                               result = SCAN_EXCEED_SHARED_PTE;
+                               count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
+                               goto out;
+                       }
                }
 
                if (PageCompound(page)) {
                if (PageCompound(page))
                        list_add_tail(&page->lru, compound_pagelist);
 next:
-               /* There should be enough young pte to collapse the page */
-               if (pte_young(pteval) ||
-                   page_is_young(page) || PageReferenced(page) ||
-                   mmu_notifier_test_young(vma->vm_mm, address))
+               /*
+                * If collapse was initiated by khugepaged, check that there is
+                * enough young pte to justify collapsing the page
+                */
+               if (cc->is_khugepaged &&
+                   (pte_young(pteval) || page_is_young(page) ||
+                    PageReferenced(page) || mmu_notifier_test_young(vma->vm_mm,
+                                                                    address)))
                        referenced++;
 
                if (pte_write(pteval))
 
        if (unlikely(!writable)) {
                result = SCAN_PAGE_RO;
-       } else if (unlikely(!referenced)) {
+       } else if (unlikely(cc->is_khugepaged && !referenced)) {
                result = SCAN_LACK_REFERENCED_PAGE;
        } else {
                result = SCAN_SUCCEED;
 
 
 struct collapse_control khugepaged_collapse_control = {
+       .is_khugepaged = true,
        .last_target_node = NUMA_NO_NODE,
 };
 
        mmu_notifier_invalidate_range_end(&range);
 
        spin_lock(pte_ptl);
-       result =  __collapse_huge_page_isolate(vma, address, pte,
+       result =  __collapse_huge_page_isolate(vma, address, pte, cc,
                                               &compound_pagelist);
        spin_unlock(pte_ptl);
 
             _pte++, _address += PAGE_SIZE) {
                pte_t pteval = *_pte;
                if (is_swap_pte(pteval)) {
-                       if (++unmapped <= khugepaged_max_ptes_swap) {
+                       ++unmapped;
+                       if (!cc->is_khugepaged ||
+                           unmapped <= khugepaged_max_ptes_swap) {
                                /*
                                 * Always be strict with uffd-wp
                                 * enabled swap entries.  Please see
                        }
                }
                if (pte_none(pteval) || is_zero_pfn(pte_pfn(pteval))) {
+                       ++none_or_zero;
                        if (!userfaultfd_armed(vma) &&
-                           ++none_or_zero <= khugepaged_max_ptes_none) {
+                           (!cc->is_khugepaged ||
+                            none_or_zero <= khugepaged_max_ptes_none)) {
                                continue;
                        } else {
                                result = SCAN_EXCEED_NONE_PTE;
                        goto out_unmap;
                }
 
-               if (page_mapcount(page) > 1 &&
-                               ++shared > khugepaged_max_ptes_shared) {
-                       result = SCAN_EXCEED_SHARED_PTE;
-                       count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
-                       goto out_unmap;
+               if (page_mapcount(page) > 1) {
+                       ++shared;
+                       if (cc->is_khugepaged &&
+                           shared > khugepaged_max_ptes_shared) {
+                               result = SCAN_EXCEED_SHARED_PTE;
+                               count_vm_event(THP_SCAN_EXCEED_SHARED_PTE);
+                               goto out_unmap;
+                       }
                }
 
                page = compound_head(page);
                        result = SCAN_PAGE_COUNT;
                        goto out_unmap;
                }
-               if (pte_young(pteval) ||
-                   page_is_young(page) || PageReferenced(page) ||
-                   mmu_notifier_test_young(vma->vm_mm, address))
+
+               /*
+                * If collapse was initiated by khugepaged, check that there is
+                * enough young pte to justify collapsing the page
+                */
+               if (cc->is_khugepaged &&
+                   (pte_young(pteval) || page_is_young(page) ||
+                    PageReferenced(page) || mmu_notifier_test_young(vma->vm_mm,
+                                                                    address)))
                        referenced++;
        }
        if (!writable) {
                result = SCAN_PAGE_RO;
-       } else if (!referenced || (unmapped && referenced < HPAGE_PMD_NR/2)) {
+       } else if (cc->is_khugepaged &&
+                  (!referenced ||
+                   (unmapped && referenced < HPAGE_PMD_NR / 2))) {
                result = SCAN_LACK_REFERENCED_PAGE;
        } else {
                result = SCAN_SUCCEED;
                        continue;
 
                if (xa_is_value(page)) {
-                       if (++swap > khugepaged_max_ptes_swap) {
+                       ++swap;
+                       if (cc->is_khugepaged &&
+                           swap > khugepaged_max_ptes_swap) {
                                result = SCAN_EXCEED_SWAP_PTE;
                                count_vm_event(THP_SCAN_EXCEED_SWAP_PTE);
                                break;
        rcu_read_unlock();
 
        if (result == SCAN_SUCCEED) {
-               if (present < HPAGE_PMD_NR - khugepaged_max_ptes_none) {
+               if (cc->is_khugepaged &&
+                   present < HPAGE_PMD_NR - khugepaged_max_ptes_none) {
                        result = SCAN_EXCEED_NONE_PTE;
                        count_vm_event(THP_SCAN_EXCEED_NONE_PTE);
                } else {