Skip to content

Commit 00f5810

Browse files
Ryan Robertsakpm00
authored andcommitted
mm: fix khugepaged activation policy
Since the introduction of mTHP, the docuementation has stated that khugepaged would be enabled when any mTHP size is enabled, and disabled when all mTHP sizes are disabled. There are 2 problems with this; 1. this is not what was implemented by the code and 2. this is not the desirable behavior. Desirable behavior is for khugepaged to be enabled when any PMD-sized THP is enabled, anon or file. (Note that file THP is still controlled by the top-level control so we must always consider that, as well as the PMD-size mTHP control for anon). khugepaged only supports collapsing to PMD-sized THP so there is no value in enabling it when PMD-sized THP is disabled. So let's change the code and documentation to reflect this policy. Further, per-size enabled control modification events were not previously forwarded to khugepaged to give it an opportunity to start or stop. Consequently the following was resulting in khugepaged eroneously not being activated: echo never > /sys/kernel/mm/transparent_hugepage/enabled echo always > /sys/kernel/mm/transparent_hugepage/hugepages-2048kB/enabled [[email protected]: v3] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Ryan Roberts <[email protected]> Fixes: 3485b88 ("mm: thp: introduce multi-size THP sysfs interface") Closes: https://lore.kernel.org/linux-mm/[email protected]/ Acked-by: David Hildenbrand <[email protected]> Cc: Baolin Wang <[email protected]> Cc: Barry Song <[email protected]> Cc: Jonathan Corbet <[email protected]> Cc: Lance Yang <[email protected]> Cc: Yang Shi <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 823430c commit 00f5810

File tree

4 files changed

+38
-25
lines changed

4 files changed

+38
-25
lines changed

Documentation/admin-guide/mm/transhuge.rst

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,11 @@ PMD-mappable transparent hugepage::
202202

203203
cat /sys/kernel/mm/transparent_hugepage/hpage_pmd_size
204204

205-
khugepaged will be automatically started when one or more hugepage
206-
sizes are enabled (either by directly setting "always" or "madvise",
207-
or by setting "inherit" while the top-level enabled is set to "always"
208-
or "madvise"), and it'll be automatically shutdown when the last
209-
hugepage size is disabled (either by directly setting "never", or by
210-
setting "inherit" while the top-level enabled is set to "never").
205+
khugepaged will be automatically started when PMD-sized THP is enabled
206+
(either of the per-size anon control or the top-level control are set
207+
to "always" or "madvise"), and it'll be automatically shutdown when
208+
PMD-sized THP is disabled (when both the per-size anon control and the
209+
top-level control are "never")
211210

212211
Khugepaged controls
213212
-------------------

include/linux/huge_mm.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,18 +128,6 @@ static inline bool hugepage_global_always(void)
128128
(1<<TRANSPARENT_HUGEPAGE_FLAG);
129129
}
130130

131-
static inline bool hugepage_flags_enabled(void)
132-
{
133-
/*
134-
* We cover both the anon and the file-backed case here; we must return
135-
* true if globally enabled, even when all anon sizes are set to never.
136-
* So we don't need to look at huge_anon_orders_inherit.
137-
*/
138-
return hugepage_global_enabled() ||
139-
READ_ONCE(huge_anon_orders_always) ||
140-
READ_ONCE(huge_anon_orders_madvise);
141-
}
142-
143131
static inline int highest_order(unsigned long orders)
144132
{
145133
return fls_long(orders) - 1;

mm/huge_memory.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,13 @@ static ssize_t thpsize_enabled_store(struct kobject *kobj,
502502
} else
503503
ret = -EINVAL;
504504

505+
if (ret > 0) {
506+
int err;
507+
508+
err = start_stop_khugepaged();
509+
if (err)
510+
ret = err;
511+
}
505512
return ret;
506513
}
507514

mm/khugepaged.c

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,26 @@ static inline int hpage_collapse_test_exit_or_disable(struct mm_struct *mm)
413413
test_bit(MMF_DISABLE_THP, &mm->flags);
414414
}
415415

416+
static bool hugepage_pmd_enabled(void)
417+
{
418+
/*
419+
* We cover both the anon and the file-backed case here; file-backed
420+
* hugepages, when configured in, are determined by the global control.
421+
* Anon pmd-sized hugepages are determined by the pmd-size control.
422+
*/
423+
if (IS_ENABLED(CONFIG_READ_ONLY_THP_FOR_FS) &&
424+
hugepage_global_enabled())
425+
return true;
426+
if (test_bit(PMD_ORDER, &huge_anon_orders_always))
427+
return true;
428+
if (test_bit(PMD_ORDER, &huge_anon_orders_madvise))
429+
return true;
430+
if (test_bit(PMD_ORDER, &huge_anon_orders_inherit) &&
431+
hugepage_global_enabled())
432+
return true;
433+
return false;
434+
}
435+
416436
void __khugepaged_enter(struct mm_struct *mm)
417437
{
418438
struct khugepaged_mm_slot *mm_slot;
@@ -449,7 +469,7 @@ void khugepaged_enter_vma(struct vm_area_struct *vma,
449469
unsigned long vm_flags)
450470
{
451471
if (!test_bit(MMF_VM_HUGEPAGE, &vma->vm_mm->flags) &&
452-
hugepage_flags_enabled()) {
472+
hugepage_pmd_enabled()) {
453473
if (thp_vma_allowable_order(vma, vm_flags, TVA_ENFORCE_SYSFS,
454474
PMD_ORDER))
455475
__khugepaged_enter(vma->vm_mm);
@@ -2462,8 +2482,7 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages, int *result,
24622482

24632483
static int khugepaged_has_work(void)
24642484
{
2465-
return !list_empty(&khugepaged_scan.mm_head) &&
2466-
hugepage_flags_enabled();
2485+
return !list_empty(&khugepaged_scan.mm_head) && hugepage_pmd_enabled();
24672486
}
24682487

24692488
static int khugepaged_wait_event(void)
@@ -2536,7 +2555,7 @@ static void khugepaged_wait_work(void)
25362555
return;
25372556
}
25382557

2539-
if (hugepage_flags_enabled())
2558+
if (hugepage_pmd_enabled())
25402559
wait_event_freezable(khugepaged_wait, khugepaged_wait_event());
25412560
}
25422561

@@ -2567,7 +2586,7 @@ static void set_recommended_min_free_kbytes(void)
25672586
int nr_zones = 0;
25682587
unsigned long recommended_min;
25692588

2570-
if (!hugepage_flags_enabled()) {
2589+
if (!hugepage_pmd_enabled()) {
25712590
calculate_min_free_kbytes();
25722591
goto update_wmarks;
25732592
}
@@ -2617,7 +2636,7 @@ int start_stop_khugepaged(void)
26172636
int err = 0;
26182637

26192638
mutex_lock(&khugepaged_mutex);
2620-
if (hugepage_flags_enabled()) {
2639+
if (hugepage_pmd_enabled()) {
26212640
if (!khugepaged_thread)
26222641
khugepaged_thread = kthread_run(khugepaged, NULL,
26232642
"khugepaged");
@@ -2643,7 +2662,7 @@ int start_stop_khugepaged(void)
26432662
void khugepaged_min_free_kbytes_update(void)
26442663
{
26452664
mutex_lock(&khugepaged_mutex);
2646-
if (hugepage_flags_enabled() && khugepaged_thread)
2665+
if (hugepage_pmd_enabled() && khugepaged_thread)
26472666
set_recommended_min_free_kbytes();
26482667
mutex_unlock(&khugepaged_mutex);
26492668
}

0 commit comments

Comments
 (0)