summaryrefslogtreecommitdiff
path: root/drivers/nvdimm/label.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2017-06-04 10:18:39 +0900
committerDan Williams <dan.j.williams@intel.com>2017-06-15 14:31:40 -0700
commitb3fde74ea195d2f9f49830a29f971a0aab4cd67a (patch)
tree57919bab5e02417c880eb7887bb6672c5ac07d3d /drivers/nvdimm/label.c
parent355d838878e1baec494c228458238d078dc3ca51 (diff)
libnvdimm, label: add address abstraction identifiers
Starting with v1.2 labels, 'address abstractions' can be hinted via an address abstraction id that implies an info-block format. The standard address abstraction in the specification is the v2 format of the Block-Translation-Table (BTT). Support for that is saved for a later patch, for now we add support for the Linux supported address abstractions BTT (v1), PFN, and DAX. The new 'holder_class' attribute for namespace devices is added for tooling to specify the 'abstraction_guid' to store in the namespace label. For v1.1 labels this field is undefined and any setting of 'holder_class' away from the default 'none' value will only have effect until the driver is unloaded. Setting 'holder_class' requires that whatever device tries to claim the namespace must be of the specified class. Cc: Vishal Verma <vishal.l.verma@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/label.c')
-rw-r--r--drivers/nvdimm/label.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/drivers/nvdimm/label.c b/drivers/nvdimm/label.c
index c503362a03c7..837bf21c8555 100644
--- a/drivers/nvdimm/label.c
+++ b/drivers/nvdimm/label.c
@@ -12,6 +12,7 @@
*/
#include <linux/device.h>
#include <linux/ndctl.h>
+#include <linux/uuid.h>
#include <linux/slab.h>
#include <linux/io.h>
#include <linux/nd.h>
@@ -19,6 +20,10 @@
#include "label.h"
#include "nd.h"
+static guid_t nvdimm_btt_guid;
+static guid_t nvdimm_pfn_guid;
+static guid_t nvdimm_dax_guid;
+
static u32 best_seq(u32 a, u32 b)
{
a &= NSINDEX_SEQ_MASK;
@@ -565,10 +570,44 @@ static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd,
- (unsigned long) to_namespace_index(ndd, 0);
}
+enum nvdimm_claim_class to_nvdimm_cclass(guid_t *guid)
+{
+ if (guid_equal(guid, &nvdimm_btt_guid))
+ return NVDIMM_CCLASS_BTT;
+ else if (guid_equal(guid, &nvdimm_pfn_guid))
+ return NVDIMM_CCLASS_PFN;
+ else if (guid_equal(guid, &nvdimm_dax_guid))
+ return NVDIMM_CCLASS_DAX;
+ else if (guid_equal(guid, &guid_null))
+ return NVDIMM_CCLASS_NONE;
+
+ return NVDIMM_CCLASS_UNKNOWN;
+}
+
+static const guid_t *to_abstraction_guid(enum nvdimm_claim_class claim_class,
+ guid_t *target)
+{
+ if (claim_class == NVDIMM_CCLASS_BTT)
+ return &nvdimm_btt_guid;
+ else if (claim_class == NVDIMM_CCLASS_PFN)
+ return &nvdimm_pfn_guid;
+ else if (claim_class == NVDIMM_CCLASS_DAX)
+ return &nvdimm_dax_guid;
+ else if (claim_class == NVDIMM_CCLASS_UNKNOWN) {
+ /*
+ * If we're modifying a namespace for which we don't
+ * know the claim_class, don't touch the existing guid.
+ */
+ return target;
+ } else
+ return &guid_null;
+}
+
static int __pmem_label_update(struct nd_region *nd_region,
struct nd_mapping *nd_mapping, struct nd_namespace_pmem *nspm,
int pos)
{
+ struct nd_namespace_common *ndns = &nspm->nsio.common;
struct nd_interleave_set *nd_set = nd_region->nd_set;
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
struct nd_label_ent *label_ent, *victim = NULL;
@@ -616,6 +655,10 @@ static int __pmem_label_update(struct nd_region *nd_region,
nd_label->slot = __cpu_to_le32(slot);
if (namespace_label_has(ndd, type_guid))
guid_copy(&nd_label->type_guid, &nd_set->type_guid);
+ if (namespace_label_has(ndd, abstraction_guid))
+ guid_copy(&nd_label->abstraction_guid,
+ to_abstraction_guid(ndns->claim_class,
+ &nd_label->abstraction_guid));
if (namespace_label_has(ndd, checksum)) {
u64 sum;
@@ -711,6 +754,7 @@ static int __blk_label_update(struct nd_region *nd_region,
{
int i, alloc, victims, nfree, old_num_resources, nlabel, rc = -ENXIO;
struct nd_interleave_set *nd_set = nd_region->nd_set;
+ struct nd_namespace_common *ndns = &nsblk->common;
struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
struct nd_namespace_label *nd_label;
struct nd_label_ent *label_ent, *e;
@@ -848,6 +892,11 @@ static int __blk_label_update(struct nd_region *nd_region,
nd_label->slot = __cpu_to_le32(slot);
if (namespace_label_has(ndd, type_guid))
guid_copy(&nd_label->type_guid, &nd_set->type_guid);
+ if (namespace_label_has(ndd, abstraction_guid))
+ guid_copy(&nd_label->abstraction_guid,
+ to_abstraction_guid(ndns->claim_class,
+ &nd_label->abstraction_guid));
+
if (namespace_label_has(ndd, checksum)) {
u64 sum;
@@ -1101,3 +1150,12 @@ int nd_blk_namespace_label_update(struct nd_region *nd_region,
return __blk_label_update(nd_region, nd_mapping, nsblk, count);
}
+
+int __init nd_label_init(void)
+{
+ WARN_ON(guid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_guid));
+ WARN_ON(guid_parse(NVDIMM_PFN_GUID, &nvdimm_pfn_guid));
+ WARN_ON(guid_parse(NVDIMM_DAX_GUID, &nvdimm_dax_guid));
+
+ return 0;
+}