During page isolation, the original migratetype is overwritten, since MIGRATE_* are enums. Change MIGRATE_ISOLATE to be a standalone bit like PB_migrate_skip. pageblock bits needs to be word aligned, so expand the number of pageblock bits from 4 to 8 and make migrate isolate bit 7. Signed-off-by: Zi Yan <ziy@xxxxxxxxxx> --- include/linux/mmzone.h | 24 ++++++++++++++++++++---- include/linux/page-isolation.h | 2 +- include/linux/pageblock-flags.h | 29 ++++++++++++++++++++++++++++- mm/page_alloc.c | 22 ++++++++++++++++++++-- 4 files changed, 69 insertions(+), 8 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 17506e4a2835..5191a90b94f9 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -108,12 +108,28 @@ extern int page_group_by_mobility_disabled; #define MIGRATETYPE_MASK ((1UL << PB_migratetype_bits) - 1) -#define get_pageblock_migratetype(page) \ - get_pfnblock_flags_mask(page, page_to_pfn(page), MIGRATETYPE_MASK) +#ifdef CONFIG_MEMORY_ISOLATION +#define get_pageblock_migratetype(page) \ + (get_pageblock_isolate(page) ? \ + MIGRATE_ISOLATE : \ + get_pfnblock_flags_mask(page, page_to_pfn(page), \ + MIGRATETYPE_MASK)) + +#define folio_migratetype(folio) \ + (get_pageblock_isolate(&folio->page) ? \ + MIGRATE_ISOLATE : \ + get_pfnblock_flags_mask(&folio->page, folio_pfn(folio), \ + MIGRATETYPE_MASK)) +#else +#define get_pageblock_migratetype(page) \ + get_pfnblock_flags_mask(page, page_to_pfn(page), \ + MIGRATETYPE_MASK) -#define folio_migratetype(folio) \ - get_pfnblock_flags_mask(&folio->page, folio_pfn(folio), \ +#define folio_migratetype(folio) \ + get_pfnblock_flags_mask(&folio->page, folio_pfn(folio), \ MIGRATETYPE_MASK) +#endif + struct free_area { struct list_head free_list[MIGRATE_TYPES]; unsigned long nr_free; diff --git a/include/linux/page-isolation.h b/include/linux/page-isolation.h index c16db0067090..11b8695115ea 100644 --- a/include/linux/page-isolation.h +++ b/include/linux/page-isolation.h @@ -9,7 +9,7 @@ static inline bool has_isolate_pageblock(struct zone *zone) } static inline bool is_migrate_isolate_page(struct page *page) { - return get_pageblock_migratetype(page) == MIGRATE_ISOLATE; + return get_pageblock_isolate(page); } static inline bool is_migrate_isolate(int migratetype) { diff --git a/include/linux/pageblock-flags.h b/include/linux/pageblock-flags.h index fc6b9c87cb0a..a8121cab4b4f 100644 --- a/include/linux/pageblock-flags.h +++ b/include/linux/pageblock-flags.h @@ -20,7 +20,10 @@ enum pageblock_bits { PB_migrate_end = PB_migrate + PB_migratetype_bits - 1, /* 3 bits required for migrate types */ PB_migrate_skip,/* If set the block is skipped by compaction */ - +#ifdef CONFIG_MEMORY_ISOLATION + PB_migrate_isolate = 7, /* If set the block is isolated */ + /* set it to 7 to make pageblock bit word aligned */ +#endif /* * Assume the bits will always align on a word. If this assumption * changes then get/set pageblock needs updating. @@ -99,4 +102,28 @@ static inline void set_pageblock_skip(struct page *page) } #endif /* CONFIG_COMPACTION */ +#ifdef CONFIG_MEMORY_ISOLATION +#define get_pageblock_isolate(page) \ + get_pfnblock_flags_mask(page, page_to_pfn(page), \ + (1 << (PB_migrate_isolate))) +#define clear_pageblock_isolate(page) \ + set_pfnblock_flags_mask(page, 0, page_to_pfn(page), \ + (1 << PB_migrate_isolate)) +#define set_pageblock_isolate(page) \ + set_pfnblock_flags_mask(page, (1 << PB_migrate_isolate), \ + page_to_pfn(page), \ + (1 << PB_migrate_isolate)) +#else +static inline bool get_pageblock_isolate(struct page *page) +{ + return false; +} +static inline void clear_pageblock_isolate(struct page *page) +{ +} +static inline void set_pageblock_isolate(struct page *page) +{ +} +#endif /* CONFIG_MEMORY_ISOLATION */ + #endif /* PAGEBLOCK_FLAGS_H */ diff --git a/mm/page_alloc.c b/mm/page_alloc.c index c2ffccf9d213..4ea5cd1a07e2 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -380,7 +380,12 @@ unsigned long get_pfnblock_flags_mask(const struct page *page, static __always_inline int get_pfnblock_migratetype(const struct page *page, unsigned long pfn) { - return get_pfnblock_flags_mask(page, pfn, MIGRATETYPE_MASK); + return +#ifdef CONFIG_MEMORY_ISOLATION + get_pageblock_isolate(page) ? + MIGRATE_ISOLATE : +#endif + get_pfnblock_flags_mask(page, pfn, MIGRATETYPE_MASK); } /** @@ -398,7 +403,11 @@ void set_pfnblock_flags_mask(struct page *page, unsigned long flags, unsigned long bitidx, word_bitidx; unsigned long word; +#ifdef CONFIG_MEMORY_ISOLATION + BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 8); +#else BUILD_BUG_ON(NR_PAGEBLOCK_BITS != 4); +#endif BUILD_BUG_ON(MIGRATE_TYPES > (1 << PB_migratetype_bits)); bitmap = get_pageblock_bitmap(page, pfn); @@ -422,8 +431,17 @@ void set_pageblock_migratetype(struct page *page, int migratetype) migratetype < MIGRATE_PCPTYPES)) migratetype = MIGRATE_UNMOVABLE; - set_pfnblock_flags_mask(page, (unsigned long)migratetype, +#ifdef CONFIG_MEMORY_ISOLATION + if (migratetype == MIGRATE_ISOLATE) + set_pageblock_isolate(page); + else +#endif + { + if (get_pageblock_isolate(page)) + clear_pageblock_isolate(page); + set_pfnblock_flags_mask(page, (unsigned long)migratetype, page_to_pfn(page), MIGRATETYPE_MASK); + } } #ifdef CONFIG_DEBUG_VM -- 2.45.2