After we split page_owner's flag from the common page_ext flags, now only 32bit page_idle is using the commt flags. Then we can define a flag for 32bit page_idle only. After this patch, the size of struct page_ext will be 0, so it won't take extra memory overhead for the page_ext which don't use this flag. Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> --- include/linux/page_ext.h | 12 +----------- include/linux/page_idle.h | 39 +++++++++++++++++++++++++++++++++------ mm/page_ext.c | 10 ---------- mm/page_idle.c | 12 ++++++++++++ 4 files changed, 46 insertions(+), 27 deletions(-) diff --git a/include/linux/page_ext.h b/include/linux/page_ext.h index c8ca4954145c..6515d2a62f34 100644 --- a/include/linux/page_ext.h +++ b/include/linux/page_ext.h @@ -15,14 +15,6 @@ struct page_ext_operations { }; #ifdef CONFIG_PAGE_EXTENSION - -#if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) -enum page_ext_flags { - PAGE_EXT_YOUNG, - PAGE_EXT_IDLE, -}; -#endif - /* * Page Extension can be considered as an extended mem_map. * A page_ext page is associated with every page descriptor. The @@ -30,9 +22,7 @@ enum page_ext_flags { * All page_ext are allocated at boot or memory hotplug event, * then the page_ext for pfn always exists. */ -struct page_ext { - unsigned long flags; -}; +struct page_ext {}; extern bool early_page_ext; extern unsigned long page_ext_size; diff --git a/include/linux/page_idle.h b/include/linux/page_idle.h index 5cb7bd2078ec..4d1311fdae1d 100644 --- a/include/linux/page_idle.h +++ b/include/linux/page_idle.h @@ -9,6 +9,21 @@ #ifdef CONFIG_PAGE_IDLE_FLAG #ifndef CONFIG_64BIT +enum page_idle_flags { + PAGE_EXT_YOUNG, + PAGE_EXT_IDLE, +}; + +struct page_idle { + unsigned long flags; +}; + +extern struct page_ext_operations page_idle_ops; +static inline struct page_idle *get_page_idle(struct page_ext *page_ext) +{ + return (void *)page_ext + page_idle_ops.offset; +} + /* * If there is not enough space to store Idle and Young bits in page flags, use * page ext flags instead. @@ -16,12 +31,14 @@ static inline bool folio_test_young(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; bool page_young; if (unlikely(!page_ext)) return false; - page_young = test_bit(PAGE_EXT_YOUNG, &page_ext->flags); + pi = get_page_idle(page_ext); + page_young = test_bit(PAGE_EXT_YOUNG, &pi->flags); page_ext_put(page_ext); return page_young; @@ -30,23 +47,27 @@ static inline bool folio_test_young(struct folio *folio) static inline void folio_set_young(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; if (unlikely(!page_ext)) return; - set_bit(PAGE_EXT_YOUNG, &page_ext->flags); + pi = get_page_idle(page_ext); + set_bit(PAGE_EXT_YOUNG, &pi->flags); page_ext_put(page_ext); } static inline bool folio_test_clear_young(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; bool page_young; if (unlikely(!page_ext)) return false; - page_young = test_and_clear_bit(PAGE_EXT_YOUNG, &page_ext->flags); + pi = get_page_idle(page_ext); + page_young = test_and_clear_bit(PAGE_EXT_YOUNG, &pi->flags); page_ext_put(page_ext); return page_young; @@ -55,12 +76,14 @@ static inline bool folio_test_clear_young(struct folio *folio) static inline bool folio_test_idle(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; bool page_idle; if (unlikely(!page_ext)) return false; - page_idle = test_bit(PAGE_EXT_IDLE, &page_ext->flags); + pi = get_page_idle(page_ext); + page_idle = test_bit(PAGE_EXT_IDLE, &pi->flags); page_ext_put(page_ext); return page_idle; @@ -69,22 +92,26 @@ static inline bool folio_test_idle(struct folio *folio) static inline void folio_set_idle(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; if (unlikely(!page_ext)) return; - set_bit(PAGE_EXT_IDLE, &page_ext->flags); + pi = get_page_idle(page_ext); + set_bit(PAGE_EXT_IDLE, &pi->flags); page_ext_put(page_ext); } static inline void folio_clear_idle(struct folio *folio) { struct page_ext *page_ext = page_ext_get(&folio->page); + struct page_idle *pi; if (unlikely(!page_ext)) return; - clear_bit(PAGE_EXT_IDLE, &page_ext->flags); + pi = get_page_idle(page_ext); + clear_bit(PAGE_EXT_IDLE, &pi->flags); page_ext_put(page_ext); } #endif /* !CONFIG_64BIT */ diff --git a/mm/page_ext.c b/mm/page_ext.c index 4ee522fd381c..b3459bf08b78 100644 --- a/mm/page_ext.c +++ b/mm/page_ext.c @@ -64,16 +64,6 @@ #define PAGE_EXT_INVALID (0x1) #endif -#if defined(CONFIG_PAGE_IDLE_FLAG) && !defined(CONFIG_64BIT) -static bool need_page_idle(void) -{ - return true; -} -static struct page_ext_operations page_idle_ops __initdata = { - .need = need_page_idle, -}; -#endif - static struct page_ext_operations *page_ext_ops[] __initdata = { #ifdef CONFIG_PAGE_OWNER &page_owner_ops, diff --git a/mm/page_idle.c b/mm/page_idle.c index bc08332a609c..ea1b08a541b3 100644 --- a/mm/page_idle.c +++ b/mm/page_idle.c @@ -18,6 +18,18 @@ #define BITMAP_CHUNK_SIZE sizeof(u64) #define BITMAP_CHUNK_BITS (BITMAP_CHUNK_SIZE * BITS_PER_BYTE) +#ifndef CONFIG_64BIT +static bool need_page_idle(void) +{ + return true; +} + +struct page_ext_operations page_idle_ops __initdata = { + .size = sizeof(struct page_idle), + .need = need_page_idle, +}; +#endif + /* * Idle page tracking only considers user memory pages, for other types of * pages the idle flag is always unset and an attempt to set it is silently -- 2.30.1 (Apple Git-130)