summaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/dimm.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2015-06-09 16:09:36 -0400
committerDan Williams <dan.j.williams@intel.com>2015-06-24 21:24:10 -0400
commit4a826c83db4edc040da3a66dbefd53f0cfcf457d (patch)
treeff26d9df31e46d3f7d8ff12fa288982460beacc3 /drivers/nvdimm/dimm.c
parenteaf961536e1622ad21247ac8d44acd48ba65566e (diff)
downloadlinux-4a826c83db4edc040da3a66dbefd53f0cfcf457d.tar.bz2
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.c23
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;