lkml.org 
[lkml]   [2012]   [Apr]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: [PATCH] hugetlb: avoid gratuitous BUG_ON in hugetlb_fault() -> hugetlb_cow()
    On Sun, 29 Apr 2012, Chris Metcalf wrote:

    > Commit 66aebce747eaf added code to avoid a race condition by
    > elevating the page refcount in hugetlb_fault() while calling
    > hugetlb_cow(). However, one code path in hugetlb_cow() includes
    > an assertion that the page count is 1, whereas it may now also
    > have the value 2 in this path.
    >
    > Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
    > ---
    > We discovered this while testing the original path; one particular
    > application triggered this due to the specific number of huge pages
    > it started with.

    Well done finding that. But I think it would be better to remove the
    BUG_ON() than complicate it, and then no need to add a comment there.

    IIRC it's unsafe to make any assertions about what a page_count() may
    be, beyond whether it's 0 or non-0: because of speculative accesses to
    the page from elsewhere (perhaps it used to be visible in a radix_tree,
    perhaps __isolate_lru_pages is having a go at it).

    I'd say that BUG_ON() has outlived its usefulness, and should just be
    eliminated now: but git "blames" Mel for it, so let's see if he agrees.

    Hugh

    >
    > mm/hugetlb.c | 9 ++++++++-
    > 1 files changed, 8 insertions(+), 1 deletions(-)
    >
    > diff --git a/mm/hugetlb.c b/mm/hugetlb.c
    > index cd65cb1..d5b0254 100644
    > --- a/mm/hugetlb.c
    > +++ b/mm/hugetlb.c
    > @@ -2498,7 +2498,14 @@ retry_avoidcopy:
    > if (outside_reserve) {
    > BUG_ON(huge_pte_none(pte));
    > if (unmap_ref_private(mm, vma, old_page, address)) {
    > - BUG_ON(page_count(old_page) != 1);
    > + /*
    > + * Page refcount may be 1 in the common case,
    > + * but since we may do an extra get_page()
    > + * when called from hugetlb_fault(), we allow
    > + * a page refcount of 2 as well.
    > + */
    > + BUG_ON(page_count(old_page) != 1 &&
    > + page_count(old_page) != 2);
    > BUG_ON(huge_pte_none(pte));
    > spin_lock(&mm->page_table_lock);
    > ptep = huge_pte_offset(mm, address & huge_page_mask(h));
    > --
    > 1.6.5.2


    \
     
     \ /
      Last update: 2012-04-30 23:01    [W:0.031 / U:0.072 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site