[PATCH v5 01/11] dax: store pfns in the radix

2018-03-09 Thread Dan Williams
In preparation for examining the busy state of dax pages in the truncate
path, switch from sectors to pfns in the radix.

Cc: Jeff Moyer 
Cc: Christoph Hellwig 
Cc: Matthew Wilcox 
Cc: Ross Zwisler 
Reviewed-by: Jan Kara 
Signed-off-by: Dan Williams 
---
 drivers/dax/super.c |   15 +++--
 fs/dax.c|   83 +++
 2 files changed, 43 insertions(+), 55 deletions(-)

diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index ecdc292aa4e4..2b2332b605e4 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -124,10 +124,19 @@ int __bdev_dax_supported(struct super_block *sb, int 
blocksize)
return len < 0 ? len : -EIO;
}
 
-   if ((IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn))
-   || pfn_t_devmap(pfn))
+   if (IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn)) {
+   /*
+* An arch that has enabled the pmem api should also
+* have its drivers support pfn_t_devmap()
+*
+* This is a developer warning and should not trigger in
+* production. dax_flush() will crash since it depends
+* on being able to do (page_address(pfn_to_page())).
+*/
+   WARN_ON(IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API));
+   } else if (pfn_t_devmap(pfn)) {
/* pass */;
-   else {
+   } else {
pr_debug("VFS (%s): error: dax support not enabled\n",
sb->s_id);
return -EOPNOTSUPP;
diff --git a/fs/dax.c b/fs/dax.c
index 0276df90e86c..b646a46e4d12 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -73,16 +73,15 @@ fs_initcall(init_dax_wait_table);
 #define RADIX_DAX_ZERO_PAGE(1 << (RADIX_TREE_EXCEPTIONAL_SHIFT + 2))
 #define RADIX_DAX_EMPTY(1 << (RADIX_TREE_EXCEPTIONAL_SHIFT + 
3))
 
-static unsigned long dax_radix_sector(void *entry)
+static unsigned long dax_radix_pfn(void *entry)
 {
return (unsigned long)entry >> RADIX_DAX_SHIFT;
 }
 
-static void *dax_radix_locked_entry(sector_t sector, unsigned long flags)
+static void *dax_radix_locked_entry(unsigned long pfn, unsigned long flags)
 {
return (void *)(RADIX_TREE_EXCEPTIONAL_ENTRY | flags |
-   ((unsigned long)sector << RADIX_DAX_SHIFT) |
-   RADIX_DAX_ENTRY_LOCK);
+   (pfn << RADIX_DAX_SHIFT) | RADIX_DAX_ENTRY_LOCK);
 }
 
 static unsigned int dax_radix_order(void *entry)
@@ -526,12 +525,13 @@ static int copy_user_dax(struct block_device *bdev, 
struct dax_device *dax_dev,
  */
 static void *dax_insert_mapping_entry(struct address_space *mapping,
  struct vm_fault *vmf,
- void *entry, sector_t sector,
+ void *entry, pfn_t pfn_t,
  unsigned long flags, bool dirty)
 {
struct radix_tree_root *page_tree = >page_tree;
-   void *new_entry;
+   unsigned long pfn = pfn_t_to_pfn(pfn_t);
pgoff_t index = vmf->pgoff;
+   void *new_entry;
 
if (dirty)
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
@@ -546,7 +546,7 @@ static void *dax_insert_mapping_entry(struct address_space 
*mapping,
}
 
spin_lock_irq(>tree_lock);
-   new_entry = dax_radix_locked_entry(sector, flags);
+   new_entry = dax_radix_locked_entry(pfn, flags);
 
if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry)) {
/*
@@ -657,17 +657,14 @@ static void dax_mapping_entry_mkclean(struct 
address_space *mapping,
i_mmap_unlock_read(mapping);
 }
 
-static int dax_writeback_one(struct block_device *bdev,
-   struct dax_device *dax_dev, struct address_space *mapping,
-   pgoff_t index, void *entry)
+static int dax_writeback_one(struct dax_device *dax_dev,
+   struct address_space *mapping, pgoff_t index, void *entry)
 {
struct radix_tree_root *page_tree = >page_tree;
-   void *entry2, **slot, *kaddr;
-   long ret = 0, id;
-   sector_t sector;
-   pgoff_t pgoff;
+   void *entry2, **slot;
+   unsigned long pfn;
+   long ret = 0;
size_t size;
-   pfn_t pfn;
 
/*
 * A page got tagged dirty in DAX mapping? Something is seriously
@@ -683,10 +680,10 @@ static int dax_writeback_one(struct block_device *bdev,
goto put_unlocked;
/*
 * Entry got reallocated elsewhere? No need to writeback. We have to
-* compare sectors as we must not bail out due to difference in lockbit
+* compare pfns as we must not bail out due to difference in lockbit
 * or entry type.
 */
-   if 

[PATCH v5 01/11] dax: store pfns in the radix

2018-03-09 Thread Dan Williams
In preparation for examining the busy state of dax pages in the truncate
path, switch from sectors to pfns in the radix.

Cc: Jeff Moyer 
Cc: Christoph Hellwig 
Cc: Matthew Wilcox 
Cc: Ross Zwisler 
Reviewed-by: Jan Kara 
Signed-off-by: Dan Williams 
---
 drivers/dax/super.c |   15 +++--
 fs/dax.c|   83 +++
 2 files changed, 43 insertions(+), 55 deletions(-)

diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index ecdc292aa4e4..2b2332b605e4 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -124,10 +124,19 @@ int __bdev_dax_supported(struct super_block *sb, int 
blocksize)
return len < 0 ? len : -EIO;
}
 
