Skip to content

Commit

Permalink
mm/shmem: allows file-back mem to be uffd wr-protected on thps
Browse files Browse the repository at this point in the history
We don't have "huge" version of pte markers, instead when necessary we
split the thp.

However split the thp is not enough, because file-backed thp is handled
totally differently comparing to anonymous thps: rather than doing a real
split, the thp pmd will simply got cleared in __split_huge_pmd_locked().

That is not enough if e.g.  when there is a thp covers range [0, 2M) but
we want to wr-protect small page resides in [4K, 8K) range, because after
__split_huge_pmd() returns, there will be a none pmd, and
change_pmd_range() will just skip it right after the split.

Here we leverage the previously introduced change_pmd_prepare() macro so
that we'll populate the pmd with a pgtable page after the pmd split (in
which process the pmd will be cleared for cases like shmem).  Then
change_pte_range() will do all the rest for us by installing the uffd-wp
pte marker at any none pte that we'd like to wr-protect.

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Peter Xu <[email protected]>
Cc: Alistair Popple <[email protected]>
Cc: Andrea Arcangeli <[email protected]>
Cc: Axel Rasmussen <[email protected]>
Cc: David Hildenbrand <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Jerome Glisse <[email protected]>
Cc: "Kirill A . Shutemov" <[email protected]>
Cc: Matthew Wilcox <[email protected]>
Cc: Mike Kravetz <[email protected]>
Cc: Mike Rapoport <[email protected]>
Cc: Nadav Amit <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
  • Loading branch information
xzpeter authored and akpm00 committed May 13, 2022
1 parent fe2567e commit 019c2d8
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion mm/mprotect.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,15 @@ static inline unsigned long change_pmd_range(struct mmu_gather *tlb,
}

if (is_swap_pmd(*pmd) || pmd_trans_huge(*pmd) || pmd_devmap(*pmd)) {
if (next - addr != HPAGE_PMD_SIZE) {
if ((next - addr != HPAGE_PMD_SIZE) ||
uffd_wp_protect_file(vma, cp_flags)) {
__split_huge_pmd(vma, pmd, addr, false, NULL);
/*
* For file-backed, the pmd could have been
* cleared; make sure pmd populated if
* necessary, then fall-through to pte level.
*/
change_pmd_prepare(vma, pmd, cp_flags);
} else {
/*
* change_huge_pmd() does not defer TLB flushes,
Expand Down

0 comments on commit 019c2d8

Please sign in to comment.