Re: [PATCH 13/15] mm, devmap: introduce CONFIG_DEVMAP_MANAGED_PAGES

2017-11-10 Thread Christoph Hellwig
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

2017-11-10 Thread Christoph Hellwig
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

2017-10-31 Thread Dan Williams
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

2017-10-31 Thread Dan Williams
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 ||