Commit bdfd99e6 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'libnvdimm-fixes-for-5.12-rc8' of...

Merge tag 'libnvdimm-fixes-for-5.12-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm

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
parents 7c226774 11d2498f
...@@ -90,13 +90,11 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf, ...@@ -90,13 +90,11 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf,
list_add(&dax_id->list, &dax_drv->ids); list_add(&dax_id->list, &dax_drv->ids);
} else } else
rc = -ENOMEM; rc = -ENOMEM;
} else }
/* nothing to remove */;
} else if (action == ID_REMOVE) { } else if (action == ID_REMOVE) {
list_del(&dax_id->list); list_del(&dax_id->list);
kfree(dax_id); kfree(dax_id);
} else }
/* dax_id already added */;
mutex_unlock(&dax_bus_lock); mutex_unlock(&dax_bus_lock);
if (rc < 0) if (rc < 0)
......
...@@ -631,16 +631,14 @@ void nvdimm_check_and_set_ro(struct gendisk *disk) ...@@ -631,16 +631,14 @@ void nvdimm_check_and_set_ro(struct gendisk *disk)
struct nd_region *nd_region = to_nd_region(dev->parent); struct nd_region *nd_region = to_nd_region(dev->parent);
int disk_ro = get_disk_ro(disk); int disk_ro = get_disk_ro(disk);
/* /* catch the disk up with the region ro state */
* Upgrade to read-only if the region is read-only preserve as if (disk_ro == nd_region->ro)
* read-only if the disk is already read-only.
*/
if (disk_ro || nd_region->ro == disk_ro)
return; return;
dev_info(dev, "%s read-only, marking %s read-only\n", dev_info(dev, "%s read-%s, marking %s read-%s\n",
dev_name(&nd_region->dev), disk->disk_name); dev_name(&nd_region->dev), nd_region->ro ? "only" : "write",
set_disk_ro(disk, 1); disk->disk_name, nd_region->ro ? "only" : "write");
set_disk_ro(disk, nd_region->ro);
} }
EXPORT_SYMBOL(nvdimm_check_and_set_ro); EXPORT_SYMBOL(nvdimm_check_and_set_ro);
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include "pmem.h" #include "pmem.h"
#include "btt.h"
#include "pfn.h" #include "pfn.h"
#include "nd.h" #include "nd.h"
...@@ -585,7 +586,7 @@ static void nd_pmem_shutdown(struct device *dev) ...@@ -585,7 +586,7 @@ static void nd_pmem_shutdown(struct device *dev)
nvdimm_flush(to_nd_region(dev->parent), NULL); nvdimm_flush(to_nd_region(dev->parent), NULL);
} }
static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) static void pmem_revalidate_poison(struct device *dev)
{ {
struct nd_region *nd_region; struct nd_region *nd_region;
resource_size_t offset = 0, end_trunc = 0; resource_size_t offset = 0, end_trunc = 0;
...@@ -595,9 +596,6 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) ...@@ -595,9 +596,6 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
struct range range; struct range range;
struct kernfs_node *bb_state; struct kernfs_node *bb_state;
if (event != NVDIMM_REVALIDATE_POISON)
return;
if (is_nd_btt(dev)) { if (is_nd_btt(dev)) {
struct nd_btt *nd_btt = to_nd_btt(dev); struct nd_btt *nd_btt = to_nd_btt(dev);
...@@ -635,6 +633,37 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) ...@@ -635,6 +633,37 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
sysfs_notify_dirent(bb_state); sysfs_notify_dirent(bb_state);
} }
static void pmem_revalidate_region(struct device *dev)
{
struct pmem_device *pmem;
if (is_nd_btt(dev)) {
struct nd_btt *nd_btt = to_nd_btt(dev);
struct btt *btt = nd_btt->btt;
nvdimm_check_and_set_ro(btt->btt_disk);
return;
}
pmem = dev_get_drvdata(dev);
nvdimm_check_and_set_ro(pmem->disk);
}
static void nd_pmem_notify(struct device *dev, enum nvdimm_event event)
{
switch (event) {
case NVDIMM_REVALIDATE_POISON:
pmem_revalidate_poison(dev);
break;
case NVDIMM_REVALIDATE_REGION:
pmem_revalidate_region(dev);
break;
default:
dev_WARN_ONCE(dev, 1, "notify: unknown event: %d\n", event);
break;
}
}
MODULE_ALIAS("pmem"); MODULE_ALIAS("pmem");
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO); MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO);
MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_PMEM); MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_PMEM);
......
...@@ -518,6 +518,12 @@ static ssize_t read_only_show(struct device *dev, ...@@ -518,6 +518,12 @@ static ssize_t read_only_show(struct device *dev,
return sprintf(buf, "%d\n", nd_region->ro); return sprintf(buf, "%d\n", nd_region->ro);
} }
static int revalidate_read_only(struct device *dev, void *data)
{
nd_device_notify(dev, NVDIMM_REVALIDATE_REGION);
return 0;
}
static ssize_t read_only_store(struct device *dev, static ssize_t read_only_store(struct device *dev,
struct device_attribute *attr, const char *buf, size_t len) struct device_attribute *attr, const char *buf, size_t len)
{ {
...@@ -529,6 +535,7 @@ static ssize_t read_only_store(struct device *dev, ...@@ -529,6 +535,7 @@ static ssize_t read_only_store(struct device *dev,
return rc; return rc;
nd_region->ro = ro; nd_region->ro = ro;
device_for_each_child(dev, NULL, revalidate_read_only);
return len; return len;
} }
static DEVICE_ATTR_RW(read_only); static DEVICE_ATTR_RW(read_only);
...@@ -1239,6 +1246,11 @@ int nvdimm_has_flush(struct nd_region *nd_region) ...@@ -1239,6 +1246,11 @@ int nvdimm_has_flush(struct nd_region *nd_region)
|| !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API))
return -ENXIO; return -ENXIO;
/* Test if an explicit flush function is defined */
if (test_bit(ND_REGION_ASYNC, &nd_region->flags) && nd_region->flush)
return 1;
/* Test if any flush hints for the region are available */
for (i = 0; i < nd_region->ndr_mappings; i++) { for (i = 0; i < nd_region->ndr_mappings; i++) {
struct nd_mapping *nd_mapping = &nd_region->mapping[i]; struct nd_mapping *nd_mapping = &nd_region->mapping[i];
struct nvdimm *nvdimm = nd_mapping->nvdimm; struct nvdimm *nvdimm = nd_mapping->nvdimm;
...@@ -1249,8 +1261,8 @@ int nvdimm_has_flush(struct nd_region *nd_region) ...@@ -1249,8 +1261,8 @@ int nvdimm_has_flush(struct nd_region *nd_region)
} }
/* /*
* The platform defines dimm devices without hints, assume * The platform defines dimm devices without hints nor explicit flush,
* platform persistence mechanism like ADR * assume platform persistence mechanism like ADR
*/ */
return 0; return 0;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
enum nvdimm_event { enum nvdimm_event {
NVDIMM_REVALIDATE_POISON, NVDIMM_REVALIDATE_POISON,
NVDIMM_REVALIDATE_REGION,
}; };
enum nvdimm_claim_class { enum nvdimm_claim_class {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment