diff --git a/include/linux/hugetlb.h b/include/linux/hugetlb.h index 6b4890fa57e7191574da1efe41eec956077d72ae..feaf0c7fb7d8715fc43257be5a0f4f89dc9668e0 100644 --- a/include/linux/hugetlb.h +++ b/include/linux/hugetlb.h @@ -358,6 +358,17 @@ static inline int hstate_index(struct hstate *h) return h - hstates; } +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 /* CONFIG_HUGETLB_PAGE */ struct hstate {}; #define alloc_huge_page_node(h, nid) NULL @@ -378,6 +389,11 @@ static inline unsigned int pages_per_huge_page(struct hstate *h) } #define hstate_index_to_shift(index) 0 #define hstate_index(h) 0 + +static inline pgoff_t basepage_index(struct page *page) +{ + return page->index; +} #endif /* CONFIG_HUGETLB_PAGE */ #endif /* _LINUX_HUGETLB_H */ diff --git a/kernel/futex.c b/kernel/futex.c index b26dcfc02c9489b3ca00bfd076f2208bb4964366..49dacfb4574563b61551a436a21a2fc33053e47f 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -61,6 +61,7 @@ #include #include #include +#include #include @@ -365,7 +366,7 @@ get_futex_key(u32 __user *uaddr, int fshared, union futex_key *key, int rw) } 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 f8feeeca6686543713a1dada46759b60b2eae240..aea87ced4268edde3973c0f47394c345c8f997ab 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -690,6 +690,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;