aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/page-flags.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/linux/page-flags.h')
-rw-r--r--include/linux/page-flags.h82
1 files changed, 19 insertions, 63 deletions
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 416509e26d6d..bb53c7b86315 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -86,12 +86,7 @@ enum pageflags {
86 PG_private, /* If pagecache, has fs-private data */ 86 PG_private, /* If pagecache, has fs-private data */
87 PG_private_2, /* If pagecache, has fs aux data */ 87 PG_private_2, /* If pagecache, has fs aux data */
88 PG_writeback, /* Page is under writeback */ 88 PG_writeback, /* Page is under writeback */
89#ifdef CONFIG_PAGEFLAGS_EXTENDED
90 PG_head, /* A head page */ 89 PG_head, /* A head page */
91 PG_tail, /* A tail page */
92#else
93 PG_compound, /* A compound page */
94#endif
95 PG_swapcache, /* Swap page: swp_entry_t in private */ 90 PG_swapcache, /* Swap page: swp_entry_t in private */
96 PG_mappedtodisk, /* Has blocks allocated on-disk */ 91 PG_mappedtodisk, /* Has blocks allocated on-disk */
97 PG_reclaim, /* To be reclaimed asap */ 92 PG_reclaim, /* To be reclaimed asap */
@@ -256,7 +251,7 @@ PAGEFLAG(Readahead, reclaim) TESTCLEARFLAG(Readahead, reclaim)
256 * Must use a macro here due to header dependency issues. page_zone() is not 251 * Must use a macro here due to header dependency issues. page_zone() is not
257 * available at this point. 252 * available at this point.
258 */ 253 */
259#define PageHighMem(__p) is_highmem(page_zone(__p)) 254#define PageHighMem(__p) is_highmem_idx(page_zonenum(__p))
260#else 255#else
261PAGEFLAG_FALSE(HighMem) 256PAGEFLAG_FALSE(HighMem)
262#endif 257#endif
@@ -398,85 +393,46 @@ static inline void set_page_writeback_keepwrite(struct page *page)
398 test_set_page_writeback_keepwrite(page); 393 test_set_page_writeback_keepwrite(page);
399} 394}
400 395
401#ifdef CONFIG_PAGEFLAGS_EXTENDED
402/*
403 * System with lots of page flags available. This allows separate
404 * flags for PageHead() and PageTail() checks of compound pages so that bit
405 * tests can be used in performance sensitive paths. PageCompound is
406 * generally not used in hot code paths except arch/powerpc/mm/init_64.c
407 * and arch/powerpc/kvm/book3s_64_vio_hv.c which use it to detect huge pages
408 * and avoid handling those in real mode.
409 */
410__PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head) 396__PAGEFLAG(Head, head) CLEARPAGEFLAG(Head, head)
411__PAGEFLAG(Tail, tail)
412 397
413static inline int PageCompound(struct page *page) 398static inline int PageTail(struct page *page)
414{
415 return page->flags & ((1L << PG_head) | (1L << PG_tail));
416
417}
418#ifdef CONFIG_TRANSPARENT_HUGEPAGE
419static inline void ClearPageCompound(struct page *page)
420{ 399{
421 BUG_ON(!PageHead(page)); 400 return READ_ONCE(page->compound_head) & 1;
422 ClearPageHead(page);
423} 401}
424#endif
425
426#define PG_head_mask ((1L << PG_head))
427 402
428#else 403static inline void set_compound_head(struct page *page, struct page *head)
429/*
430 * Reduce page flag use as much as possible by overlapping
431 * compound page flags with the flags used for page cache pages. Possible
432 * because PageCompound is always set for compound pages and not for
433 * pages on the LRU and/or pagecache.
434 */
435TESTPAGEFLAG(Compound, compound)
436__SETPAGEFLAG(Head, compound) __CLEARPAGEFLAG(Head, compound)
437
438/*
439 * PG_reclaim is used in combination with PG_compound to mark the
440 * head and tail of a compound page. This saves one page flag
441 * but makes it impossible to use compound pages for the page cache.
442 * The PG_reclaim bit would have to be used for reclaim or readahead
443 * if compound pages enter the page cache.
444 *
445 * PG_compound & PG_reclaim => Tail page
446 * PG_compound & ~PG_reclaim => Head page
447 */
448#define PG_head_mask ((1L << PG_compound))
449#define PG_head_tail_mask ((1L << PG_compound) | (1L << PG_reclaim))
450
451static inline int PageHead(struct page *page)
452{ 404{
453 return ((page->flags & PG_head_tail_mask) == PG_head_mask); 405 WRITE_ONCE(page->compound_head, (unsigned long)head + 1);
454} 406}
455 407
456static inline int PageTail(struct page *page) 408static inline void clear_compound_head(struct page *page)
457{ 409{
458 return ((page->flags & PG_head_tail_mask) == PG_head_tail_mask); 410 WRITE_ONCE(page->compound_head, 0);
459} 411}
460 412
461static inline void __SetPageTail(struct page *page) 413static inline struct page *compound_head(struct page *page)
462{ 414{
463 page->flags |= PG_head_tail_mask; 415 unsigned long head = READ_ONCE(page->compound_head);
416
417 if (unlikely(head & 1))
418 return (struct page *) (head - 1);
419 return page;
464} 420}
465 421
466static inline void __ClearPageTail(struct page *page) 422static inline int PageCompound(struct page *page)
467{ 423{
468 page->flags &= ~PG_head_tail_mask; 424 return PageHead(page) || PageTail(page);
469}
470 425
426}
471#ifdef CONFIG_TRANSPARENT_HUGEPAGE 427#ifdef CONFIG_TRANSPARENT_HUGEPAGE
472static inline void ClearPageCompound(struct page *page) 428static inline void ClearPageCompound(struct page *page)
473{ 429{
474 BUG_ON((page->flags & PG_head_tail_mask) != (1 << PG_compound)); 430 BUG_ON(!PageHead(page));
475 clear_bit(PG_compound, &page->flags); 431 ClearPageHead(page);
476} 432}
477#endif 433#endif
478 434
479#endif /* !PAGEFLAGS_EXTENDED */ 435#define PG_head_mask ((1L << PG_head))
480 436
481#ifdef CONFIG_HUGETLB_PAGE 437#ifdef CONFIG_HUGETLB_PAGE
482int PageHuge(struct page *page); 438int PageHuge(struct page *page);