mm: split page_type out from _mapcount
We're already using a union of many fields here, so stop abusing the _mapcount and make page_type its own field. That implies renaming some of the machinery that creates PageBuddy, PageBalloon and PageKmemcg; bring back the PG_buddy, PG_balloon and PG_kmemcg names. As suggested by Kirill, make page_type a bitmask. Because it starts out life as -1 (thanks to sharing the storage with _mapcount), setting a page flag means clearing the appropriate bit. This gives us space for probably twenty or so extra bits (depending how paranoid we want to be about _mapcount underflow). Link: http://lkml.kernel.org/r/20180518194519.3820-3-willy@infradead.org Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com> Acked-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Cc: Christoph Lameter <cl@linux.com> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: Jérôme Glisse <jglisse@redhat.com> Cc: Lai Jiangshan <jiangshanlai@gmail.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Pekka Enberg <penberg@kernel.org> Cc: Randy Dunlap <rdunlap@infradead.org> Cc: Andrey Ryabinin <aryabinin@virtuozzo.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:

committed by
Linus Torvalds

parent
620b4e9031
commit
6e292b9be7
@@ -642,49 +642,56 @@ PAGEFLAG_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.
|
||||
* For pages that are never mapped to userspace (and aren't PageSlab),
|
||||
* page_type may be used. Because it is initialised to -1, we invert the
|
||||
* sense of the bit, so __SetPageFoo *clears* the bit used for PageFoo, and
|
||||
* __ClearPageFoo *sets* the bit used for PageFoo. We reserve a few high and
|
||||
* low bits so that an underflow or overflow of page_mapcount() won't be
|
||||
* mistaken for a page type value.
|
||||
*/
|
||||
#define PAGE_MAPCOUNT_OPS(uname, lname) \
|
||||
|
||||
#define PAGE_TYPE_BASE 0xf0000000
|
||||
/* Reserve 0x0000007f to catch underflows of page_mapcount */
|
||||
#define PG_buddy 0x00000080
|
||||
#define PG_balloon 0x00000100
|
||||
#define PG_kmemcg 0x00000200
|
||||
|
||||
#define PageType(page, flag) \
|
||||
((page->page_type & (PAGE_TYPE_BASE | flag)) == PAGE_TYPE_BASE)
|
||||
|
||||
#define PAGE_TYPE_OPS(uname, lname) \
|
||||
static __always_inline int Page##uname(struct page *page) \
|
||||
{ \
|
||||
return atomic_read(&page->_mapcount) == \
|
||||
PAGE_##lname##_MAPCOUNT_VALUE; \
|
||||
return PageType(page, PG_##lname); \
|
||||
} \
|
||||
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); \
|
||||
VM_BUG_ON_PAGE(!PageType(page, 0), page); \
|
||||
page->page_type &= ~PG_##lname; \
|
||||
} \
|
||||
static __always_inline void __ClearPage##uname(struct page *page) \
|
||||
{ \
|
||||
VM_BUG_ON_PAGE(!Page##uname(page), page); \
|
||||
atomic_set(&page->_mapcount, -1); \
|
||||
page->page_type |= PG_##lname; \
|
||||
}
|
||||
|
||||
/*
|
||||
* PageBuddy() indicate that the page is free and in the buddy system
|
||||
* PageBuddy() indicates that the page is free and in the buddy system
|
||||
* (see mm/page_alloc.c).
|
||||
*/
|
||||
#define PAGE_BUDDY_MAPCOUNT_VALUE (-128)
|
||||
PAGE_MAPCOUNT_OPS(Buddy, BUDDY)
|
||||
PAGE_TYPE_OPS(Buddy, buddy)
|
||||
|
||||
/*
|
||||
* PageBalloon() is set on pages that are on the balloon page list
|
||||
* PageBalloon() is true for pages that are on the balloon page list
|
||||
* (see mm/balloon_compaction.c).
|
||||
*/
|
||||
#define PAGE_BALLOON_MAPCOUNT_VALUE (-256)
|
||||
PAGE_MAPCOUNT_OPS(Balloon, BALLOON)
|
||||
PAGE_TYPE_OPS(Balloon, balloon)
|
||||
|
||||
/*
|
||||
* 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)
|
||||
PAGE_TYPE_OPS(Kmemcg, kmemcg)
|
||||
|
||||
extern bool is_free_buddy_page(struct page *page);
|
||||
|
||||
|
Reference in New Issue
Block a user