This patch is partially taken from John Grove's famfs dax series.

Save the kva for memremap because we need direct_access() support.

Signed-off-by: Dave Jiang <[email protected]>
---
 drivers/dax/dax-private.h |  4 ++++
 drivers/dax/device.c      | 19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
index c6ae27c982f4..425a515905e5 100644
--- a/drivers/dax/dax-private.h
+++ b/drivers/dax/dax-private.h
@@ -69,6 +69,8 @@ struct dev_dax_range {
  * data while the device is activated in the driver.
  * @region: parent region
  * @dax_dev: core dax functionality
+ * @virt_addr: kva from memremap; used by fsdev_dax
+ * @cached_size: cached size of the memory range for quick access; used by 
fsdev_dax
  * @align: alignment of this instance
  * @target_node: effective numa node if dev_dax memory range is onlined
  * @dyn_id: is this a dynamic or statically created instance
@@ -83,6 +85,8 @@ struct dev_dax_range {
 struct dev_dax {
        struct dax_region *region;
        struct dax_device *dax_dev;
+       void *virt_addr;
+       u64 cached_size;
        unsigned int align;
        int target_node;
        bool dyn_id;
diff --git a/drivers/dax/device.c b/drivers/dax/device.c
index 62206bcb63a6..4ffa3ef60a57 100644
--- a/drivers/dax/device.c
+++ b/drivers/dax/device.c
@@ -370,6 +370,7 @@ static int dax_open(struct inode *inode, struct file *filp)
        filp->f_sb_err = file_sample_sb_err(filp);
        filp->private_data = dev_dax;
        inode->i_flags = S_DAX;
+       inode->i_size = dev_dax->cached_size;
 
        return 0;
 }
@@ -408,7 +409,9 @@ static int dev_dax_probe(struct dev_dax *dev_dax)
        struct device *dev = &dev_dax->dev;
        struct dev_pagemap *pgmap;
        struct inode *inode;
+       u64 data_offset = 0;
        struct cdev *cdev;
+       u64 len = 0;
        void *addr;
        int rc, i;
 
@@ -451,6 +454,7 @@ static int dev_dax_probe(struct dev_dax *dev_dax)
                                        i, range->start, range->end);
                        return -EBUSY;
                }
+               len += range_len(range);
        }
 
        pgmap->type = MEMORY_DEVICE_GENERIC;
@@ -461,6 +465,21 @@ static int dev_dax_probe(struct dev_dax *dev_dax)
        if (IS_ERR(addr))
                return PTR_ERR(addr);
 
+       /* Detect whether the data is at a non-zero offset into the memory */
+       if (pgmap->range.start != dev_dax->ranges[0].range.start) {
+               u64 phys = dev_dax->ranges[0].range.start;
+               u64 pgmap_phys = dev_dax->pgmap[0].range.start;
+
+               if (!WARN_ON(pgmap_phys > phys))
+                       data_offset = phys - pgmap_phys;
+
+               pr_debug("%s: offset detected phys=%llx pgmap_phys=%llx 
offset=%llx\n",
+                        __func__, phys, pgmap_phys, data_offset);
+       }
+
+       dev_dax->virt_addr = addr + data_offset;
+       dev_dax->cached_size = len;
+
        inode = dax_inode(dax_dev);
        cdev = inode->i_cdev;
        cdev_init(cdev, &dax_fops);
-- 
2.53.0


Reply via email to