]> git.proxmox.com Git - mirror_ubuntu-disco-kernel.git/commitdiff
libnvdimm: Introduce locked DIMM capacity support
authorDan Williams <dan.j.williams@intel.com>
Wed, 13 Jun 2018 16:08:36 +0000 (09:08 -0700)
committerDan Williams <dan.j.williams@intel.com>
Sat, 14 Jul 2018 17:27:00 +0000 (10:27 -0700)
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>
drivers/nvdimm/dimm.c
drivers/nvdimm/namespace_devs.c
drivers/nvdimm/nd.h

index 233907889f96a36d6a3b87fc79cf82cabf602def..6c8fb7590838668c537aa09cfb289ed82f7fa563 100644 (file)
@@ -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)
index 28afdd668905019472d802be06695bfc06897b48..cb322f2bc60525d1795b63ad2e89da9353bbcf1e 100644 (file)
@@ -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",
index 32e0364b48b9d70f2f218f53734a6abe1c18e9b0..9d17abd9f8d00a2b79f10e390a255938fda5917b 100644 (file)
@@ -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);