diff options
-rw-r--r-- | include/linux/hugetlb.h | 16 | ||||
-rw-r--r-- | kernel/futex.c | 3 | ||||
-rw-r--r-- | mm/hugetlb.c | 17 |
3 files changed, 35 insertions, 1 deletions
diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 59225ef..db70f1b 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -313,6 +313,17 @@ static inline unsigned hstate_index_to_shift(unsigned index) return hstates[index].order + PAGE_SHIFT; } +pgoff_t __basepage_index(struct page *page); + +/* Return page->index in PAGE_SIZE units */ +static inline pgoff_t basepage_index(struct page *page) +{ + if (!PageCompound(page)) + return page->index; + + return __basepage_index(page); +} + #else struct hstate {}; #define alloc_huge_page_node(h, nid) NULL @@ -331,6 +342,11 @@ static inline unsigned int pages_per_huge_page(struct hstate *h) return 1; } #define hstate_index_to_shift(index) 0 + +static inline pgoff_t basepage_index(struct page *page) +{ + return page->index; +} #endif #endif /* _LINUX_HUGETLB_H */ diff --git a/kernel/futex.c b/kernel/futex.c index 91691e9..5c305c0 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -60,6 +60,7 @@ #include <linux/pid.h> #include <linux/nsproxy.h> #include <linux/ptrace.h> +#include <linux/hugetlb.h> #include <asm/futex.h> @@ -363,7 +364,7 @@ again: } else { key->both.offset |= FUT_OFF_INODE; /* inode-based key */ key->shared.inode = page_head->mapping->host; - key->shared.pgoff = page_head->index; + key->shared.pgoff = basepage_index(page); } get_futex_key_refs(key); diff --git a/mm/hugetlb.c b/mm/hugetlb.c index a3498eb..6fdad25 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -602,6 +602,23 @@ int PageHuge(struct page *page) EXPORT_SYMBOL_GPL(PageHuge); +pgoff_t __basepage_index(struct page *page) +{ + struct page *page_head = compound_head(page); + pgoff_t index = page_index(page_head); + unsigned long compound_idx; + + if (!PageHuge(page_head)) + return page_index(page); + + if (compound_order(page_head) >= MAX_ORDER) + compound_idx = page_to_pfn(page) - page_to_pfn(page_head); + else + compound_idx = page - page_head; + + return (index << compound_order(page_head)) + compound_idx; +} + static struct page *alloc_fresh_huge_page_node(struct hstate *h, int nid) { struct page *page; |