Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b3fde74e authored by Dan Williams's avatar Dan Williams
Browse files

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: default avatarDan Williams <dan.j.williams@intel.com>
parent 355d8388
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -295,6 +295,14 @@ int nd_btt_probe(struct device *dev, struct nd_namespace_common *ndns)
	if (ndns->force_raw)
		return -ENODEV;

	switch (ndns->claim_class) {
	case NVDIMM_CCLASS_NONE:
	case NVDIMM_CCLASS_BTT:
		break;
	default:
		return -ENODEV;
	}

	nvdimm_bus_lock(&ndns->dev);
	btt_dev = __nd_btt_create(nd_region, 0, NULL, ndns);
	nvdimm_bus_unlock(&ndns->dev);
+28 −0
Original line number Diff line number Diff line
@@ -184,6 +184,34 @@ ssize_t nd_namespace_store(struct device *dev,
	}

	ndns = to_ndns(found);

	switch (ndns->claim_class) {
	case NVDIMM_CCLASS_NONE:
		break;
	case NVDIMM_CCLASS_BTT:
		if (!is_nd_btt(dev)) {
			len = -EBUSY;
			goto out_attach;
		}
		break;
	case NVDIMM_CCLASS_PFN:
		if (!is_nd_pfn(dev)) {
			len = -EBUSY;
			goto out_attach;
		}
		break;
	case NVDIMM_CCLASS_DAX:
		if (!is_nd_dax(dev)) {
			len = -EBUSY;
			goto out_attach;
		}
		break;
	default:
		len = -EBUSY;
		goto out_attach;
		break;
	}

	if (__nvdimm_namespace_capacity(ndns) < SZ_16M) {
		dev_dbg(dev, "%s too small to host\n", name);
		len = -ENXIO;
+3 −0
Original line number Diff line number Diff line
@@ -699,6 +699,9 @@ static __init int libnvdimm_init(void)
	rc = nd_region_init();
	if (rc)
		goto err_region;

	nd_label_init();

	return 0;
 err_region:
	nvdimm_exit();
+8 −0
Original line number Diff line number Diff line
@@ -111,6 +111,14 @@ int nd_dax_probe(struct device *dev, struct nd_namespace_common *ndns)
	if (ndns->force_raw)
		return -ENODEV;

	switch (ndns->claim_class) {
	case NVDIMM_CCLASS_NONE:
	case NVDIMM_CCLASS_DAX:
		break;
	default:
		return -ENODEV;
	}

	nvdimm_bus_lock(&ndns->dev);
	nd_dax = nd_dax_alloc(nd_region);
	nd_pfn = &nd_dax->nd_pfn;
+58 −0
Original line number Diff line number Diff line
@@ -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;
}
Loading