Pull libnvdimm fixes from Dan Williams: "The largest change is for a regression that landed during -rc1 for block-device read-only handling. Vaibhav found a new use for the ability (originally introduced by virtio_pmem) to call back to the platform to flush data, but also found an original bug in that implementation. Lastly, Arnd cleans up some compile warnings in dax. This has all appeared in -next with no reported issues. Summary: - Fix a regression of read-only handling in the pmem driver - Fix a compile warning - Fix support for platform cache flush commands on powerpc/papr" * tag 'libnvdimm-fixes-for-5.12-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC libnvdimm: Notify disk drivers to revalidate region read-only dax: avoid -Wempty-body warnings
Unified · Split
| @@ -90,13 +90,11 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf, · 89 unmodified lines | ||
| 90 | 90 | list_add(&dax_id->list, &dax_drv->ids); |
| 91 | 91 | } else |
| 92 | 92 | rc = -ENOMEM; |
| 93 | − } else | |
| 94 | − /* nothing to remove */; | |
| 93 | + } | |
| 95 | 94 | } else if (action == ID_REMOVE) { |
| 96 | 95 | list_del(&dax_id->list); |
| 97 | 96 | kfree(dax_id); |
| 98 | − } else | |
| 99 | − /* dax_id already added */; | |
| 97 | + } | |
| 100 | 98 | mutex_unlock(&dax_bus_lock); |
| 101 | 99 | |
| 102 | 100 | if (rc < 0) |
| @@ -631,16 +631,14 @@ void nvdimm_check_and_set_ro(struct gendisk *disk) · 630 unmodified lines | ||
| 631 | 631 | struct nd_region *nd_region = to_nd_region(dev->parent); |
| 632 | 632 | int disk_ro = get_disk_ro(disk); |
| 633 | 633 | |
| 634 | − /* | |
| 635 | − * Upgrade to read-only if the region is read-only preserve as | |
| 636 | − * read-only if the disk is already read-only. | |
| 637 | − */ | |
| 638 | − if (disk_ro || nd_region->ro == disk_ro) | |
| 634 | + /* catch the disk up with the region ro state */ | |
| 635 | + if (disk_ro == nd_region->ro) | |
| 639 | 636 | return; |
| 640 | 637 | |
| 641 | − dev_info(dev, "%s read-only, marking %s read-only\n", | |
| 642 | − dev_name(&nd_region->dev), disk->disk_name); | |
| 643 | − set_disk_ro(disk, 1); | |
| 638 | + dev_info(dev, "%s read-%s, marking %s read-%s\n", | |
| 639 | + dev_name(&nd_region->dev), nd_region->ro ? "only" : "write", | |
| 640 | + disk->disk_name, nd_region->ro ? "only" : "write"); | |
| 641 | + set_disk_ro(disk, nd_region->ro); | |
| 644 | 642 | } |
| 645 | 643 | EXPORT_SYMBOL(nvdimm_check_and_set_ro); |
| 646 | 644 | |
| @@ -26,6 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | #include <linux/mm.h> |
| 27 | 27 | #include <asm/cacheflush.h> |
| 28 | 28 | #include "pmem.h" |
| 29 | +#include "btt.h" | |
| 29 | 30 | #include "pfn.h" |
| 30 | 31 | #include "nd.h" |
| 31 | 32 | |
| @@ -585,7 +586,7 @@ static void nd_pmem_shutdown(struct device *dev) · 553 unmodified lines | ||
| 585 | 586 | nvdimm_flush(to_nd_region(dev->parent), NULL); |
| 586 | 587 | } |
| 587 | 588 | |
| 588 | −static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) | |
| 589 | +static void pmem_revalidate_poison(struct device *dev) | |
| 589 | 590 | { |
| 590 | 591 | struct nd_region *nd_region; |
| 591 | 592 | resource_size_t offset = 0, end_trunc = 0; |
| @@ -595,9 +596,6 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) · 3 unmodified lines | ||
| 595 | 596 | struct range range; |
| 596 | 597 | struct kernfs_node *bb_state; |
| 597 | 598 | |
| 598 | − if (event != NVDIMM_REVALIDATE_POISON) | |
| 599 | − return; | |
| 600 | − | |
| 601 | 599 | if (is_nd_btt(dev)) { |
| 602 | 600 | struct nd_btt *nd_btt = to_nd_btt(dev); |
| 603 | 601 | |
| @@ -635,6 +633,37 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) · 31 unmodified lines | ||
| 635 | 633 | sysfs_notify_dirent(bb_state); |
| 636 | 634 | } |
| 637 | 635 | |
| 636 | +static void pmem_revalidate_region(struct device *dev) | |
| 637 | +{ | |
| 638 | + struct pmem_device *pmem; | |
| 639 | + | |
| 640 | + if (is_nd_btt(dev)) { | |
| 641 | + struct nd_btt *nd_btt = to_nd_btt(dev); | |
| 642 | + struct btt *btt = nd_btt->btt; | |
| 643 | + | |
| 644 | + nvdimm_check_and_set_ro(btt->btt_disk); | |
| 645 | + return; | |
| 646 | + } | |
| 647 | + | |
| 648 | + pmem = dev_get_drvdata(dev); | |
| 649 | + nvdimm_check_and_set_ro(pmem->disk); | |
| 650 | +} | |
| 651 | + | |
| 652 | +static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) | |
| 653 | +{ | |
| 654 | + switch (event) { | |
| 655 | + case NVDIMM_REVALIDATE_POISON: | |
| 656 | + pmem_revalidate_poison(dev); | |
| 657 | + break; | |
| 658 | + case NVDIMM_REVALIDATE_REGION: | |
| 659 | + pmem_revalidate_region(dev); | |
| 660 | + break; | |
| 661 | + default: | |
| 662 | + dev_WARN_ONCE(dev, 1, "notify: unknown event: %d\n", event); | |
| 663 | + break; | |
| 664 | + } | |
| 665 | +} | |
| 666 | + | |
| 638 | 667 | MODULE_ALIAS("pmem"); |
| 639 | 668 | MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO); |
| 640 | 669 | MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_PMEM); |
| @@ -518,6 +518,12 @@ static ssize_t read_only_show(struct device *dev, · 517 unmodified lines | ||
| 518 | 518 | return sprintf(buf, "%d\n", nd_region->ro); |
| 519 | 519 | } |
| 520 | 520 | |
| 521 | +static int revalidate_read_only(struct device *dev, void *data) | |
| 522 | +{ | |
| 523 | + nd_device_notify(dev, NVDIMM_REVALIDATE_REGION); | |
| 524 | + return 0; | |
| 525 | +} | |
| 526 | + | |
| 521 | 527 | static ssize_t read_only_store(struct device *dev, |
| 522 | 528 | struct device_attribute *attr, const char *buf, size_t len) |
| 523 | 529 | { |
| @@ -529,6 +535,7 @@ static ssize_t read_only_store(struct device *dev, · 5 unmodified lines | ||
| 529 | 535 | return rc; |
| 530 | 536 | |
| 531 | 537 | nd_region->ro = ro; |
| 538 | + device_for_each_child(dev, NULL, revalidate_read_only); | |
| 532 | 539 | return len; |
| 533 | 540 | } |
| 534 | 541 | static DEVICE_ATTR_RW(read_only); |
| @@ -1239,6 +1246,11 @@ int nvdimm_has_flush(struct nd_region *nd_region) · 704 unmodified lines | ||
| 1239 | 1246 | || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) |
| 1240 | 1247 | return -ENXIO; |
| 1241 | 1248 | |
| 1249 | + /* Test if an explicit flush function is defined */ | |
| 1250 | + if (test_bit(ND_REGION_ASYNC, &nd_region->flags) && nd_region->flush) | |
| 1251 | + return 1; | |
| 1252 | + | |
| 1253 | + /* Test if any flush hints for the region are available */ | |
| 1242 | 1254 | for (i = 0; i < nd_region->ndr_mappings; i++) { |
| 1243 | 1255 | struct nd_mapping *nd_mapping = &nd_region->mapping[i]; |
| 1244 | 1256 | struct nvdimm *nvdimm = nd_mapping->nvdimm; |
| @@ -1249,8 +1261,8 @@ int nvdimm_has_flush(struct nd_region *nd_region) · 4 unmodified lines | ||
| 1249 | 1261 | } |
| 1250 | 1262 | |
| 1251 | 1263 | /* |
| 1252 | − * The platform defines dimm devices without hints, assume | |
| 1253 | − * platform persistence mechanism like ADR | |
| 1264 | + * The platform defines dimm devices without hints nor explicit flush, | |
| 1265 | + * assume platform persistence mechanism like ADR | |
| 1254 | 1266 | */ |
| 1255 | 1267 | return 0; |
| 1256 | 1268 | } |
| @@ -11,6 +11,7 @@ · 10 unmodified lines | ||
| 11 | 11 | |
| 12 | 12 | enum nvdimm_event { |
| 13 | 13 | NVDIMM_REVALIDATE_POISON, |
| 14 | + NVDIMM_REVALIDATE_REGION, | |
| 14 | 15 | }; |
| 15 | 16 | |
| 16 | 17 | enum nvdimm_claim_class { |