]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
mm: thp: fix false negative of shmem vma's THP eligibility
authorYang Shi <yang.shi@linux.alibaba.com>
Thu, 18 Jul 2019 22:57:27 +0000 (15:57 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 19 Jul 2019 00:08:06 +0000 (17:08 -0700)
Commit 7635d9cbe832 ("mm, thp, proc: report THP eligibility for each
vma") introduced THPeligible bit for processes' smaps.  But, when
checking the eligibility for shmem vma, __transparent_hugepage_enabled()
is called to override the result from shmem_huge_enabled().  It may
result in the anonymous vma's THP flag override shmem's.  For example,
running a simple test which create THP for shmem, but with anonymous THP
disabled, when reading the process's smaps, it may show:

  7fc92ec00000-7fc92f000000 rw-s 00000000 00:14 27764 /dev/shm/test
  Size:               4096 kB
  ...
  [snip]
  ...
  ShmemPmdMapped:     4096 kB
  ...
  [snip]
  ...
  THPeligible:    0

And, /proc/meminfo does show THP allocated and PMD mapped too:

  ShmemHugePages:     4096 kB
  ShmemPmdMapped:     4096 kB

This doesn't make too much sense.  The shmem objects should be treated
separately from anonymous THP.  Calling shmem_huge_enabled() with
checking MMF_DISABLE_THP sounds good enough.  And, we could skip stack
and dax vma check since we already checked if the vma is shmem already.

Also check if vma is suitable for THP by calling
transhuge_vma_suitable().

And minor fix to smaps output format and documentation.

Link: http://lkml.kernel.org/r/1560401041-32207-3-git-send-email-yang.shi@linux.alibaba.com
Fixes: 7635d9cbe832 ("mm, thp, proc: report THP eligibility for each vma")
Signed-off-by: Yang Shi <yang.shi@linux.alibaba.com>
Acked-by: Hugh Dickins <hughd@google.com>
Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: David Rientjes <rientjes@google.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Documentation/filesystems/proc.txt
fs/proc/task_mmu.c
mm/huge_memory.c
mm/shmem.c

index fb4735fd73b0945fa5cd4d4cb972068892352173..99ca040e3f900e399b59e2b5233fa9169ac61ccb 100644 (file)
@@ -486,8 +486,8 @@ replaced by copy-on-write) part of the underlying shmem object out on swap.
 "SwapPss" shows proportional swap share of this mapping. Unlike "Swap", this
 does not take into account swapped out page of underlying shmem objects.
 "Locked" indicates whether the mapping is locked in memory or not.
-"THPeligible" indicates whether the mapping is eligible for THP pages - 1 if
-true, 0 otherwise.
+"THPeligible" indicates whether the mapping is eligible for allocating THP
+pages - 1 if true, 0 otherwise. It just shows the current status.
 
 "VmFlags" field deserves a separate description. This member represents the kernel
 flags associated with the particular virtual memory area in two letter encoded
index 818cedbed95fec30f236a914deac04b6c85eb394..731642e0f5a0fb42c13873bf3abfc21cedb67dd9 100644 (file)
@@ -832,7 +832,8 @@ static int show_smap(struct seq_file *m, void *v)
 
        __show_smap(m, &mss, false);
 
-       seq_printf(m, "THPeligible:    %d\n", transparent_hugepage_enabled(vma));
+       seq_printf(m, "THPeligible:             %d\n",
+                  transparent_hugepage_enabled(vma));
 
        if (arch_pkeys_enabled())
                seq_printf(m, "ProtectionKey:  %8u\n", vma_pkey(vma));
index 782dd1446a3e959578d38606ada4b4ff0d5bdeec..1334ede667a82aa1d5701526836c7f54487e9996 100644 (file)
@@ -63,10 +63,15 @@ struct page *huge_zero_page __read_mostly;
 
 bool transparent_hugepage_enabled(struct vm_area_struct *vma)
 {
+       /* The addr is used to check if the vma size fits */
+       unsigned long addr = (vma->vm_end & HPAGE_PMD_MASK) - HPAGE_PMD_SIZE;
+
+       if (!transhuge_vma_suitable(vma, addr))
+               return false;
        if (vma_is_anonymous(vma))
                return __transparent_hugepage_enabled(vma);
-       if (vma_is_shmem(vma) && shmem_huge_enabled(vma))
-               return __transparent_hugepage_enabled(vma);
+       if (vma_is_shmem(vma))
+               return shmem_huge_enabled(vma);
 
        return false;
 }
index 99497cb32e71aab00fcd566e6daaa47aaa0639dd..c88a30919ae5b220e66a39f027b55dfd80f6cf2b 100644 (file)
@@ -3874,6 +3874,9 @@ bool shmem_huge_enabled(struct vm_area_struct *vma)
        loff_t i_size;
        pgoff_t off;
 
+       if ((vma->vm_flags & VM_NOHUGEPAGE) ||
+           test_bit(MMF_DISABLE_THP, &vma->vm_mm->flags))
+               return false;
        if (shmem_huge == SHMEM_HUGE_FORCE)
                return true;
        if (shmem_huge == SHMEM_HUGE_DENY)