libnvdimm: add dax_dev sync flag
authorPankaj Gupta <pagupta@redhat.com>
Fri, 5 Jul 2019 14:03:24 +0000 (19:33 +0530)
committerDan Williams <dan.j.williams@intel.com>
Fri, 5 Jul 2019 22:19:10 +0000 (15:19 -0700)
This patch adds 'DAXDEV_SYNC' flag which is set
for nd_region doing synchronous flush. This later
is used to disable MAP_SYNC functionality for
ext4 & xfs filesystem for devices don't support
synchronous flush.

Signed-off-by: Pankaj Gupta <pagupta@redhat.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/dax/bus.c
drivers/dax/super.c
drivers/md/dm.c
drivers/nvdimm/pmem.c
drivers/nvdimm/region_devs.c
drivers/s390/block/dcssblk.c
include/linux/dax.h
include/linux/libnvdimm.h

index 2109cfe80219db2ff4bb9fa516bbbfefbed10045..5f184e751c826dfe312c4e59f67fd823c8e08558 100644 (file)
@@ -388,7 +388,7 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
         * No 'host' or dax_operations since there is no access to this
         * device outside of mmap of the resulting character device.
         */
-       dax_dev = alloc_dax(dev_dax, NULL, NULL);
+       dax_dev = alloc_dax(dev_dax, NULL, NULL, DAXDEV_F_SYNC);
        if (!dax_dev)
                goto err;
 
index 4e5ae7e8b557407a5a988e55b81268aa590574a7..8ab12068eea33ff738f220f10aad993f7f9adc69 100644 (file)
@@ -195,6 +195,8 @@ enum dax_device_flags {
        DAXDEV_ALIVE,
        /* gate whether dax_flush() calls the low level flush routine */
        DAXDEV_WRITE_CACHE,
+       /* flag to check if device supports synchronous flush */
+       DAXDEV_SYNC,
 };
 
 /**
@@ -372,6 +374,18 @@ bool dax_write_cache_enabled(struct dax_device *dax_dev)
 }
 EXPORT_SYMBOL_GPL(dax_write_cache_enabled);
 
+bool __dax_synchronous(struct dax_device *dax_dev)
+{
+       return test_bit(DAXDEV_SYNC, &dax_dev->flags);
+}
+EXPORT_SYMBOL_GPL(__dax_synchronous);
+
+void __set_dax_synchronous(struct dax_device *dax_dev)
+{
+       set_bit(DAXDEV_SYNC, &dax_dev->flags);
+}
+EXPORT_SYMBOL_GPL(__set_dax_synchronous);
+
 bool dax_alive(struct dax_device *dax_dev)
 {
        lockdep_assert_held(&dax_srcu);
@@ -526,7 +540,7 @@ static void dax_add_host(struct dax_device *dax_dev, const char *host)
 }
 
 struct dax_device *alloc_dax(void *private, const char *__host,
-               const struct dax_operations *ops)
+               const struct dax_operations *ops, unsigned long flags)
 {
        struct dax_device *dax_dev;
        const char *host;
@@ -549,6 +563,9 @@ struct dax_device *alloc_dax(void *private, const char *__host,
        dax_add_host(dax_dev, host);
        dax_dev->ops = ops;
        dax_dev->private = private;
+       if (flags & DAXDEV_F_SYNC)
+               set_dax_synchronous(dax_dev);
+
        return dax_dev;
 
  err_dev:
index 5475081dcbd6736d37b7fb319b4ef3f72084a0c3..b1caa7188209916c34a6bfc551755f3918080a74 100644 (file)
@@ -1991,7 +1991,8 @@ static struct mapped_device *alloc_dev(int minor)
        sprintf(md->disk->disk_name, "dm-%d", minor);
 
        if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
-               md->dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops);
+               md->dax_dev = alloc_dax(md, md->disk->disk_name,
+                                       &dm_dax_ops, 0);
                if (!md->dax_dev)
                        goto bad;
        }
index 223da63d1bd76d87b8739390b3729398289a4a1c..8be868e2a18b57e20bb59be44f58ca5d6ef2ff6a 100644 (file)
@@ -376,6 +376,7 @@ static int pmem_attach_disk(struct device *dev,
        struct gendisk *disk;
        void *addr;
        int rc;
+       unsigned long flags = 0UL;
 
        pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL);
        if (!pmem)
@@ -474,7 +475,9 @@ static int pmem_attach_disk(struct device *dev,
        nvdimm_badblocks_populate(nd_region, &pmem->bb, &bb_res);
        disk->bb = &pmem->bb;
 
-       dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops);
+       if (is_nvdimm_sync(nd_region))
+               flags = DAXDEV_F_SYNC;
+       dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags);
        if (!dax_dev) {
                put_disk(disk);
                return -ENOMEM;
index eca2e62af134b3be8cdbb2c01dbce80236fa62ee..56f2227f192a1897575f587af68cbf04368077d4 100644 (file)
@@ -1211,6 +1211,13 @@ int nvdimm_has_cache(struct nd_region *nd_region)
 }
 EXPORT_SYMBOL_GPL(nvdimm_has_cache);
 
+bool is_nvdimm_sync(struct nd_region *nd_region)
+{
+       return is_nd_pmem(&nd_region->dev) &&
+               !test_bit(ND_REGION_ASYNC, &nd_region->flags);
+}
+EXPORT_SYMBOL_GPL(is_nvdimm_sync);
+
 struct conflict_context {
        struct nd_region *nd_region;
        resource_size_t start, size;
index d04d4378ca50fe4ca18712217441697dfa408ae6..63502ca537eb801c650615a89273809fd69b3978 100644 (file)
@@ -679,7 +679,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
                goto put_dev;
 
        dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name,
-                       &dcssblk_dax_ops);
+                       &dcssblk_dax_ops, DAXDEV_F_SYNC);
        if (!dev_info->dax_dev) {
                rc = -ENOMEM;
                goto put_dev;
index becaea5f4488880d54d7eb9a51716fba5d58d3f2..8b535bc4526febcce133e3e380b593dfacac9336 100644 (file)
@@ -7,6 +7,9 @@
 #include <linux/radix-tree.h>
 #include <asm/pgtable.h>
 
+/* Flag for synchronous flush */
+#define DAXDEV_F_SYNC (1UL << 0)
+
 typedef unsigned long dax_entry_t;
 
 struct iomap_ops;
