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.
Unified · Split
| @@ -388,7 +388,7 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id, · 387 unmodified lines | |||
| 388 | * No 'host' or dax_operations since there is no access to this | 388 | * No 'host' or dax_operations since there is no access to this |
| 389 | * device outside of mmap of the resulting character device. | 389 | * device outside of mmap of the resulting character device. |
| 390 | */ | 390 | */ |
| 391 | dax_dev = alloc_dax(dev_dax, NULL, NULL); | 391 | dax_dev = alloc_dax(dev_dax, NULL, NULL, DAXDEV_F_SYNC); |
| 392 | if (!dax_dev) | 392 | if (!dax_dev) |
| 393 | goto err; | 393 | goto err; |
| 394 | 394 | ||
| @@ -195,6 +195,8 @@ enum dax_device_flags { · 194 unmodified lines | |||
| 195 | DAXDEV_ALIVE, | 195 | DAXDEV_ALIVE, |
| 196 | /* gate whether dax_flush() calls the low level flush routine */ | 196 | /* gate whether dax_flush() calls the low level flush routine */ |
| 197 | DAXDEV_WRITE_CACHE, | 197 | DAXDEV_WRITE_CACHE, |
| 198 | /* flag to check if device supports synchronous flush */ | ||
| 199 | DAXDEV_SYNC, | ||
| 198 | }; | 200 | }; |
| 199 | 201 | ||
| 200 | /** | 202 | /** |
| @@ -372,6 +374,18 @@ bool dax_write_cache_enabled(struct dax_device *dax_dev) · 171 unmodified lines | |||
| 372 | } | 374 | } |
| 373 | EXPORT_SYMBOL_GPL(dax_write_cache_enabled); | 375 | EXPORT_SYMBOL_GPL(dax_write_cache_enabled); |
| 374 | 376 | ||
| 377 | bool __dax_synchronous(struct dax_device *dax_dev) | ||
| 378 | { | ||
| 379 | return test_bit(DAXDEV_SYNC, &dax_dev->flags); | ||
| 380 | } | ||
| 381 | EXPORT_SYMBOL_GPL(__dax_synchronous); | ||
| 382 | |||
| 383 | void __set_dax_synchronous(struct dax_device *dax_dev) | ||
| 384 | { | ||
| 385 | set_bit(DAXDEV_SYNC, &dax_dev->flags); | ||
| 386 | } | ||
| 387 | EXPORT_SYMBOL_GPL(__set_dax_synchronous); | ||
| 388 | |||
| 375 | bool dax_alive(struct dax_device *dax_dev) | 389 | bool dax_alive(struct dax_device *dax_dev) |
| 376 | { | 390 | { |
| 377 | lockdep_assert_held(&dax_srcu); | 391 | lockdep_assert_held(&dax_srcu); |
| @@ -526,7 +540,7 @@ static void dax_add_host(struct dax_device *dax_dev, const char *host) · 148 unmodified lines | |||
| 526 | } | 540 | } |
| 527 | 541 | ||
| 528 | struct dax_device *alloc_dax(void *private, const char *__host, | 542 | struct dax_device *alloc_dax(void *private, const char *__host, |
| 529 | const struct dax_operations *ops) | 543 | const struct dax_operations *ops, unsigned long flags) |
| 530 | { | 544 | { |
| 531 | struct dax_device *dax_dev; | 545 | struct dax_device *dax_dev; |
| 532 | const char *host; | 546 | const char *host; |
| @@ -549,6 +563,9 @@ struct dax_device *alloc_dax(void *private, const char *__host, · 16 unmodified lines | |||
| 549 | dax_add_host(dax_dev, host); | 563 | dax_add_host(dax_dev, host); |
| 550 | dax_dev->ops = ops; | 564 | dax_dev->ops = ops; |
| 551 | dax_dev->private = private; | 565 | dax_dev->private = private; |
| 566 | if (flags & DAXDEV_F_SYNC) | ||
| 567 | set_dax_synchronous(dax_dev); | ||
| 568 | |||
| 552 | return dax_dev; | 569 | return dax_dev; |
| 553 | 570 | ||
| 554 | err_dev: | 571 | err_dev: |
| @@ -1991,7 +1991,8 @@ static struct mapped_device *alloc_dev(int minor) · 1990 unmodified lines | |||
| 1991 | sprintf(md->disk->disk_name, "dm-%d", minor); | 1991 | sprintf(md->disk->disk_name, "dm-%d", minor); |
| 1992 | 1992 | ||
| 1993 | if (IS_ENABLED(CONFIG_DAX_DRIVER)) { | 1993 | if (IS_ENABLED(CONFIG_DAX_DRIVER)) { |
| 1994 | md->dax_dev = alloc_dax(md, md->disk->disk_name, &dm_dax_ops); | 1994 | md->dax_dev = alloc_dax(md, md->disk->disk_name, |
| 1995 | &dm_dax_ops, 0); | ||
| 1995 | if (!md->dax_dev) | 1996 | if (!md->dax_dev) |
| 1996 | goto bad; | 1997 | goto bad; |
| 1997 | } | 1998 | } |
| @@ -376,6 +376,7 @@ static int pmem_attach_disk(struct device *dev, · 375 unmodified lines | |||
| 376 | struct gendisk *disk; | 376 | struct gendisk *disk; |
| 377 | void *addr; | 377 | void *addr; |
| 378 | int rc; | 378 | int rc; |
| 379 | unsigned long flags = 0UL; | ||
| 379 | 380 | ||
| 380 | pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL); | 381 | pmem = devm_kzalloc(dev, sizeof(*pmem), GFP_KERNEL); |
| 381 | if (!pmem) | 382 | if (!pmem) |
| @@ -474,7 +475,9 @@ static int pmem_attach_disk(struct device *dev, · 92 unmodified lines | |||
| 474 | nvdimm_badblocks_populate(nd_region, &pmem->bb, &bb_res); | 475 | nvdimm_badblocks_populate(nd_region, &pmem->bb, &bb_res); |
| 475 | disk->bb = &pmem->bb; | 476 | disk->bb = &pmem->bb; |
| 476 | 477 | ||
| 477 | dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops); | 478 | if (is_nvdimm_sync(nd_region)) |
| 479 | flags = DAXDEV_F_SYNC; | ||
| 480 | dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags); | ||
| 478 | if (!dax_dev) { | 481 | if (!dax_dev) { |
| 479 | put_disk(disk); | 482 | put_disk(disk); |
| 480 | return -ENOMEM; | 483 | return -ENOMEM; |
| @@ -1211,6 +1211,13 @@ int nvdimm_has_cache(struct nd_region *nd_region) · 1210 unmodified lines | |||
| 1211 | } | 1211 | } |
| 1212 | EXPORT_SYMBOL_GPL(nvdimm_has_cache); | 1212 | EXPORT_SYMBOL_GPL(nvdimm_has_cache); |
| 1213 | 1213 | ||
| 1214 | bool is_nvdimm_sync(struct nd_region *nd_region) | ||
| 1215 | { | ||
| 1216 | return is_nd_pmem(&nd_region->dev) && | ||
| 1217 | !test_bit(ND_REGION_ASYNC, &nd_region->flags); | ||
| 1218 | } | ||
| 1219 | EXPORT_SYMBOL_GPL(is_nvdimm_sync); | ||
| 1220 | |||
| 1214 | struct conflict_context { | 1221 | struct conflict_context { |
| 1215 | struct nd_region *nd_region; | 1222 | struct nd_region *nd_region; |
| 1216 | resource_size_t start, size; | 1223 | resource_size_t start, size; |
| @@ -679,7 +679,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char · 678 unmodified lines | |||
| 679 | goto put_dev; | 679 | goto put_dev; |
| 680 | 680 | ||
| 681 | dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name, | 681 | dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name, |
| 682 | &dcssblk_dax_ops); | 682 | &dcssblk_dax_ops, DAXDEV_F_SYNC); |
| 683 | if (!dev_info->dax_dev) { | 683 | if (!dev_info->dax_dev) { |
| 684 | rc = -ENOMEM; | 684 | rc = -ENOMEM; |
| 685 | goto put_dev; | 685 | goto put_dev; |
| @@ -7,6 +7,9 @@ · 6 unmodified lines | |||
| 7 | #include <linux/radix-tree.h> | 7 | #include <linux/radix-tree.h> |
| 8 | #include <asm/pgtable.h> | 8 | #include <asm/pgtable.h> |
| 9 | 9 | ||
| 10 | /* Flag for synchronous flush */ | ||
| 11 | #define DAXDEV_F_SYNC (1UL << 0) | ||
| 12 | |||
| 10 | typedef unsigned long dax_entry_t; | 13 | typedef unsigned long dax_entry_t; |
| 11 | 14 | ||
| 12 | struct iomap_ops; | 15 | struct iomap_ops; |
| @@ -38,18 +41,28 @@ extern struct attribute_group dax_attribute_group; · 25 unmodified lines | |||
| 38 | #if IS_ENABLED(CONFIG_DAX) | 41 | #if IS_ENABLED(CONFIG_DAX) |
| 39 | struct dax_device *dax_get_by_host(const char *host); | 42 | struct dax_device *dax_get_by_host(const char *host); |
| 40 | struct dax_device *alloc_dax(void *private, const char *host, | 43 | struct dax_device *alloc_dax(void *private, const char *host, |
| 41 | const struct dax_operations *ops); | 44 | const struct dax_operations *ops, unsigned long flags); |
| 42 | void put_dax(struct dax_device *dax_dev); | 45 | void put_dax(struct dax_device *dax_dev); |
| 43 | void kill_dax(struct dax_device *dax_dev); | 46 | void kill_dax(struct dax_device *dax_dev); |
| 44 | void dax_write_cache(struct dax_device *dax_dev, bool wc); | 47 | void dax_write_cache(struct dax_device *dax_dev, bool wc); |
| 45 | bool dax_write_cache_enabled(struct dax_device *dax_dev); | 48 | bool dax_write_cache_enabled(struct dax_device *dax_dev); |
| 49 | bool __dax_synchronous(struct dax_device *dax_dev); | ||
| 50 | static inline bool dax_synchronous(struct dax_device *dax_dev) | ||
| 51 | { | ||
| 52 | return __dax_synchronous(dax_dev); | ||
| 53 | } | ||
| 54 | void __set_dax_synchronous(struct dax_device *dax_dev); | ||
| 55 | static inline void set_dax_synchronous(struct dax_device *dax_dev) | ||
| 56 | { | ||
| 57 | __set_dax_synchronous(dax_dev); | ||
| 58 | } | ||
| 46 | #else | 59 | #else |
| 47 | static inline struct dax_device *dax_get_by_host(const char *host) | 60 | static inline struct dax_device *dax_get_by_host(const char *host) |
| 48 | { | 61 | { |
| 49 | return NULL; | 62 | return NULL; |
| 50 | } | 63 | } |
| 51 | static inline struct dax_device *alloc_dax(void *private, const char *host, | 64 | static inline struct dax_device *alloc_dax(void *private, const char *host, |
| 52 | const struct dax_operations *ops) | 65 | const struct dax_operations *ops, unsigned long flags) |
| 53 | { | 66 | { |
| 54 | /* | 67 | /* |
| 55 | * Callers should check IS_ENABLED(CONFIG_DAX) to know if this | 68 | * 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) · 14 unmodified lines | |||
| 70 | { | 83 | { |
| 71 | return false; | 84 | return false; |
| 72 | } | 85 | } |
| 86 | static inline bool dax_synchronous(struct dax_device *dax_dev) | ||
| 87 | { | ||
| 88 | return true; | ||
| 89 | } | ||
| 90 | static inline void set_dax_synchronous(struct dax_device *dax_dev) | ||
| 91 | { | ||
| 92 | } | ||
| 73 | #endif | 93 | #endif |
| 74 | 94 | ||
| 75 | struct writeback_control; | 95 | struct writeback_control; |
| @@ -263,6 +263,7 @@ int generic_nvdimm_flush(struct nd_region *nd_region); · 262 unmodified lines | |||
| 263 | int nvdimm_has_flush(struct nd_region *nd_region); | 263 | int nvdimm_has_flush(struct nd_region *nd_region); |
| 264 | int nvdimm_has_cache(struct nd_region *nd_region); | 264 | int nvdimm_has_cache(struct nd_region *nd_region); |
| 265 | int nvdimm_in_overwrite(struct nvdimm *nvdimm); | 265 | int nvdimm_in_overwrite(struct nvdimm *nvdimm); |
| 266 | bool is_nvdimm_sync(struct nd_region *nd_region); | ||
| 266 | 267 | ||
| 267 | static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf, | 268 | static inline int nvdimm_ctl(struct nvdimm *nvdimm, unsigned int cmd, void *buf, |
| 268 | unsigned int buf_len, int *cmd_rc) | 269 | unsigned int buf_len, int *cmd_rc) |