diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/mm.h | 33 | ||||
-rw-r--r-- | include/linux/page-flags.h | 14 |
2 files changed, 42 insertions, 5 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index c95d96ebd5ad..8c149fa4491d 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) | |||
267 | return atomic_inc_not_zero(&page->_count); | 267 | return atomic_inc_not_zero(&page->_count); |
268 | } | 268 | } |
269 | 269 | ||
270 | static inline struct page *compound_head(struct page *page) | ||
271 | { | ||
272 | /* | ||
273 | * We could avoid the PageCompound(page) check if | ||
274 | * we would not overload PageTail(). | ||
275 | * | ||
276 | * This check has to be done in several performance critical | ||
277 | * paths of the slab etc. IMHO PageTail deserves its own flag. | ||
278 | */ | ||
279 | if (unlikely(PageCompound(page) && PageTail(page))) | ||
280 | return page->first_page; | ||
281 | return page; | ||
282 | } | ||
283 | |||
270 | static inline int page_count(struct page *page) | 284 | static inline int page_count(struct page *page) |
271 | { | 285 | { |
272 | if (unlikely(PageCompound(page))) | 286 | return atomic_read(&compound_head(page)->_count); |
273 | page = (struct page *)page_private(page); | ||
274 | return atomic_read(&page->_count); | ||
275 | } | 287 | } |
276 | 288 | ||
277 | static inline void get_page(struct page *page) | 289 | static inline void get_page(struct page *page) |
278 | { | 290 | { |
279 | if (unlikely(PageCompound(page))) | 291 | page = compound_head(page); |
280 | page = (struct page *)page_private(page); | ||
281 | VM_BUG_ON(atomic_read(&page->_count) == 0); | 292 | VM_BUG_ON(atomic_read(&page->_count) == 0); |
282 | atomic_inc(&page->_count); | 293 | atomic_inc(&page->_count); |
283 | } | 294 | } |
@@ -314,6 +325,18 @@ static inline compound_page_dtor *get_compound_page_dtor(struct page *page) | |||
314 | return (compound_page_dtor *)page[1].lru.next; | 325 | return (compound_page_dtor *)page[1].lru.next; |
315 | } | 326 | } |
316 | 327 | ||
328 | static inline int compound_order(struct page *page) | ||
329 | { | ||
330 | if (!PageCompound(page) || PageTail(page)) | ||
331 | return 0; | ||
332 | return (unsigned long)page[1].lru.prev; | ||
333 | } | ||
334 | |||
335 | static inline void set_compound_order(struct page *page, unsigned long order) | ||
336 | { | ||
337 | page[1].lru.prev = (void *)order; | ||
338 | } | ||
339 | |||
317 | /* | 340 | /* |
318 | * Multiple processes may "see" the same page. E.g. for untouched | 341 | * Multiple processes may "see" the same page. E.g. for untouched |
319 | * mappings of /dev/null, all processes see the same page full of | 342 | * mappings of /dev/null, all processes see the same page full of |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 96326594e55d..a1e143634946 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -94,6 +94,12 @@ | |||
94 | /* PG_owner_priv_1 users should have descriptive aliases */ | 94 | /* PG_owner_priv_1 users should have descriptive aliases */ |
95 | #define PG_checked PG_owner_priv_1 /* Used by some filesystems */ | 95 | #define PG_checked PG_owner_priv_1 /* Used by some filesystems */ |
96 | 96 | ||
97 | /* | ||
98 | * Marks tail portion of a compound page. We currently do not reclaim | ||
99 | * compound pages so we can reuse a flag only used for reclaim here. | ||
100 | */ | ||
101 | #define PG_tail PG_reclaim | ||
102 | |||
97 | #if (BITS_PER_LONG > 32) | 103 | #if (BITS_PER_LONG > 32) |
98 | /* | 104 | /* |
99 | * 64-bit-only flags build down from bit 31 | 105 | * 64-bit-only flags build down from bit 31 |
@@ -241,6 +247,14 @@ static inline void SetPageUptodate(struct page *page) | |||
241 | #define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags) | 247 | #define __SetPageCompound(page) __set_bit(PG_compound, &(page)->flags) |
242 | #define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags) | 248 | #define __ClearPageCompound(page) __clear_bit(PG_compound, &(page)->flags) |
243 | 249 | ||
250 | /* | ||
251 | * Note: PG_tail is an alias of another page flag. The result of PageTail() | ||
252 | * is only valid if PageCompound(page) is true. | ||
253 | */ | ||
254 | #define PageTail(page) test_bit(PG_tail, &(page)->flags) | ||
255 | #define __SetPageTail(page) __set_bit(PG_tail, &(page)->flags) | ||
256 | #define __ClearPageTail(page) __clear_bit(PG_tail, &(page)->flags) | ||
257 | |||
244 | #ifdef CONFIG_SWAP | 258 | #ifdef CONFIG_SWAP |
245 | #define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) | 259 | #define PageSwapCache(page) test_bit(PG_swapcache, &(page)->flags) |
246 | #define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags) | 260 | #define SetPageSwapCache(page) set_bit(PG_swapcache, &(page)->flags) |