diff options
Diffstat (limited to 'include/linux/page-flags.h')
| -rw-r--r-- | include/linux/page-flags.h | 128 | 
1 files changed, 75 insertions, 53 deletions
| diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index e5a32445f930..74e4dda91238 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -129,6 +129,9 @@ enum pageflags {  	/* Compound pages. Stored in first tail page's flags */  	PG_double_map = PG_private_2, + +	/* non-lru isolated movable page */ +	PG_isolated = PG_reclaim,  };  #ifndef __GENERATING_BOUNDS_H @@ -292,11 +295,11 @@ PAGEFLAG(OwnerPriv1, owner_priv_1, PF_ANY)   */  TESTPAGEFLAG(Writeback, writeback, PF_NO_COMPOUND)  	TESTSCFLAG(Writeback, writeback, PF_NO_COMPOUND) -PAGEFLAG(MappedToDisk, mappedtodisk, PF_NO_COMPOUND) +PAGEFLAG(MappedToDisk, mappedtodisk, PF_NO_TAIL)  /* PG_readahead is only used for reads; PG_reclaim is only for writes */ -PAGEFLAG(Reclaim, reclaim, PF_NO_COMPOUND) -	TESTCLEARFLAG(Reclaim, reclaim, PF_NO_COMPOUND) +PAGEFLAG(Reclaim, reclaim, PF_NO_TAIL) +	TESTCLEARFLAG(Reclaim, reclaim, PF_NO_TAIL)  PAGEFLAG(Readahead, reclaim, PF_NO_COMPOUND)  	TESTCLEARFLAG(Readahead, reclaim, PF_NO_COMPOUND) @@ -357,29 +360,37 @@ PAGEFLAG(Idle, idle, PF_ANY)   * with the PAGE_MAPPING_ANON bit set to distinguish it.  See rmap.h.   *   * On an anonymous page in a VM_MERGEABLE area, if CONFIG_KSM is enabled, - * the PAGE_MAPPING_KSM bit may be set along with the PAGE_MAPPING_ANON bit; - * and then page->mapping points, not to an anon_vma, but to a private + * the PAGE_MAPPING_MOVABLE bit may be set along with the PAGE_MAPPING_ANON + * bit; and then page->mapping points, not to an anon_vma, but to a private   * structure which KSM associates with that merged page.  See ksm.h.   * - * PAGE_MAPPING_KSM without PAGE_MAPPING_ANON is currently never used. + * PAGE_MAPPING_KSM without PAGE_MAPPING_ANON is used for non-lru movable + * page and then page->mapping points a struct address_space.   *   * Please note that, confusingly, "page_mapping" refers to the inode   * address_space which maps the page from disk; whereas "page_mapped"   * refers to user virtual address space into which the page is mapped.   */ -#define PAGE_MAPPING_ANON	1 -#define PAGE_MAPPING_KSM	2 -#define PAGE_MAPPING_FLAGS	(PAGE_MAPPING_ANON | PAGE_MAPPING_KSM) +#define PAGE_MAPPING_ANON	0x1 +#define PAGE_MAPPING_MOVABLE	0x2 +#define PAGE_MAPPING_KSM	(PAGE_MAPPING_ANON | PAGE_MAPPING_MOVABLE) +#define PAGE_MAPPING_FLAGS	(PAGE_MAPPING_ANON | PAGE_MAPPING_MOVABLE) -static __always_inline int PageAnonHead(struct page *page) +static __always_inline int PageMappingFlags(struct page *page)  { -	return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; +	return ((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) != 0;  }  static __always_inline int PageAnon(struct page *page)  {  	page = compound_head(page); -	return PageAnonHead(page); +	return ((unsigned long)page->mapping & PAGE_MAPPING_ANON) != 0; +} + +static __always_inline int __PageMovable(struct page *page) +{ +	return ((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) == +				PAGE_MAPPING_MOVABLE;  }  #ifdef CONFIG_KSM @@ -393,7 +404,7 @@ static __always_inline int PageKsm(struct page *page)  {  	page = compound_head(page);  	return ((unsigned long)page->mapping & PAGE_MAPPING_FLAGS) == -				(PAGE_MAPPING_ANON | PAGE_MAPPING_KSM); +				PAGE_MAPPING_KSM;  }  #else  TESTPAGEFLAG_FALSE(Ksm) @@ -570,6 +581,17 @@ static inline int PageDoubleMap(struct page *page)  	return PageHead(page) && test_bit(PG_double_map, &page[1].flags);  } +static inline void SetPageDoubleMap(struct page *page) +{ +	VM_BUG_ON_PAGE(!PageHead(page), page); +	set_bit(PG_double_map, &page[1].flags); +} + +static inline void ClearPageDoubleMap(struct page *page) +{ +	VM_BUG_ON_PAGE(!PageHead(page), page); +	clear_bit(PG_double_map, &page[1].flags); +}  static inline int TestSetPageDoubleMap(struct page *page)  {  	VM_BUG_ON_PAGE(!PageHead(page), page); @@ -587,59 +609,59 @@ TESTPAGEFLAG_FALSE(TransHuge)  TESTPAGEFLAG_FALSE(TransCompound)  TESTPAGEFLAG_FALSE(TransCompoundMap)  TESTPAGEFLAG_FALSE(TransTail) -TESTPAGEFLAG_FALSE(DoubleMap) +PAGEFLAG_FALSE(DoubleMap)  	TESTSETFLAG_FALSE(DoubleMap)  	TESTCLEARFLAG_FALSE(DoubleMap)  #endif  /* + * For pages that are never mapped to userspace, page->mapcount may be + * used for storing extra information about page type. Any value used + * for this purpose must be <= -2, but it's better start not too close + * to -2 so that an underflow of the page_mapcount() won't be mistaken + * for a special page. + */ +#define PAGE_MAPCOUNT_OPS(uname, lname)					\ +static __always_inline int Page##uname(struct page *page)		\ +{									\ +	return atomic_read(&page->_mapcount) ==				\ +				PAGE_##lname##_MAPCOUNT_VALUE;		\ +}									\ +static __always_inline void __SetPage##uname(struct page *page)		\ +{									\ +	VM_BUG_ON_PAGE(atomic_read(&page->_mapcount) != -1, page);	\ +	atomic_set(&page->_mapcount, PAGE_##lname##_MAPCOUNT_VALUE);	\ +}									\ +static __always_inline void __ClearPage##uname(struct page *page)	\ +{									\ +	VM_BUG_ON_PAGE(!Page##uname(page), page);			\ +	atomic_set(&page->_mapcount, -1);				\ +} + +/*   * PageBuddy() indicate that the page is free and in the buddy system   * (see mm/page_alloc.c). - * - * PAGE_BUDDY_MAPCOUNT_VALUE must be <= -2 but better not too close to - * -2 so that an underflow of the page_mapcount() won't be mistaken - * for a genuine PAGE_BUDDY_MAPCOUNT_VALUE. -128 can be created very - * efficiently by most CPU architectures.   */ -#define PAGE_BUDDY_MAPCOUNT_VALUE (-128) - -static inline int PageBuddy(struct page *page) -{ -	return atomic_read(&page->_mapcount) == PAGE_BUDDY_MAPCOUNT_VALUE; -} +#define PAGE_BUDDY_MAPCOUNT_VALUE		(-128) +PAGE_MAPCOUNT_OPS(Buddy, BUDDY) -static inline void __SetPageBuddy(struct page *page) -{ -	VM_BUG_ON_PAGE(atomic_read(&page->_mapcount) != -1, page); -	atomic_set(&page->_mapcount, PAGE_BUDDY_MAPCOUNT_VALUE); -} +/* + * PageBalloon() is set on pages that are on the balloon page list + * (see mm/balloon_compaction.c). + */ +#define PAGE_BALLOON_MAPCOUNT_VALUE		(-256) +PAGE_MAPCOUNT_OPS(Balloon, BALLOON) -static inline void __ClearPageBuddy(struct page *page) -{ -	VM_BUG_ON_PAGE(!PageBuddy(page), page); -	atomic_set(&page->_mapcount, -1); -} +/* + * If kmemcg is enabled, the buddy allocator will set PageKmemcg() on + * pages allocated with __GFP_ACCOUNT. It gets cleared on page free. + */ +#define PAGE_KMEMCG_MAPCOUNT_VALUE		(-512) +PAGE_MAPCOUNT_OPS(Kmemcg, KMEMCG)  extern bool is_free_buddy_page(struct page *page); -#define PAGE_BALLOON_MAPCOUNT_VALUE (-256) - -static inline int PageBalloon(struct page *page) -{ -	return atomic_read(&page->_mapcount) == PAGE_BALLOON_MAPCOUNT_VALUE; -} - -static inline void __SetPageBalloon(struct page *page) -{ -	VM_BUG_ON_PAGE(atomic_read(&page->_mapcount) != -1, page); -	atomic_set(&page->_mapcount, PAGE_BALLOON_MAPCOUNT_VALUE); -} - -static inline void __ClearPageBalloon(struct page *page) -{ -	VM_BUG_ON_PAGE(!PageBalloon(page), page); -	atomic_set(&page->_mapcount, -1); -} +__PAGEFLAG(Isolated, isolated, PF_ANY);  /*   * If network-based swap is enabled, sl*b must keep track of whether pages |