Re: [PATCH 13/15] mm, devmap: introduce CONFIG_DEVMAP_MANAGED_PAGES
On Tue, Oct 31, 2017 at 04:22:46PM -0700, Dan Williams wrote: > Combine the now three use cases of page-idle callbacks for ZONE_DEVICE > memory into a common selectable symbol. Very sparse changelog. I understand the Kconfig bit, but it also seems to introduce new static key functionality that isn't explained at all.
Re: [PATCH 13/15] mm, devmap: introduce CONFIG_DEVMAP_MANAGED_PAGES
On Tue, Oct 31, 2017 at 04:22:46PM -0700, Dan Williams wrote: > Combine the now three use cases of page-idle callbacks for ZONE_DEVICE > memory into a common selectable symbol. Very sparse changelog. I understand the Kconfig bit, but it also seems to introduce new static key functionality that isn't explained at all.
[PATCH 13/15] mm, devmap: introduce CONFIG_DEVMAP_MANAGED_PAGES
Combine the now three use cases of page-idle callbacks for ZONE_DEVICE memory into a common selectable symbol. Cc: "Jérôme Glisse"Cc: Michal Hocko Signed-off-by: Dan Williams --- drivers/dax/super.c |2 ++ fs/Kconfig |1 + include/linux/memremap.h | 18 +++--- include/linux/mm.h | 46 -- kernel/memremap.c| 25 + mm/Kconfig |5 + mm/hmm.c | 13 ++--- mm/swap.c|3 ++- 8 files changed, 72 insertions(+), 41 deletions(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 193e0cd8d90c..4ac359e14777 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -190,6 +190,7 @@ struct dax_device *fs_dax_claim_bdev(struct block_device *bdev, void *owner) return NULL; } + devmap_managed_pages_enable(); pgmap->type = MEMORY_DEVICE_FS_DAX; pgmap->page_free = generic_dax_pagefree; pgmap->data = owner; @@ -214,6 +215,7 @@ void fs_dax_release(struct dax_device *dax_dev, void *owner) pgmap->type = MEMORY_DEVICE_HOST; pgmap->page_free = NULL; pgmap->data = NULL; + devmap_managed_pages_disable(); mutex_unlock(_lock); } EXPORT_SYMBOL_GPL(fs_dax_release); diff --git a/fs/Kconfig b/fs/Kconfig index b40128bf6d1a..cd4ee17ecdd8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -38,6 +38,7 @@ config FS_DAX bool "Direct Access (DAX) support" depends on MMU depends on !(ARM || MIPS || SPARC) + select DEVMAP_MANAGED_PAGES select FS_IOMAP select DAX help diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 39d2de3f744b..a6716f5335e7 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h @@ -1,6 +1,5 @@ #ifndef _LINUX_MEMREMAP_H_ #define _LINUX_MEMREMAP_H_ -#include #include #include @@ -138,6 +137,9 @@ struct dev_pagemap { enum memory_type type; }; +void devmap_managed_pages_enable(void); +void devmap_managed_pages_disable(void); + #ifdef CONFIG_ZONE_DEVICE void *devm_memremap_pages(struct device *dev, struct resource *res, struct percpu_ref *ref, struct vmem_altmap *altmap); @@ -164,7 +166,7 @@ static inline struct dev_pagemap *find_dev_pagemap(resource_size_t phys) } #endif -#if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) +#ifdef CONFIG_DEVMAP_MANAGED_PAGES static inline bool is_device_private_page(const struct page *page) { return is_zone_device_page(page) && @@ -176,7 +178,17 @@ static inline bool is_device_public_page(const struct page *page) return is_zone_device_page(page) && page->pgmap->type == MEMORY_DEVICE_PUBLIC; } -#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ +#else /* CONFIG_DEVMAP_MANAGED_PAGES */ +static inline bool is_device_private_page(const struct page *page) +{ + return false; +} + +static inline bool is_device_public_page(const struct page *page) +{ + return false; +} +#endif /* CONFIG_DEVMAP_MANAGED_PAGES */ /** * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn diff --git a/include/linux/mm.h b/include/linux/mm.h index 8c1e3ac77285..2d6cf2583e10 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -800,27 +800,32 @@ static inline bool is_zone_device_page(const struct page *page) } #endif -#if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) -void put_zone_device_private_or_public_page(struct page *page); -DECLARE_STATIC_KEY_FALSE(device_private_key); -#define IS_HMM_ENABLED static_branch_unlikely(_private_key) -static inline bool is_device_private_page(const struct page *page); -static inline bool is_device_public_page(const struct page *page); -#else /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ -static inline void put_zone_device_private_or_public_page(struct page *page) -{ -} -#define IS_HMM_ENABLED 0 -static inline bool is_device_private_page(const struct page *page) +#ifdef CONFIG_DEVMAP_MANAGED_PAGES +void __put_devmap_managed_page(struct page *page); +DECLARE_STATIC_KEY_FALSE(devmap_managed_key); +static inline bool put_devmap_managed_page(struct page *page) { + if (!static_branch_unlikely(_managed_key)) + return false; + if (!is_zone_device_page(page)) + return false; + switch (page->pgmap->type) { + case MEMORY_DEVICE_PRIVATE: + case MEMORY_DEVICE_PUBLIC: + case MEMORY_DEVICE_FS_DAX: + __put_devmap_managed_page(page); + return true; + default: + break; + } return false; } -static inline bool is_device_public_page(const struct page *page) +#else /* CONFIG_DEVMAP_MANAGED_PAGES */ +static inline bool put_devmap_managed_page(struct page *page) {
[PATCH 13/15] mm, devmap: introduce CONFIG_DEVMAP_MANAGED_PAGES
Combine the now three use cases of page-idle callbacks for ZONE_DEVICE memory into a common selectable symbol. Cc: "Jérôme Glisse" Cc: Michal Hocko Signed-off-by: Dan Williams --- drivers/dax/super.c |2 ++ fs/Kconfig |1 + include/linux/memremap.h | 18 +++--- include/linux/mm.h | 46 -- kernel/memremap.c| 25 + mm/Kconfig |5 + mm/hmm.c | 13 ++--- mm/swap.c|3 ++- 8 files changed, 72 insertions(+), 41 deletions(-) diff --git a/drivers/dax/super.c b/drivers/dax/super.c index 193e0cd8d90c..4ac359e14777 100644 --- a/drivers/dax/super.c +++ b/drivers/dax/super.c @@ -190,6 +190,7 @@ struct dax_device *fs_dax_claim_bdev(struct block_device *bdev, void *owner) return NULL; } + devmap_managed_pages_enable(); pgmap->type = MEMORY_DEVICE_FS_DAX; pgmap->page_free = generic_dax_pagefree; pgmap->data = owner; @@ -214,6 +215,7 @@ void fs_dax_release(struct dax_device *dax_dev, void *owner) pgmap->type = MEMORY_DEVICE_HOST; pgmap->page_free = NULL; pgmap->data = NULL; + devmap_managed_pages_disable(); mutex_unlock(_lock); } EXPORT_SYMBOL_GPL(fs_dax_release); diff --git a/fs/Kconfig b/fs/Kconfig index b40128bf6d1a..cd4ee17ecdd8 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -38,6 +38,7 @@ config FS_DAX bool "Direct Access (DAX) support" depends on MMU depends on !(ARM || MIPS || SPARC) + select DEVMAP_MANAGED_PAGES select FS_IOMAP select DAX help diff --git a/include/linux/memremap.h b/include/linux/memremap.h index 39d2de3f744b..a6716f5335e7 100644 --- a/include/linux/memremap.h +++ b/include/linux/memremap.h @@ -1,6 +1,5 @@ #ifndef _LINUX_MEMREMAP_H_ #define _LINUX_MEMREMAP_H_ -#include #include #include @@ -138,6 +137,9 @@ struct dev_pagemap { enum memory_type type; }; +void devmap_managed_pages_enable(void); +void devmap_managed_pages_disable(void); + #ifdef CONFIG_ZONE_DEVICE void *devm_memremap_pages(struct device *dev, struct resource *res, struct percpu_ref *ref, struct vmem_altmap *altmap); @@ -164,7 +166,7 @@ static inline struct dev_pagemap *find_dev_pagemap(resource_size_t phys) } #endif -#if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) +#ifdef CONFIG_DEVMAP_MANAGED_PAGES static inline bool is_device_private_page(const struct page *page) { return is_zone_device_page(page) && @@ -176,7 +178,17 @@ static inline bool is_device_public_page(const struct page *page) return is_zone_device_page(page) && page->pgmap->type == MEMORY_DEVICE_PUBLIC; } -#endif /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ +#else /* CONFIG_DEVMAP_MANAGED_PAGES */ +static inline bool is_device_private_page(const struct page *page) +{ + return false; +} + +static inline bool is_device_public_page(const struct page *page) +{ + return false; +} +#endif /* CONFIG_DEVMAP_MANAGED_PAGES */ /** * get_dev_pagemap() - take a new live reference on the dev_pagemap for @pfn diff --git a/include/linux/mm.h b/include/linux/mm.h index 8c1e3ac77285..2d6cf2583e10 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -800,27 +800,32 @@ static inline bool is_zone_device_page(const struct page *page) } #endif -#if defined(CONFIG_DEVICE_PRIVATE) || defined(CONFIG_DEVICE_PUBLIC) -void put_zone_device_private_or_public_page(struct page *page); -DECLARE_STATIC_KEY_FALSE(device_private_key); -#define IS_HMM_ENABLED static_branch_unlikely(_private_key) -static inline bool is_device_private_page(const struct page *page); -static inline bool is_device_public_page(const struct page *page); -#else /* CONFIG_DEVICE_PRIVATE || CONFIG_DEVICE_PUBLIC */ -static inline void put_zone_device_private_or_public_page(struct page *page) -{ -} -#define IS_HMM_ENABLED 0 -static inline bool is_device_private_page(const struct page *page) +#ifdef CONFIG_DEVMAP_MANAGED_PAGES +void __put_devmap_managed_page(struct page *page); +DECLARE_STATIC_KEY_FALSE(devmap_managed_key); +static inline bool put_devmap_managed_page(struct page *page) { + if (!static_branch_unlikely(_managed_key)) + return false; + if (!is_zone_device_page(page)) + return false; + switch (page->pgmap->type) { + case MEMORY_DEVICE_PRIVATE: + case MEMORY_DEVICE_PUBLIC: + case MEMORY_DEVICE_FS_DAX: + __put_devmap_managed_page(page); + return true; + default: + break; + } return false; } -static inline bool is_device_public_page(const struct page *page) +#else /* CONFIG_DEVMAP_MANAGED_PAGES */ +static inline bool put_devmap_managed_page(struct page *page) { return false; } -#endif /* CONFIG_DEVICE_PRIVATE ||