@@ -38,18 +41,28 @@ extern struct attribute_group dax_attribute_group;
 #if IS_ENABLED(CONFIG_DAX)
 struct dax_device *dax_get_by_host(const char *host);
 struct dax_device *alloc_dax(void *private, const char *host,
-               const struct dax_operations *ops);
+               const struct dax_operations *ops, unsigned long flags);
 void put_dax(struct dax_device *dax_dev);
 void kill_dax(struct dax_device *dax_dev);
 void dax_write_cache(struct dax_device *dax_dev, bool wc);
 bool dax_write_cache_enabled(struct dax_device *dax_dev);
+bool __dax_synchronous(struct dax_device *dax_dev);
+static inline bool dax_synchronous(struct dax_device *dax_dev)
+{
+       return  __dax_synchronous(dax_dev);
+}
+void __set_dax_synchronous(struct dax_device *dax_dev);
+static inline void set_dax_synchronous(struct dax_device *dax_dev)
+{
+       __set_dax_synchronous(dax_dev);
+}
 #else
 static inline struct dax_device *dax_get_by_host(const char *host)
 {
        return NULL;
 }
 static inline struct dax_device *alloc_dax(void *private, const char *host,
-               const struct dax_operations *ops)
+               const struct dax_operations *ops, unsigned long flags)
 {
        /*
         * Callers should check IS_ENABLED(CONFIG_DAX) to know if this
@@ -70,6 +83,13 @@ static inline bool dax_write_cache_enabled(struct dax_device *dax_dev)
 {
        return false;
 }
+static inline bool dax_synchronous(struct dax_device *dax_dev)
+{
+       return true;
+}
+static inline void set_dax_synchronous(struct dax_device *dax_dev)
+{
+}
 #endif
 
 struct writeback_control;
index e13100f424c8b4e1dce1cf6d2e4878bee5b8d920..7a64b3ddb40840aadf70c74595f16eb6a45fc19f 100644 (file)
@@ -263,6 +263,7 @@ int generic_nvdimm_flush(struct nd_region *nd_region);
 int nvdimm_has_flush(struct nd_region *nd_region);
 int nvdimm_has_cache(struct nd_region *nd_region);
 int nvdimm_in_overwrite(struct nvdimm *nvdimm);
+bool is_nvdimm_sync(struct nd_region *nd_region);
 
 static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf,
                unsigned int buf_len, int *cmd_rc)