@@ -73,6 +73,8 @@ static DECLARE_WAIT_QUEUE_HEAD(khugepaged_wait);
73
73
* default collapse hugepages if there is at least one pte mapped like
74
74
* it would have happened if the vma was large enough during page
75
75
* fault.
76
+ *
77
+ * Note that these are only respected if collapse was initiated by khugepaged.
76
78
*/
77
79
static unsigned int khugepaged_max_ptes_none __read_mostly ;
78
80
static unsigned int khugepaged_max_ptes_swap __read_mostly ;
@@ -86,6 +88,8 @@ static struct kmem_cache *mm_slot_cache __read_mostly;
86
88
#define MAX_PTE_MAPPED_THP 8
87
89
88
90
struct collapse_control {
91
+ bool is_khugepaged ;
92
+
89
93
/* Num pages scanned per node */
90
94
u32 node_load [MAX_NUMNODES ];
91
95
@@ -554,6 +558,7 @@ static bool is_refcount_suitable(struct page *page)
554
558
static int __collapse_huge_page_isolate (struct vm_area_struct * vma ,
555
559
unsigned long address ,
556
560
pte_t * pte ,
561
+ struct collapse_control * cc ,
557
562
struct list_head * compound_pagelist )
558
563
{
559
564
struct page * page = NULL ;
@@ -566,8 +571,10 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
566
571
pte_t pteval = * _pte ;
567
572
if (pte_none (pteval ) || (pte_present (pteval ) &&
568
573
is_zero_pfn (pte_pfn (pteval )))) {
574
+ ++ none_or_zero ;
569
575
if (!userfaultfd_armed (vma ) &&
570
- ++ none_or_zero <= khugepaged_max_ptes_none ) {
576
+ (!cc -> is_khugepaged ||
577
+ none_or_zero <= khugepaged_max_ptes_none )) {
571
578
continue ;
572
579
} else {
573
580
result = SCAN_EXCEED_NONE_PTE ;
@@ -587,11 +594,14 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
587
594
588
595
VM_BUG_ON_PAGE (!PageAnon (page ), page );
589
596
590
- if (page_mapcount (page ) > 1 &&
591
- ++ shared > khugepaged_max_ptes_shared ) {
592
- result = SCAN_EXCEED_SHARED_PTE ;
593
- count_vm_event (THP_SCAN_EXCEED_SHARED_PTE );
594
- goto out ;
597
+ if (page_mapcount (page ) > 1 ) {
598
+ ++ shared ;
599
+ if (cc -> is_khugepaged &&
600
+ shared > khugepaged_max_ptes_shared ) {
601
+ result = SCAN_EXCEED_SHARED_PTE ;
602
+ count_vm_event (THP_SCAN_EXCEED_SHARED_PTE );
603
+ goto out ;
604
+ }
595
605
}
596
606
597
607
if (PageCompound (page )) {
@@ -654,10 +664,14 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
654
664
if (PageCompound (page ))
655
665
list_add_tail (& page -> lru , compound_pagelist );
656
666
next :
657
- /* There should be enough young pte to collapse the page */
658
- if (pte_young (pteval ) ||
659
- page_is_young (page ) || PageReferenced (page ) ||
660
- mmu_notifier_test_young (vma -> vm_mm , address ))
667
+ /*
668
+ * If collapse was initiated by khugepaged, check that there is
669
+ * enough young pte to justify collapsing the page
670
+ */
671
+ if (cc -> is_khugepaged &&
672
+ (pte_young (pteval ) || page_is_young (page ) ||
673
+ PageReferenced (page ) || mmu_notifier_test_young (vma -> vm_mm ,
674
+ address )))
661
675
referenced ++ ;
662
676
663
677
if (pte_write (pteval ))
@@ -666,7 +680,7 @@ static int __collapse_huge_page_isolate(struct vm_area_struct *vma,
666
680
667
681
if (unlikely (!writable )) {
668
682
result = SCAN_PAGE_RO ;
669
- } else if (unlikely (!referenced )) {
683
+ } else if (unlikely (cc -> is_khugepaged && !referenced )) {
670
684
result = SCAN_LACK_REFERENCED_PAGE ;
671
685
} else {
672
686
result = SCAN_SUCCEED ;
@@ -745,6 +759,7 @@ static void khugepaged_alloc_sleep(void)
745
759
746
760
747
761
struct collapse_control khugepaged_collapse_control = {
762
+ .is_khugepaged = true,
748
763
.last_target_node = NUMA_NO_NODE ,
749
764
};
750
765
@@ -1025,7 +1040,7 @@ static int collapse_huge_page(struct mm_struct *mm, unsigned long address,
1025
1040
mmu_notifier_invalidate_range_end (& range );
1026
1041
1027
1042
spin_lock (pte_ptl );
1028
- result = __collapse_huge_page_isolate (vma , address , pte ,
1043
+ result = __collapse_huge_page_isolate (vma , address , pte , cc ,
1029
1044
& compound_pagelist );
1030
1045
spin_unlock (pte_ptl );
1031
1046
@@ -1116,7 +1131,9 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
1116
1131
_pte ++ , _address += PAGE_SIZE ) {
1117
1132
pte_t pteval = * _pte ;
1118
1133
if (is_swap_pte (pteval )) {
1119
- if (++ unmapped <= khugepaged_max_ptes_swap ) {
1134
+ ++ unmapped ;
1135
+ if (!cc -> is_khugepaged ||
1136
+ unmapped <= khugepaged_max_ptes_swap ) {
1120
1137
/*
1121
1138
* Always be strict with uffd-wp
1122
1139
* enabled swap entries. Please see
@@ -1134,8 +1151,10 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
1134
1151
}
1135
1152
}
1136
1153
if (pte_none (pteval ) || is_zero_pfn (pte_pfn (pteval ))) {
1154
+ ++ none_or_zero ;
1137
1155
if (!userfaultfd_armed (vma ) &&
1138
- ++ none_or_zero <= khugepaged_max_ptes_none ) {
1156
+ (!cc -> is_khugepaged ||
1157
+ none_or_zero <= khugepaged_max_ptes_none )) {
1139
1158
continue ;
1140
1159
} else {
1141
1160
result = SCAN_EXCEED_NONE_PTE ;
@@ -1165,11 +1184,14 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
1165
1184
goto out_unmap ;
1166
1185
}
1167
1186
1168
- if (page_mapcount (page ) > 1 &&
1169
- ++ shared > khugepaged_max_ptes_shared ) {
1170
- result = SCAN_EXCEED_SHARED_PTE ;
1171
- count_vm_event (THP_SCAN_EXCEED_SHARED_PTE );
1172
- goto out_unmap ;
1187
+ if (page_mapcount (page ) > 1 ) {
1188
+ ++ shared ;
1189
+ if (cc -> is_khugepaged &&
1190
+ shared > khugepaged_max_ptes_shared ) {
1191
+ result = SCAN_EXCEED_SHARED_PTE ;
1192
+ count_vm_event (THP_SCAN_EXCEED_SHARED_PTE );
1193
+ goto out_unmap ;
1194
+ }
1173
1195
}
1174
1196
1175
1197
page = compound_head (page );
@@ -1220,14 +1242,22 @@ static int khugepaged_scan_pmd(struct mm_struct *mm, struct vm_area_struct *vma,
1220
1242
result = SCAN_PAGE_COUNT ;
1221
1243
goto out_unmap ;
1222
1244
}
1223
- if (pte_young (pteval ) ||
1224
- page_is_young (page ) || PageReferenced (page ) ||
1225
- mmu_notifier_test_young (vma -> vm_mm , address ))
1245
+
1246
+ /*
1247
+ * If collapse was initiated by khugepaged, check that there is
1248
+ * enough young pte to justify collapsing the page
1249
+ */
1250
+ if (cc -> is_khugepaged &&
1251
+ (pte_young (pteval ) || page_is_young (page ) ||
1252
+ PageReferenced (page ) || mmu_notifier_test_young (vma -> vm_mm ,
1253
+ address )))
1226
1254
referenced ++ ;
1227
1255
}
1228
1256
if (!writable ) {
1229
1257
result = SCAN_PAGE_RO ;
1230
- } else if (!referenced || (unmapped && referenced < HPAGE_PMD_NR /2 )) {
1258
+ } else if (cc -> is_khugepaged &&
1259
+ (!referenced ||
1260
+ (unmapped && referenced < HPAGE_PMD_NR / 2 ))) {
1231
1261
result = SCAN_LACK_REFERENCED_PAGE ;
1232
1262
} else {
1233
1263
result = SCAN_SUCCEED ;
@@ -1896,7 +1926,9 @@ static int khugepaged_scan_file(struct mm_struct *mm, struct file *file,
1896
1926
continue ;
1897
1927
1898
1928
if (xa_is_value (page )) {
1899
- if (++ swap > khugepaged_max_ptes_swap ) {
1929
+ ++ swap ;
1930
+ if (cc -> is_khugepaged &&
1931
+ swap > khugepaged_max_ptes_swap ) {
1900
1932
result = SCAN_EXCEED_SWAP_PTE ;
1901
1933
count_vm_event (THP_SCAN_EXCEED_SWAP_PTE );
1902
1934
break ;
@@ -1947,7 +1979,8 @@ static int khugepaged_scan_file(struct mm_struct *mm, struct file *file,
1947
1979
rcu_read_unlock ();
1948
1980
1949
1981
if (result == SCAN_SUCCEED ) {
1950
- if (present < HPAGE_PMD_NR - khugepaged_max_ptes_none ) {
1982
+ if (cc -> is_khugepaged &&
1983
+ present < HPAGE_PMD_NR - khugepaged_max_ptes_none ) {
1951
1984
result = SCAN_EXCEED_NONE_PTE ;
1952
1985
count_vm_event (THP_SCAN_EXCEED_NONE_PTE );
1953
1986
} else {
0 commit comments