diff options
author | Dan Williams <dan.j.williams@intel.com> | 2015-06-09 16:09:36 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2015-06-24 21:24:10 -0400 |
commit | 4a826c83db4edc040da3a66dbefd53f0cfcf457d (patch) | |
tree | ff26d9df31e46d3f7d8ff12fa288982460beacc3 /drivers/nvdimm/dimm.c | |
parent | eaf961536e1622ad21247ac8d44acd48ba65566e (diff) |
libnvdimm: namespace indices: read and validate
This on media label format [1] consists of two index blocks followed by
an array of labels. None of these structures are ever updated in place.
A sequence number tracks the current active index and the next one to
write, while labels are written to free slots.
+------------+
| |
| nsindex0 |
| |
+------------+
| |
| nsindex1 |
| |
+------------+
| label0 |
+------------+
| label1 |
+------------+
| |
....nslot...
| |
+------------+
| labelN |
+------------+
After reading valid labels, store the dpa ranges they claim into
per-dimm resource trees.
[1]: http://pmem.io/documents/NVDIMM_Namespace_Spec.pdf
Cc: Neil Brown <neilb@suse.de>
Acked-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/dimm.c')
-rw-r--r-- | drivers/nvdimm/dimm.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/nvdimm/dimm.c b/drivers/nvdimm/dimm.c index eb20fc2df32b..2df97c3c3b34 100644 --- a/drivers/nvdimm/dimm.c +++ b/drivers/nvdimm/dimm.c @@ -18,6 +18,7 @@ #include <linux/slab.h> #include <linux/mm.h> #include <linux/nd.h> +#include "label.h" #include "nd.h" static void free_data(struct nvdimm_drvdata *ndd) @@ -42,6 +43,11 @@ static int nvdimm_probe(struct device *dev) return -ENOMEM; dev_set_drvdata(dev, ndd); + ndd->dpa.name = dev_name(dev); + ndd->ns_current = -1; + ndd->ns_next = -1; + ndd->dpa.start = 0; + ndd->dpa.end = -1; ndd->dev = dev; rc = nvdimm_init_nsarea(ndd); @@ -54,6 +60,17 @@ static int nvdimm_probe(struct device *dev) dev_dbg(dev, "config data size: %d\n", ndd->nsarea.config_size); + nvdimm_bus_lock(dev); + ndd->ns_current = nd_label_validate(ndd); + ndd->ns_next = nd_label_next_nsindex(ndd->ns_current); + nd_label_copy(ndd, to_next_namespace_index(ndd), + to_current_namespace_index(ndd)); + rc = nd_label_reserve_dpa(ndd); + nvdimm_bus_unlock(dev); + + if (rc) + goto err; + return 0; err: @@ -64,7 +81,13 @@ static int nvdimm_probe(struct device *dev) static int nvdimm_remove(struct device *dev) { struct nvdimm_drvdata *ndd = dev_get_drvdata(dev); + struct resource *res, *_r; + nvdimm_bus_lock(dev); + dev_set_drvdata(dev, NULL); + for_each_dpa_resource_safe(ndd, res, _r) + nvdimm_free_dpa(ndd, res); + nvdimm_bus_unlock(dev); free_data(ndd); return 0; |