diff options
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index c95d96ebd5a..8c149fa4491 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -267,17 +267,28 @@ static inline int get_page_unless_zero(struct page *page) return atomic_inc_not_zero(&page->_count); } +static inline struct page *compound_head(struct page *page) +{ + /* + * We could avoid the PageCompound(page) check if + * we would not overload PageTail(). + * + * This check has to be done in several performance critical + * paths of the slab etc. IMHO PageTail deserves its own flag. + */ + if (unlikely(PageCompound(page) && PageTail(page))) + return page->first_page; + return page; +} + static inline int page_count(struct page *page) { - if (unlikely(PageCompound(page))) - page = (struct page *)page_private(page); - return atomic_read(&page->_count); + return atomic_read(&compound_head(page)->_count); } static inline void get_page(struct page *page) { - if (unlikely(PageCompound(page))) - page = (struct page *)page_private(page); + page = compound_head(page); VM_BUG_ON(atomic_read(&page->_count) == 0); atomic_inc(&page->_count); } @@ -314,6 +325,18 @@ static inline compound_page_dtor *get_compound_page_dtor(struct page *page) return (compound_page_dtor *)page[1].lru.next; } +static inline int compound_order(struct page *page) +{ + if (!PageCompound(page) || PageTail(page)) + return 0; + return (unsigned long)page[1].lru.prev; +} + +static inline void set_compound_order(struct page *page, unsigned long order) +{ + page[1].lru.prev = (void *)order; +} + /* * Multiple processes may "see" the same page. E.g. for untouched * mappings of /dev/null, all processes see the same page full of |