lkml.org 
[lkml]   [2016]   [Sep]   [5]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.7 108/143] soft_dirty: fix soft_dirty during THP split
    Date
    4.7-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Andrea Arcangeli <aarcange@redhat.com>

    commit 804dd150468cfd920d92d4b3cf00536fedef3902 upstream.

    While adding proper userfaultfd_wp support with bits in pagetable and
    swap entry to avoid false positives WP userfaults through swap/fork/
    KSM/etc, I've been adding a framework that mostly mirrors soft dirty.

    So I noticed in one place I had to add uffd_wp support to the pagetables
    that wasn't covered by soft_dirty and I think it should have.

    Example: in the THP migration code migrate_misplaced_transhuge_page()
    pmd_mkdirty is called unconditionally after mk_huge_pmd.

    entry = mk_huge_pmd(new_page, vma->vm_page_prot);
    entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);

    That sets soft dirty too (it's a false positive for soft dirty, the soft
    dirty bit could be more finegrained and transfer the bit like uffd_wp
    will do.. pmd/pte_uffd_wp() enforces the invariant that when it's set
    pmd/pte_write is not set).

    However in the THP split there's no unconditional pmd_mkdirty after
    mk_huge_pmd and pte_swp_mksoft_dirty isn't called after the migration
    entry is created. The code sets the dirty bit in the struct page
    instead of setting it in the pagetable (which is fully equivalent as far
    as the real dirty bit is concerned, as the whole point of pagetable bits
    is to be eventually flushed out of to the page, but that is not
    equivalent for the soft-dirty bit that gets lost in translation).

    This was found by code review only and totally untested as I'm working
    to actually replace soft dirty and I don't have time to test potential
    soft dirty bugfixes as well :).

    Transfer the soft_dirty from pmd to pte during THP splits.

    This fix avoids losing the soft_dirty bit and avoids userland memory
    corruption in the checkpoint.

    Fixes: eef1b3ba053aa6 ("thp: implement split_huge_pmd()")
    Link: http://lkml.kernel.org/r/1471610515-30229-2-git-send-email-aarcange@redhat.com
    Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
    Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
    Cc: "Kirill A. Shutemov" <kirill@shutemov.name>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    mm/huge_memory.c | 7 ++++++-
    1 file changed, 6 insertions(+), 1 deletion(-)

    --- a/mm/huge_memory.c
    +++ b/mm/huge_memory.c
    @@ -2872,7 +2872,7 @@ static void __split_huge_pmd_locked(stru
    struct page *page;
    pgtable_t pgtable;
    pmd_t _pmd;
    - bool young, write, dirty;
    + bool young, write, dirty, soft_dirty;
    unsigned long addr;
    int i;

    @@ -2898,6 +2898,7 @@ static void __split_huge_pmd_locked(stru
    write = pmd_write(*pmd);
    young = pmd_young(*pmd);
    dirty = pmd_dirty(*pmd);
    + soft_dirty = pmd_soft_dirty(*pmd);

    pmdp_huge_split_prepare(vma, haddr, pmd);
    pgtable = pgtable_trans_huge_withdraw(mm, pmd);
    @@ -2914,6 +2915,8 @@ static void __split_huge_pmd_locked(stru
    swp_entry_t swp_entry;
    swp_entry = make_migration_entry(page + i, write);
    entry = swp_entry_to_pte(swp_entry);
    + if (soft_dirty)
    + entry = pte_swp_mksoft_dirty(entry);
    } else {
    entry = mk_pte(page + i, vma->vm_page_prot);
    entry = maybe_mkwrite(entry, vma);
    @@ -2921,6 +2924,8 @@ static void __split_huge_pmd_locked(stru
    entry = pte_wrprotect(entry);
    if (!young)
    entry = pte_mkold(entry);
    + if (soft_dirty)
    + entry = pte_mksoft_dirty(entry);
    }
    if (dirty)
    SetPageDirty(page + i);

    \
     
     \ /
      Last update: 2016-09-17 09:58    [W:4.922 / U:0.380 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site