compound_trans_head
PATCH 1/1 compound_trans_head
Hello Andrew,
this is the third and last patch and it should apply clean at the end. It cleanup some code in KVM and KSM with an helper.
=======
Subject: add compound_trans_head helper
From: Andrea Arcangeli <[email protected]>
Cleanup some code with common compound_trans_head helper.
Signed-off-by Andrea Arcangeli <[email protected]>
--- include/linux/huge_mm.h | 18 ++++++++++++++++++ mm/ksm.c | 15 +++------------ virt/kvm/kvm_main.c | 38 ++++++++++++++------------------------ 3 files changed, 35 insertions(+), 36 deletions(-)
include/linux/huge_mm.h +18 -0
@@ -126,6 +126,23 @@ static inline int hpage_nr_pages(structreturn 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 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) {
mm/ksm.c +3 -12
@@ -415,20 +415,11 @@ out: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; }
virt/kvm/kvm_main.c +14 -24
@@ -103,34 +103,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); }
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Fight unfair telecom policy in Canada: sign http://dissolvethecrtc.ca/
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>