thp: add compound_trans_head() helper
Cleanup some code with common compound_trans_head helper. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Cc: Hugh Dickins <hughd@google.com> Cc: Johannes Weiner <jweiner@redhat.com> Cc: Marcelo Tosatti <mtosatti@redhat.com> Cc: Avi Kivity <avi@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
29ad768cfc
commit
22e5c47ee2
3 changed files with 35 additions and 36 deletions
|
@ -126,6 +126,23 @@ static inline int hpage_nr_pages(struct page *page)
|
|||
return HPAGE_PMD_NR;
|
||||
return 1;
|
||||
}
|
||||
static inline struct page *compound_trans_head(struct page *page)
|
||||
{
|
||||
if (PageTail(page)) {
|
||||
struct page *head;
|
||||
head = page->first_page;
|
||||
smp_rmb();
|
||||
/*
|
||||
* head may be a dangling pointer.
|
||||
* __split_huge_page_refcount clears PageTail before
|
||||
* overwriting first_page, so if PageTail is still
|
||||
* there it means the head pointer isn't dangling.
|
||||
*/
|
||||
if (PageTail(page))
|
||||
return head;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
#define HPAGE_PMD_SHIFT ({ BUG(); 0; })
|
||||
#define HPAGE_PMD_MASK ({ BUG(); 0; })
|
||||
|
@ -144,6 +161,7 @@ static inline int split_huge_page(struct page *page)
|
|||
do { } while (0)
|
||||
#define wait_split_huge_page(__anon_vma, __pmd) \
|
||||
do { } while (0)
|
||||
#define compound_trans_head(page) compound_head(page)
|
||||
static inline int hugepage_madvise(struct vm_area_struct *vma,
|
||||
unsigned long *vm_flags, int advice)
|
||||
{
|
||||
|
|
15
mm/ksm.c
15
mm/ksm.c
|
@ -415,20 +415,11 @@ static void break_cow(struct rmap_item *rmap_item)
|
|||
static struct page *page_trans_compound_anon(struct page *page)
|
||||
{
|
||||
if (PageTransCompound(page)) {
|
||||
struct page *head;
|
||||
head = compound_head(page);
|
||||
struct page *head = compound_trans_head(page);
|
||||
/*
|
||||
* head may be a dangling pointer.
|
||||
* __split_huge_page_refcount clears PageTail
|
||||
* before overwriting first_page, so if
|
||||
* PageTail is still there it means the head
|
||||
* pointer isn't dangling.
|
||||
* head may actually be splitted and freed from under
|
||||
* us but it's ok here.
|
||||
*/
|
||||
if (head != page) {
|
||||
smp_rmb();
|
||||
if (!PageTransCompound(page))
|
||||
return NULL;
|
||||
}
|
||||
if (PageAnon(head))
|
||||
return head;
|
||||
}
|
||||
|
|
|
@ -104,34 +104,24 @@ static pfn_t fault_pfn;
|
|||
inline int kvm_is_mmio_pfn(pfn_t pfn)
|
||||
{
|
||||
if (pfn_valid(pfn)) {
|
||||
struct page *head;
|
||||
int reserved;
|
||||
struct page *tail = pfn_to_page(pfn);
|
||||
head = compound_head(tail);
|
||||
struct page *head = compound_trans_head(tail);
|
||||
reserved = PageReserved(head);
|
||||
if (head != tail) {
|
||||
smp_rmb();
|
||||
/*
|
||||
* head may be a dangling pointer.
|
||||
* __split_huge_page_refcount clears PageTail
|
||||
* before overwriting first_page, so if
|
||||
* PageTail is still there it means the head
|
||||
* pointer isn't dangling.
|
||||
* "head" is not a dangling pointer
|
||||
* (compound_trans_head takes care of that)
|
||||
* but the hugepage may have been splitted
|
||||
* from under us (and we may not hold a
|
||||
* reference count on the head page so it can
|
||||
* be reused before we run PageReferenced), so
|
||||
* we've to check PageTail before returning
|
||||
* what we just read.
|
||||
*/
|
||||
if (PageTail(tail)) {
|
||||
/*
|
||||
* the "head" is not a dangling
|
||||
* pointer but the hugepage may have
|
||||
* been splitted from under us (and we
|
||||
* may not hold a reference count on
|
||||
* the head page so it can be reused
|
||||
* before we run PageReferenced), so
|
||||
* we've to recheck PageTail before
|
||||
* returning what we just read.
|
||||
*/
|
||||
int reserved = PageReserved(head);
|
||||
smp_rmb();
|
||||
if (PageTail(tail))
|
||||
return reserved;
|
||||
}
|
||||
smp_rmb();
|
||||
if (PageTail(tail))
|
||||
return reserved;
|
||||
}
|
||||
return PageReserved(tail);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue