diff options
Diffstat (limited to 'include/linux/page-flags.h')
-rw-r--r-- | include/linux/page-flags.h | 82 |
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 |
261 | PAGEFLAG_FALSE(HighMem) | 256 | PAGEFLAG_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 | ||
413 | static inline int PageCompound(struct page *page) | 398 | static inline int PageTail(struct page *page) |
414 | { | ||
415 | return page->flags & ((1L << PG_head) | (1L << PG_tail)); | ||
416 | |||
417 | } | ||
418 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
419 | static 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 | 403 | static 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 | */ | ||
435 | TESTPAGEFLAG(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 | |||
451 | static 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 | ||
456 | static inline int PageTail(struct page *page) | 408 | static 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 | ||
461 | static inline void __SetPageTail(struct page *page) | 413 | static 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 | ||
466 | static inline void __ClearPageTail(struct page *page) | 422 | static 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 |
472 | static inline void ClearPageCompound(struct page *page) | 428 | static 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 |
482 | int PageHuge(struct page *page); | 438 | int PageHuge(struct page *page); |