-   if ((IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn))
-   || pfn_t_devmap(pfn))
+   if (IS_ENABLED(CONFIG_FS_DAX_LIMITED) && pfn_t_special(pfn)) {
+   /*
+* An arch that has enabled the pmem api should also
+* have its drivers support pfn_t_devmap()
+*
+* This is a developer warning and should not trigger in
+* production. dax_flush() will crash since it depends
+* on being able to do (page_address(pfn_to_page())).
+*/
+   WARN_ON(IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API));
+   } else if (pfn_t_devmap(pfn)) {
/* pass */;
-   else {
+   } else {
pr_debug("VFS (%s): error: dax support not enabled\n",
sb->s_id);
return -EOPNOTSUPP;
diff --git a/fs/dax.c b/fs/dax.c
index 0276df90e86c..b646a46e4d12 100644
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -73,16 +73,15 @@ fs_initcall(init_dax_wait_table);
 #define RADIX_DAX_ZERO_PAGE(1 << (RADIX_TREE_EXCEPTIONAL_SHIFT + 2))
 #define RADIX_DAX_EMPTY(1 << (RADIX_TREE_EXCEPTIONAL_SHIFT + 
3))
 
-static unsigned long dax_radix_sector(void *entry)
+static unsigned long dax_radix_pfn(void *entry)
 {
return (unsigned long)entry >> RADIX_DAX_SHIFT;
 }
 
-static void *dax_radix_locked_entry(sector_t sector, unsigned long flags)
+static void *dax_radix_locked_entry(unsigned long pfn, unsigned long flags)
 {
return (void *)(RADIX_TREE_EXCEPTIONAL_ENTRY | flags |
-   ((unsigned long)sector << RADIX_DAX_SHIFT) |
-   RADIX_DAX_ENTRY_LOCK);
+   (pfn << RADIX_DAX_SHIFT) | RADIX_DAX_ENTRY_LOCK);
 }
 
 static unsigned int dax_radix_order(void *entry)
@@ -526,12 +525,13 @@ static int copy_user_dax(struct block_device *bdev, 
struct dax_device *dax_dev,
  */
 static void *dax_insert_mapping_entry(struct address_space *mapping,
  struct vm_fault *vmf,
- void *entry, sector_t sector,
+ void *entry, pfn_t pfn_t,
  unsigned long flags, bool dirty)
 {
struct radix_tree_root *page_tree = >page_tree;
-   void *new_entry;
+   unsigned long pfn = pfn_t_to_pfn(pfn_t);
pgoff_t index = vmf->pgoff;
+   void *new_entry;
 
if (dirty)
__mark_inode_dirty(mapping->host, I_DIRTY_PAGES);
@@ -546,7 +546,7 @@ static void *dax_insert_mapping_entry(struct address_space 
*mapping,
}
 
spin_lock_irq(>tree_lock);
-   new_entry = dax_radix_locked_entry(sector, flags);
+   new_entry = dax_radix_locked_entry(pfn, flags);
 
if (dax_is_zero_entry(entry) || dax_is_empty_entry(entry)) {
/*
@@ -657,17 +657,14 @@ static void dax_mapping_entry_mkclean(struct 
address_space *mapping,
i_mmap_unlock_read(mapping);
 }
 
-static int dax_writeback_one(struct block_device *bdev,
-   struct dax_device *dax_dev, struct address_space *mapping,
-   pgoff_t index, void *entry)
+static int dax_writeback_one(struct dax_device *dax_dev,
+   struct address_space *mapping, pgoff_t index, void *entry)
 {
struct radix_tree_root *page_tree = >page_tree;
-   void *entry2, **slot, *kaddr;
-   long ret = 0, id;
-   sector_t sector;
-   pgoff_t pgoff;
+   void *entry2, **slot;
+   unsigned long pfn;
+   long ret = 0;
size_t size;
-   pfn_t pfn;
 
/*
 * A page got tagged dirty in DAX mapping? Something is seriously
@@ -683,10 +680,10 @@ static int dax_writeback_one(struct block_device *bdev,
goto put_unlocked;
/*
 * Entry got reallocated elsewhere? No need to writeback. We have to
-* compare sectors as we must not bail out due to difference in lockbit
+* compare pfns as we must not bail out due to difference in lockbit
 * or entry type.
 */
-   if (dax_radix_sector(entry2) != dax_radix_sector(entry))
+   if (dax_radix_pfn(entry2) != dax_radix_pfn(entry))
goto