dax: introduce dax_direct_access()
authorDan Williams <dan.j.williams@intel.com>
Fri, 27 Jan 2017 04:37:35 +0000 (20:37 -0800)
committerDan Williams <dan.j.williams@intel.com>
Thu, 20 Apr 2017 18:57:52 +0000 (11:57 -0700)
Replace bdev_direct_access() with dax_direct_access() that uses
dax_device and dax_operations instead of a block_device and
block_device_operations for dax. Once all consumers of the old api have
been converted bdev_direct_access() will be deleted.

Given that block device partitioning decisions can cause dax page
alignment constraints to be violated this also introduces the
bdev_dax_pgoff() helper. It handles calculating a logical pgoff relative
to the dax_device and also checks for page alignment.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
block/Kconfig
drivers/dax/super.c
fs/block_dev.c
include/linux/blkdev.h
include/linux/dax.h

index e9f780f815f5d70e094b5d13778c5752e8c3d504..93da7fc3f254fdc27eebf8c57909695780305870 100644 (file)
@@ -6,6 +6,7 @@ menuconfig BLOCK
        default y
        select SBITMAP
        select SRCU
+       select DAX
        help
         Provide block layer support for the kernel.
 
index 1a58542ee8fd15f281de621f8a7f5daa1057acaf..465dcd7317d5f620c1b7c1fcf67597afae1fb9f0 100644 (file)
@@ -65,6 +65,45 @@ struct dax_device {
        const struct dax_operations *ops;
 };
 
+/**
+ * dax_direct_access() - translate a device pgoff to an absolute pfn
+ * @dax_dev: a dax_device instance representing the logical memory range
+ * @pgoff: offset in pages from the start of the device to translate
+ * @nr_pages: number of consecutive pages caller can handle relative to @pfn
+ * @kaddr: output parameter that returns a virtual address mapping of pfn
+ * @pfn: output parameter that returns an absolute pfn translation of @pgoff
+ *
+ * Return: negative errno if an error occurs, otherwise the number of
+ * pages accessible at the device relative @pgoff.
+ */
+long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
+               void **kaddr, pfn_t *pfn)
+{
+       long avail;
+
+       /*
+        * The device driver is allowed to sleep, in order to make the
+        * memory directly accessible.
+        */
+       might_sleep();
+
+       if (!dax_dev)
+               return -EOPNOTSUPP;
+
+       if (!dax_alive(dax_dev))
+               return -ENXIO;
+
+       if (nr_pages < 0)
+               return nr_pages;
+
+       avail = dax_dev->ops->direct_access(dax_dev, pgoff, nr_pages,
+                       kaddr, pfn);
+       if (!avail)
+               return -ERANGE;
+       return min(avail, nr_pages);
+}
+EXPORT_SYMBOL_GPL(dax_direct_access);
+
 bool dax_alive(struct dax_device *dax_dev)
 {
        lockdep_assert_held(&dax_srcu);
index 7f40ea2f0875fab5b1ca11b138b2087b90779598..2f788571257595ffcc50aca822ef1f26a9eb5872 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/blkpg.h>
 #include <linux/magic.h>
+#include <linux/dax.h>
 #include <linux/buffer_head.h>
 #include <linux/swap.h>
 #include <linux/pagevec.h>
@@ -762,6 +763,19 @@ long bdev_direct_access(struct block_device *bdev, struct blk_dax_ctl *dax)
 }
 EXPORT_SYMBOL_GPL(bdev_direct_access);
 
+int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
+               pgoff_t *pgoff)
+{
+       phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;
+
+       if (pgoff)
+               *pgoff = PHYS_PFN(phys_off);
+       if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
+               return -EINVAL;
+       return 0;
+}
+EXPORT_SYMBOL(bdev_dax_pgoff);
+
 /**
  * bdev_dax_supported() - Check if the device supports dax for filesystem
  * @sb: The superblock of the device
index f72708399b838eff601a004e546d57c75de8e0d0..612c497d146108f556f8d768abf4cc63936aface 100644 (file)
@@ -1958,6 +1958,7 @@ extern int bdev_write_page(struct block_device *, sector_t, struct page *,
                                                struct writeback_control *);
 extern long bdev_direct_access(struct block_device *, struct blk_dax_ctl *);
 extern int bdev_dax_supported(struct super_block *, int);
+int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
 #else /* CONFIG_BLOCK */
 
 struct block_device;
index 39a0312c45c3a95d8c52d333e3c4583000b22975..7e62e280c11f3cfec8f04946168d50e742dc9bd1 100644 (file)
@@ -27,6 +27,8 @@ void put_dax(struct dax_device *dax_dev);
 bool dax_alive(struct dax_device *dax_dev);
 void kill_dax(struct dax_device *dax_dev);
 void *dax_get_private(struct dax_device *dax_dev);
+long dax_direct_access(struct dax_device *dax_dev, pgoff_t pgoff, long nr_pages,
+               void **kaddr, pfn_t *pfn);
 
 /*
  * We use lowest available bit in exceptional entry for locking, one bit for