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>
This commit is contained in:
@@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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,
|
|||||||
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);
|
||||||
|
|||||||
Reference in New Issue
Block a user