lkml.org 
[lkml]   [2018]   [Jan]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [mm 4.15-rc8] Random oopses under memory pressure.
    On Thu, Jan 18, 2018 at 04:12:10PM +0300, Kirill A. Shutemov wrote:
    > On Thu, Jan 18, 2018 at 03:25:50PM +0300, Kirill A. Shutemov wrote:
    > > On Thu, Jan 18, 2018 at 05:12:45PM +0900, Tetsuo Handa wrote:
    > > > Tetsuo Handa wrote:
    > > > > OK. I missed the mark. I overlooked that 4.11 already has this problem.
    > > > >
    > > > > I needed to bisect between 4.10 and 4.11, and I got plausible culprit.
    > > > >
    > > > > I haven't completed bisecting between b4fb8f66f1ae2e16 and c470abd4fde40ea6, but
    > > > > b4fb8f66f1ae2e16 ("mm, page_alloc: Add missing check for memory holes") and
    > > > > 13ad59df67f19788 ("mm, page_alloc: avoid page_to_pfn() when merging buddies")
    > > > > are talking about memory holes, which matches the situation that I'm trivially
    > > > > hitting the bug if CONFIG_SPARSEMEM=y .
    > > > >
    > > > > Thus, I call for an attention by speculative execution. ;-)
    > > >
    > > > Speculative execution failed. I was confused by jiffies precision bug.
    > > > The final culprit is c7ab0d2fdc840266 ("mm: convert try_to_unmap_one() to use page_vma_mapped_walk()").
    > >
    > > I think I've tracked it down. check_pte() in mm/page_vma_mapped.c doesn't
    > > work as intended.
    > >
    > > I've added instrumentation below to prove it.
    > >
    > > The BUG() triggers with following output:
    > >
    > > [ 10.084024] diff: -858690919
    > > [ 10.084258] hpage_nr_pages: 1
    > > [ 10.084386] check1: 0
    > > [ 10.084478] check2: 0
    > >
    > > Basically, pte_page(*pvmw->pte) is below pvmw->page, but
    > > (pte_page(*pvmw->pte) < pvmw->page) doesn't catch it.
    > >
    > > Well, I can see how C lawyer can argue that you can only compare pointers
    > > of the same memory object which is not the case here. But this is kinda
    > > insane.
    > >
    > > Any suggestions how to rewrite it in a way that compiler would
    > > understand?
    >
    > The patch below makes the crash go away for me.
    >
    > But this is situation is scary. So we cannot compare arbitrary pointers in
    > kernel?
    >
    > Don't we rely on this for lock ordering in some cases? Like in
    > mutex_lock_double()?
    >
    > diff --git a/mm/page_vma_mapped.c b/mm/page_vma_mapped.c
    > index d22b84310f6d..1f0f512fd127 100644
    > --- a/mm/page_vma_mapped.c
    > +++ b/mm/page_vma_mapped.c
    > @@ -51,6 +51,8 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw)
    > WARN_ON_ONCE(1);
    > #endif
    > } else {
    > + unsigned long ptr1, ptr2;
    > +
    > if (is_swap_pte(*pvmw->pte)) {
    > swp_entry_t entry;
    >
    > @@ -63,12 +65,14 @@ static bool check_pte(struct page_vma_mapped_walk *pvmw)
    > if (!pte_present(*pvmw->pte))
    > return false;
    >
    > - /* THP can be referenced by any subpage */
    > - if (pte_page(*pvmw->pte) - pvmw->page >=
    > - hpage_nr_pages(pvmw->page)) {
    > + ptr1 = (unsigned long)pte_page(*pvmw->pte);
    > + ptr2 = (unsigned long)pvmw->page;
    > +
    > + if (ptr1 < ptr2)
    > return false;
    > - }
    > - if (pte_page(*pvmw->pte) < pvmw->page)
    > +
    > + /* THP can be referenced by any subpage */
    > + if (ptr1 - ptr2 >= hpage_nr_pages(pvmw->page))

    Arghhh.. It has to be

    if (ptr1 - ptr2 >= hpage_nr_pages(pvmw->page) * sizeof(*pvmw->page))

    --
    Kirill A. Shutemov

    \
     
     \ /
      Last update: 2018-01-18 15:35    [W:4.046 / U:0.452 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site