lkml.org 
[lkml]   [2015]   [Apr]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCHv5 04/28] mm, thp: adjust conditions when we can reuse the page on WP fault
    On 04/23/2015 11:03 PM, Kirill A. Shutemov wrote:
    > With new refcounting we will be able map the same compound page with
    > PTEs and PMDs. It requires adjustment to conditions when we can reuse
    > the page on write-protection fault.
    >
    > For PTE fault we can't reuse the page if it's part of huge page.
    >
    > For PMD we can only reuse the page if nobody else maps the huge page or
    > it's part. We can do it by checking page_mapcount() on each sub-page,
    > but it's expensive.
    >
    > The cheaper way is to check page_count() to be equal 1: every mapcount
    > takes page reference, so this way we can guarantee, that the PMD is the
    > only mapping.
    >
    > This approach can give false negative if somebody pinned the page, but
    > that doesn't affect correctness.
    >
    > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
    > Tested-by: Sasha Levin <sasha.levin@oracle.com>

    Acked-by: Jerome Marchand <jmarchan@redhat.com>

    > ---
    > include/linux/swap.h | 3 ++-
    > mm/huge_memory.c | 12 +++++++++++-
    > mm/swapfile.c | 3 +++
    > 3 files changed, 16 insertions(+), 2 deletions(-)
    >
    > diff --git a/include/linux/swap.h b/include/linux/swap.h
    > index 0428e4c84e1d..17cdd6b9456b 100644
    > --- a/include/linux/swap.h
    > +++ b/include/linux/swap.h
    > @@ -524,7 +524,8 @@ static inline int page_swapcount(struct page *page)
    > return 0;
    > }
    >
    > -#define reuse_swap_page(page) (page_mapcount(page) == 1)
    > +#define reuse_swap_page(page) \
    > + (!PageTransCompound(page) && page_mapcount(page) == 1)
    >
    > static inline int try_to_free_swap(struct page *page)
    > {
    > diff --git a/mm/huge_memory.c b/mm/huge_memory.c
    > index 534f353e12bf..fd8af5b9917f 100644
    > --- a/mm/huge_memory.c
    > +++ b/mm/huge_memory.c
    > @@ -1103,7 +1103,17 @@ int do_huge_pmd_wp_page(struct mm_struct *mm, struct vm_area_struct *vma,
    >
    > page = pmd_page(orig_pmd);
    > VM_BUG_ON_PAGE(!PageCompound(page) || !PageHead(page), page);
    > - if (page_mapcount(page) == 1) {
    > + /*
    > + * We can only reuse the page if nobody else maps the huge page or it's
    > + * part. We can do it by checking page_mapcount() on each sub-page, but
    > + * it's expensive.
    > + * The cheaper way is to check page_count() to be equal 1: every
    > + * mapcount takes page reference reference, so this way we can
    > + * guarantee, that the PMD is the only mapping.
    > + * This can give false negative if somebody pinned the page, but that's
    > + * fine.
    > + */
    > + if (page_mapcount(page) == 1 && page_count(page) == 1) {
    > pmd_t entry;
    > entry = pmd_mkyoung(orig_pmd);
    > entry = maybe_pmd_mkwrite(pmd_mkdirty(entry), vma);
    > diff --git a/mm/swapfile.c b/mm/swapfile.c
    > index 6dd365d1c488..3cd5f188b996 100644
    > --- a/mm/swapfile.c
    > +++ b/mm/swapfile.c
    > @@ -887,6 +887,9 @@ int reuse_swap_page(struct page *page)
    > VM_BUG_ON_PAGE(!PageLocked(page), page);
    > if (unlikely(PageKsm(page)))
    > return 0;
    > + /* The page is part of THP and cannot be reused */
    > + if (PageTransCompound(page))
    > + return 0;
    > count = page_mapcount(page);
    > if (count <= 1 && PageSwapCache(page)) {
    > count += page_swapcount(page);
    >


    [unhandled content-type:application/pgp-signature]
    \
     
     \ /
      Last update: 2015-04-29 18:21    [W:2.082 / U:0.284 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site