[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20131211191855.GA32485@redhat.com>
Date: Wed, 11 Dec 2013 20:18:55 +0100
From: Oleg Nesterov <oleg@...hat.com>
To: Thomas Gleixner <tglx@...utronix.de>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>,
Dave Jones <davej@...hat.com>,
Darren Hart <dvhart@...ux.intel.com>,
Andrea Arcangeli <aarcange@...hat.com>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Peter Zijlstra <peterz@...radead.org>,
Mel Gorman <mgorman@...e.de>
Subject: PATCH? introduce get_compound_page (Was: process 'stuck' at exit)
On 12/11, Oleg Nesterov wrote:
>
> On 12/11, Thomas Gleixner wrote:
> >
> > On Wed, 11 Dec 2013, Oleg Nesterov wrote:
> > >
> > > I have to admit, I do not understand why we can't avoid this altogether.
> > >
> > > __get_page_tail() can find the stable ->first_page, why get_futex_key()
> > > can't ?
> >
> > Because it can be split under us.
>
> I understand, but why we can't rely on compound_lock() like
> __get_page_tail() does?
>
> OK, could you please explain why something like the pseudo-code
> below can't work?
Seriously. Can the path below work?
With this change get_futex_key() can simply do
page_head = get_compound_head(page);
if (page_head)
put_page(page);
else
page_head = page;
instead of CONFIG_TRANSPARENT_HUGEPAGE/else code.
(and we can also remove "bool get_page_head" from __get_page_tail_foll).
I am sure I missed something. But I am curious and I'd like to understand
what I have missed.
Thanks,
Oleg.
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -210,7 +210,7 @@ EXPORT_SYMBOL(put_page);
* This function is exported but must not be called by anything other
* than get_page(). It implements the slow path of get_page().
*/
-bool __get_page_tail(struct page *page)
+static struct page *__get_compound_head(struct page *page, bool and_tail)
{
/*
* This takes care of get_page() if run on a tail page
@@ -234,8 +234,9 @@ bool __get_page_tail(struct page *page)
* cannot race here.
*/
VM_BUG_ON(!PageHead(page_head));
- __get_page_tail_foll(page, false);
- return true;
+ if (and_tail)
+ get_huge_page_tail(page);
+ return page_head;
} else {
/*
* __split_huge_page_refcount run
@@ -260,17 +261,34 @@ bool __get_page_tail(struct page *page)
flags = compound_lock_irqsave(page_head);
/* here __split_huge_page_refcount won't run anymore */
if (likely(PageTail(page))) {
- __get_page_tail_foll(page, false);
+ if (and_tail)
+ get_huge_page_tail(page);
got = true;
}
compound_unlock_irqrestore(page_head, flags);
- if (unlikely(!got))
+
+ if (likely(got))
+ return page_head;
+ else
put_page(page_head);
}
- return got;
+ return NULL;
+}
+
+bool __get_page_tail(struct page *page)
+{
+ return !!__get_compound_head(page, true);
}
EXPORT_SYMBOL(__get_page_tail);
+struct page *get_compound_head(struct page *page)
+{
+ if (PageTail(page))
+ return __get_compound_head(page, false);
+ else
+ return NULL;
+}
+
/**
* put_pages_list() - release a list of pages
* @pages: list of pages threaded on page->lru
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists