Skip to content

Commit

Permalink
mm: don't play games with pinned pages in clear_page_refs
Browse files Browse the repository at this point in the history
[ Upstream commit 9348b73 ]

Turning a pinned page read-only breaks the pinning after COW.  Don't do it.

The whole "track page soft dirty" state doesn't work with pinned pages
anyway, since the page might be dirtied by the pinning entity without
ever being noticed in the page tables.

Signed-off-by: Linus Torvalds <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
torvalds authored and gregkh committed Jan 19, 2021
1 parent 41b0b0c commit 1eea108
Showing 1 changed file with 21 additions and 0 deletions.
21 changes: 21 additions & 0 deletions fs/proc/task_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,25 @@ struct clear_refs_private {
};

#ifdef CONFIG_MEM_SOFT_DIRTY

#define is_cow_mapping(flags) (((flags) & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE)

static inline bool pte_is_pinned(struct vm_area_struct *vma, unsigned long addr, pte_t pte)
{
struct page *page;

if (!pte_write(pte))
return false;
if (!is_cow_mapping(vma->vm_flags))
return false;
if (likely(!atomic_read(&vma->vm_mm->has_pinned)))
return false;
page = vm_normal_page(vma, addr, pte);
if (!page)
return false;
return page_maybe_dma_pinned(page);
}

static inline void clear_soft_dirty(struct vm_area_struct *vma,
unsigned long addr, pte_t *pte)
{
Expand All @@ -1049,6 +1068,8 @@ static inline void clear_soft_dirty(struct vm_area_struct *vma,
if (pte_present(ptent)) {
pte_t old_pte;

if (pte_is_pinned(vma, addr, ptent))
return;
old_pte = ptep_modify_prot_start(vma, addr, pte);
ptent = pte_wrprotect(old_pte);
ptent = pte_clear_soft_dirty(ptent);
Expand Down

0 comments on commit 1eea108

Please sign in to comment.