diff options
author | Dan Williams <dan.j.williams@intel.com> | 2018-06-13 19:08:36 +0300 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2018-07-14 20:27:00 +0300 |
commit | 08e6b3c6e3a054f566367740c94b8c1d18e52056 (patch) | |
tree | 2b32de4d367f7fe923c2826b6b0be3269f91a82f /drivers/nvdimm | |
parent | 1273c253c32b9a073a4d8921ed079177ccc7c8af (diff) | |
download | linux-08e6b3c6e3a054f566367740c94b8c1d18e52056.tar.xz |
libnvdimm: Introduce locked DIMM capacity support
When a DIMM is locked its namespace label area may not be. Introduce the
distinction of locked namespaces to allow namespace enumeration while
the capacity is locked.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm')
-rw-r--r-- | drivers/nvdimm/dimm.c | 24 | ||||
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 23 | ||||
-rw-r--r-- | drivers/nvdimm/nd.h | 1 |
3 files changed, 46 insertions, 2 deletions
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index 233907889f96..6c8fb7590838 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -34,6 +34,9 @@ static int nvdimm_probe(struct device *dev) return rc; } + /* reset locked, to be validated below... */ + nvdimm_clear_locked(dev); + ndd = kzalloc(sizeof(*ndd), GFP_KERNEL); if (!ndd) return -ENOMEM; @@ -48,12 +51,30 @@ static int nvdimm_probe(struct device *dev) get_device(dev); kref_init(&ndd->kref); + /* + * EACCES failures reading the namespace label-area-properties + * are interpreted as the DIMM capacity being locked but the + * namespace labels themselves being accessible. + */ rc = nvdimm_init_nsarea(ndd); - if (rc == -EACCES) + if (rc == -EACCES) { + /* + * See nvdimm_namespace_common_probe() where we fail to + * allow namespaces to probe while the DIMM is locked, + * but we do allow for namespace enumeration. + */ nvdimm_set_locked(dev); + rc = 0; + } if (rc) goto err; + /* + * EACCES failures reading the namespace label-data are + * interpreted as the label area being locked in addition to the + * DIMM capacity. We fail the dimm probe to prevent regions from + * attempting to parse the label area. + */ rc = nvdimm_init_config_data(ndd); if (rc == -EACCES) nvdimm_set_locked(dev); @@ -72,7 +93,6 @@ static int nvdimm_probe(struct device *dev) if (rc == 0) nvdimm_set_aliasing(dev); } - nvdimm_clear_locked(dev); nvdimm_bus_unlock(dev); if (rc) diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index 28afdd668905..cb322f2bc605 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c @@ -1144,6 +1144,26 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns) } EXPORT_SYMBOL(nvdimm_namespace_capacity); +bool nvdimm_namespace_locked(struct nd_namespace_common *ndns) +{ + int i; + bool locked = false; + struct device *dev = &ndns->dev; + struct nd_region *nd_region = to_nd_region(dev->parent); + + for (i = 0; i < nd_region->ndr_mappings; i++) { + struct nd_mapping *nd_mapping = &nd_region->mapping[i]; + struct nvdimm *nvdimm = nd_mapping->nvdimm; + + if (test_bit(NDD_LOCKED, &nvdimm->flags)) { + dev_dbg(dev, "%s locked\n", nvdimm_name(nvdimm)); + locked = true; + } + } + return locked; +} +EXPORT_SYMBOL(nvdimm_namespace_locked); + static ssize_t size_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -1695,6 +1715,9 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) } } + if (nvdimm_namespace_locked(ndns)) + return ERR_PTR(-EACCES); + size = nvdimm_namespace_capacity(ndns); if (size < ND_MIN_NAMESPACE_SIZE) { dev_dbg(&ndns->dev, "%pa, too small must be at least %#x\n", diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h index 32e0364b48b9..9d17abd9f8d0 100644 --- a/drivers/nvdimm/nd.h +++ b/drivers/nvdimm/nd.h @@ -357,6 +357,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd, struct nd_label_id *label_id, resource_size_t start, resource_size_t n); resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns); +bool nvdimm_namespace_locked(struct nd_namespace_common *ndns); struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev); int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns); int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt); |