Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1666776 > unrolled thread
| Started by | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| First post | 2017-06-15 17:00 +0200 |
| Last post | 2017-06-19 15:30 +0200 |
| Articles | 3 — 3 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
[PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> - 2017-06-15 17:00 +0200
Re: [PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() Andrea Arcangeli <aarcange@redhat.com> - 2017-06-16 15:50 +0200
Re: [PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() "Kirill A. Shutemov" <kirill@shutemov.name> - 2017-06-19 15:30 +0200
| From | "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com> |
|---|---|
| Date | 2017-06-15 17:00 +0200 |
| Subject | [PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() |
| Message-ID | <tSEpA-3Kz-11@gated-at.bofh.it> |
Vlastimil noted that pmdp_invalidate() is not atomic and we can loose
dirty and access bits if CPU sets them after pmdp dereference, but
before set_pmd_at().
The bug doesn't lead to user-visible misbehaviour in current kernel.
Loosing access bit can lead to sub-optimal reclaim behaviour for THP,
but nothing destructive.
Loosing dirty bit is not a big deal too: we would make page dirty
unconditionally on splitting huge page.
The fix is critical for future work on THP: both huge-ext4 and THP swap
out rely on proper dirty tracking.
The patch change pmdp_invalidate() to make the entry non-present atomically and
return previous value of the entry. This value can be used to check if
CPU set dirty/accessed bits under us.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Reported-by: Vlastimil Babka <vbabka@suse.cz>
---
include/asm-generic/pgtable.h | 2 +-
mm/pgtable-generic.c | 9 +++++----
2 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 7dfa767dc680..ece5e399567a 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -309,7 +309,7 @@ extern pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp);
#endif
#ifndef __HAVE_ARCH_PMDP_INVALIDATE
-extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp);
#endif
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index c99d9512a45b..148fe36f61a7 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -179,12 +179,13 @@ pgtable_t pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp)
#endif
#ifndef __HAVE_ARCH_PMDP_INVALIDATE
-void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
+pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp)
{
- pmd_t entry = *pmdp;
- set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
- flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+ pmd_t old = pmdp_establish(pmdp, pmd_mknotpresent(*pmdp));
+ if (pmd_present(old))
+ flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
+ return old;
}
#endif
--
2.11.0
[toc] | [next] | [standalone]
| From | Andrea Arcangeli <aarcange@redhat.com> |
|---|---|
| Date | 2017-06-16 15:50 +0200 |
| Subject | Re: [PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() |
| Message-ID | <tSZNn-Hp-1@gated-at.bofh.it> |
| In reply to | #1666776 |
On Thu, Jun 15, 2017 at 05:52:23PM +0300, Kirill A. Shutemov wrote:
> -void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
> +pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
> pmd_t *pmdp)
> {
> - pmd_t entry = *pmdp;
> - set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
> - flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
> + pmd_t old = pmdp_establish(pmdp, pmd_mknotpresent(*pmdp));
> + if (pmd_present(old))
> + flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
> + return old;
> }
> #endif
The pmd_present() check added above is superflous because there's no
point to call pmdp_invalidate if the pmd is not present (present as in
pmd_present) already. pmd_present returns true if _PAGE_PSE is set
and it was always set before calling pmdp_invalidate.
It looks like we could skip the flush if _PAGE_PRESENT is not set
(i.e. for example if the pmd is PROTNONE) but that's not what the above
pmd_present will do.
[toc] | [prev] | [next] | [standalone]
| From | "Kirill A. Shutemov" <kirill@shutemov.name> |
|---|---|
| Date | 2017-06-19 15:30 +0200 |
| Subject | Re: [PATCHv2 2/3] mm: Do not loose dirty and access bits in pmdp_invalidate() |
| Message-ID | <tU4UH-3bd-35@gated-at.bofh.it> |
| In reply to | #1667755 |
On Fri, Jun 16, 2017 at 03:40:41PM +0200, Andrea Arcangeli wrote:
> On Thu, Jun 15, 2017 at 05:52:23PM +0300, Kirill A. Shutemov wrote:
> > -void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
> > +pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
> > pmd_t *pmdp)
> > {
> > - pmd_t entry = *pmdp;
> > - set_pmd_at(vma->vm_mm, address, pmdp, pmd_mknotpresent(entry));
> > - flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
> > + pmd_t old = pmdp_establish(pmdp, pmd_mknotpresent(*pmdp));
> > + if (pmd_present(old))
> > + flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE);
> > + return old;
> > }
> > #endif
>
> The pmd_present() check added above is superflous because there's no
> point to call pmdp_invalidate if the pmd is not present (present as in
> pmd_present) already. pmd_present returns true if _PAGE_PSE is set
> and it was always set before calling pmdp_invalidate.
>
> It looks like we could skip the flush if _PAGE_PRESENT is not set
> (i.e. for example if the pmd is PROTNONE) but that's not what the above
> pmd_present will do.
You are right. We seems don't have a generic way to check the entry is
present to CPU.
I guess I'll drop the check then.
--
Kirill A. Shutemov
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web