Skip to content

Commit 3489dbb

Browse files
mjkravetzakpm00
authored andcommitted
mm: hugetlb: proc: check for hugetlb shared PMD in /proc/PID/smaps
Patch series "Fixes for hugetlb mapcount at most 1 for shared PMDs". This issue of mapcount in hugetlb pages referenced by shared PMDs was discussed in [1]. The following two patches address user visible behavior caused by this issue. [1] https://lore.kernel.org/linux-mm/Y9BF+OCdWnCSilEu@monkey/ This patch (of 2): A hugetlb page will have a mapcount of 1 if mapped by multiple processes via a shared PMD. This is because only the first process increases the map count, and subsequent processes just add the shared PMD page to their page table. page_mapcount is being used to decide if a hugetlb page is shared or private in /proc/PID/smaps. Pages referenced via a shared PMD were incorrectly being counted as private. To fix, check for a shared PMD if mapcount is 1. If a shared PMD is found count the hugetlb page as shared. A new helper to check for a shared PMD is added. [[email protected]: simplification, per David] [[email protected]: hugetlb.h: include page_ref.h for page_count()] Link: https://lkml.kernel.org/r/[email protected] Fixes: 25ee01a ("mm: hugetlb: proc: add hugetlb-related fields to /proc/PID/smaps") Signed-off-by: Mike Kravetz <[email protected]> Acked-by: Peter Xu <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: James Houghton <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Muchun Song <[email protected]> Cc: Naoya Horiguchi <[email protected]> Cc: Vishal Moola (Oracle) <[email protected]> Cc: Yang Shi <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent edb5d0c commit 3489dbb

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

fs/proc/task_mmu.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -745,9 +745,7 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask,
745745
page = pfn_swap_entry_to_page(swpent);
746746
}
747747
if (page) {
748-
int mapcount = page_mapcount(page);
749-
750-
if (mapcount >= 2)
748+
if (page_mapcount(page) >= 2 || hugetlb_pmd_shared(pte))
751749
mss->shared_hugetlb += huge_page_size(hstate_vma(vma));
752750
else
753751
mss->private_hugetlb += huge_page_size(hstate_vma(vma));

include/linux/hugetlb.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <linux/fs.h>
88
#include <linux/hugetlb_inline.h>
99
#include <linux/cgroup.h>
10+
#include <linux/page_ref.h>
1011
#include <linux/list.h>
1112
#include <linux/kref.h>
1213
#include <linux/pgtable.h>
@@ -1187,6 +1188,18 @@ static inline __init void hugetlb_cma_reserve(int order)
11871188
}
11881189
#endif
11891190

1191+
#ifdef CONFIG_ARCH_WANT_HUGE_PMD_SHARE
1192+
static inline bool hugetlb_pmd_shared(pte_t *pte)
1193+
{
1194+
return page_count(virt_to_page(pte)) > 1;
1195+
}
1196+
#else
1197+
static inline bool hugetlb_pmd_shared(pte_t *pte)
1198+
{
1199+
return false;
1200+
}
1201+
#endif
1202+
11901203
bool want_pmd_share(struct vm_area_struct *vma, unsigned long addr);
11911204

11921205
#ifndef __HAVE_ARCH_FLUSH_HUGETLB_TLB_RANGE

0 commit comments

Comments
 (0)