Commit 08e6b3c6 authored by Dan Williams's avatar Dan Williams

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: default avatarDan Williams <dan.j.williams@intel.com>
parent 1273c253
...@@ -34,6 +34,9 @@ static int nvdimm_probe(struct device *dev) ...@@ -34,6 +34,9 @@ static int nvdimm_probe(struct device *dev)
return rc; return rc;
} }
/* reset locked, to be validated below... */
nvdimm_clear_locked(dev);
ndd = kzalloc(sizeof(*ndd), GFP_KERNEL); ndd = kzalloc(sizeof(*ndd), GFP_KERNEL);
if (!ndd) if (!ndd)
return -ENOMEM; return -ENOMEM;
...@@ -48,12 +51,30 @@ static int nvdimm_probe(struct device *dev) ...@@ -48,12 +51,30 @@ static int nvdimm_probe(struct device *dev)
get_device(dev); get_device(dev);
kref_init(&ndd->kref); 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); 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); nvdimm_set_locked(dev);
rc = 0;
}
if (rc) if (rc)
goto err; 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); rc = nvdimm_init_config_data(ndd);
if (rc == -EACCES) if (rc == -EACCES)
nvdimm_set_locked(dev); nvdimm_set_locked(dev);
...@@ -72,7 +93,6 @@ static int nvdimm_probe(struct device *dev) ...@@ -72,7 +93,6 @@ static int nvdimm_probe(struct device *dev)
if (rc == 0) if (rc == 0)
nvdimm_set_aliasing(dev); nvdimm_set_aliasing(dev);
} }
nvdimm_clear_locked(dev);
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
if (rc) if (rc)
......
...@@ -1144,6 +1144,26 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns) ...@@ -1144,6 +1144,26 @@ resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns)
} }
EXPORT_SYMBOL(nvdimm_namespace_capacity); 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, static ssize_t size_show(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -1695,6 +1715,9 @@ struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev) ...@@ -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); size = nvdimm_namespace_capacity(ndns);
if (size < ND_MIN_NAMESPACE_SIZE) { if (size < ND_MIN_NAMESPACE_SIZE) {
dev_dbg(&ndns->dev, "%pa, too small must be at least %#x\n", dev_dbg(&ndns->dev, "%pa, too small must be at least %#x\n",
......
...@@ -357,6 +357,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd, ...@@ -357,6 +357,7 @@ struct resource *nvdimm_allocate_dpa(struct nvdimm_drvdata *ndd,
struct nd_label_id *label_id, resource_size_t start, struct nd_label_id *label_id, resource_size_t start,
resource_size_t n); resource_size_t n);
resource_size_t nvdimm_namespace_capacity(struct nd_namespace_common *ndns); 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); struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev);
int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns); int nvdimm_namespace_attach_btt(struct nd_namespace_common *ndns);
int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt); int nvdimm_namespace_detach_btt(struct nd_btt *nd_btt);
......
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