diff options
Diffstat (limited to 'include/linux/mm.h')
| -rw-r--r-- | include/linux/mm.h | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index d2b99c852301..c68771c27d88 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -208,24 +208,55 @@ struct page { * Also, many kernel routines increase the page count before a critical * routine so they can be sure the page doesn't go away from under them. */ -#define get_page(p) atomic_inc(&(p)->count) -#define __put_page(p) atomic_dec(&(p)->count) #define put_page_testzero(p) \ ({ \ BUG_ON(page_count(page) == 0); \ atomic_dec_and_test(&(p)->count); \ }) + #define page_count(p) atomic_read(&(p)->count) #define set_page_count(p,v) atomic_set(&(p)->count, v) +#define __put_page(p) atomic_dec(&(p)->count) extern void FASTCALL(__page_cache_release(struct page *)); +#ifdef CONFIG_HUGETLB_PAGE + +static inline void get_page(struct page *page) +{ + if (PageCompound(page)) + page = (struct page *)page->lru.next; + atomic_inc(&page->count); +} + static inline void put_page(struct page *page) { + if (PageCompound(page)) { + page = (struct page *)page->lru.next; + if (page->lru.prev) { /* destructor? */ + (*(void (*)(struct page *))page->lru.prev)(page); + return; + } + } if (!PageReserved(page) && put_page_testzero(page)) __page_cache_release(page); } +#else /* CONFIG_HUGETLB_PAGE */ + +static inline void get_page(struct page *page) +{ + atomic_inc(&page->count); +} + +static inline void put_page(struct page *page) +{ + if (!PageReserved(page) && put_page_testzero(page)) + __page_cache_release(page); +} + +#endif /* CONFIG_HUGETLB_PAGE */ + /* * Multiple processes may "see" the same page. E.g. for untouched * mappings of /dev/null, all processes see the same page full of |
