libnvdimm/labels: Introduce CXL labels

Now that all of use sites of label data have been converted to nsl_*
helpers, introduce the CXL label format. The ->cxl flag in
nvdimm_drvdata indicates the label format the device expects. A
follow-on patch allows a bus provider to select the label style.

Note that the EFI definition of the labels represents the Linux "claim
class" with a GUID. The CXL definition of the labels stores the same
identifier in UUID byte order.

Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
Link: https://lore.kernel.org/r/163116432405.2460985.5547867384570123403.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
Dan Williams
2021-09-08 22:12:04 -07:00
parent 540ccaa2e4
commit 5af96835e4
3 changed files with 241 additions and 50 deletions

View File

@@ -17,6 +17,14 @@ static guid_t nvdimm_btt2_guid;
static guid_t nvdimm_pfn_guid;
static guid_t nvdimm_dax_guid;
static uuid_t nvdimm_btt_uuid;
static uuid_t nvdimm_btt2_uuid;
static uuid_t nvdimm_pfn_uuid;
static uuid_t nvdimm_dax_uuid;
static uuid_t cxl_region_uuid;
static uuid_t cxl_namespace_uuid;
static const char NSINDEX_SIGNATURE[] = "NAMESPACE_INDEX\0";
static u32 best_seq(u32 a, u32 b)
@@ -352,7 +360,7 @@ static bool nsl_validate_checksum(struct nvdimm_drvdata *ndd,
{
u64 sum, sum_save;
if (!namespace_label_has(ndd, checksum))
if (!ndd->cxl && !efi_namespace_label_has(ndd, checksum))
return true;
sum_save = nsl_get_checksum(ndd, nd_label);
@@ -367,7 +375,7 @@ static void nsl_calculate_checksum(struct nvdimm_drvdata *ndd,
{
u64 sum;
if (!namespace_label_has(ndd, checksum))
if (!ndd->cxl && !efi_namespace_label_has(ndd, checksum))
return;
nsl_set_checksum(ndd, nd_label, 0);
sum = nd_fletcher64(nd_label, sizeof_namespace_label(ndd), 1);
@@ -725,7 +733,7 @@ static unsigned long nd_label_offset(struct nvdimm_drvdata *ndd,
- (unsigned long) to_namespace_index(ndd, 0);
}
static enum nvdimm_claim_class to_nvdimm_cclass(guid_t *guid)
static enum nvdimm_claim_class guid_to_nvdimm_cclass(guid_t *guid)
{
if (guid_equal(guid, &nvdimm_btt_guid))
return NVDIMM_CCLASS_BTT;
@@ -741,6 +749,23 @@ static enum nvdimm_claim_class to_nvdimm_cclass(guid_t *guid)
return NVDIMM_CCLASS_UNKNOWN;
}
/* CXL labels store UUIDs instead of GUIDs for the same data */
static enum nvdimm_claim_class uuid_to_nvdimm_cclass(uuid_t *uuid)
{
if (uuid_equal(uuid, &nvdimm_btt_uuid))
return NVDIMM_CCLASS_BTT;
else if (uuid_equal(uuid, &nvdimm_btt2_uuid))
return NVDIMM_CCLASS_BTT2;
else if (uuid_equal(uuid, &nvdimm_pfn_uuid))
return NVDIMM_CCLASS_PFN;
else if (uuid_equal(uuid, &nvdimm_dax_uuid))
return NVDIMM_CCLASS_DAX;
else if (uuid_equal(uuid, &uuid_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)
{
@@ -762,6 +787,28 @@ static const guid_t *to_abstraction_guid(enum nvdimm_claim_class claim_class,
return &guid_null;
}
/* CXL labels store UUIDs instead of GUIDs for the same data */
static const uuid_t *to_abstraction_uuid(enum nvdimm_claim_class claim_class,
uuid_t *target)
{
if (claim_class == NVDIMM_CCLASS_BTT)
return &nvdimm_btt_uuid;
else if (claim_class == NVDIMM_CCLASS_BTT2)
return &nvdimm_btt2_uuid;
else if (claim_class == NVDIMM_CCLASS_PFN)
return &nvdimm_pfn_uuid;
else if (claim_class == NVDIMM_CCLASS_DAX)
return &nvdimm_dax_uuid;
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 uuid.
*/
return target;
} else
return &uuid_null;
}
static void reap_victim(struct nd_mapping *nd_mapping,
struct nd_label_ent *victim)
{
@@ -776,18 +823,18 @@ static void reap_victim(struct nd_mapping *nd_mapping,
static void nsl_set_type_guid(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label, guid_t *guid)
{
if (namespace_label_has(ndd, type_guid))
guid_copy(&nd_label->type_guid, guid);
if (efi_namespace_label_has(ndd, type_guid))
guid_copy(&nd_label->efi.type_guid, guid);
}
bool nsl_validate_type_guid(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label, guid_t *guid)
{
if (!namespace_label_has(ndd, type_guid))
if (ndd->cxl || !efi_namespace_label_has(ndd, type_guid))
return true;
if (!guid_equal(&nd_label->type_guid, guid)) {
if (!guid_equal(&nd_label->efi.type_guid, guid)) {
dev_dbg(ndd->dev, "expect type_guid %pUb got %pUb\n", guid,
&nd_label->type_guid);
&nd_label->efi.type_guid);
return false;
}
return true;
@@ -797,19 +844,34 @@ static void nsl_set_claim_class(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label,
enum nvdimm_claim_class claim_class)
{
if (!namespace_label_has(ndd, abstraction_guid))
if (ndd->cxl) {
uuid_t uuid;
import_uuid(&uuid, nd_label->cxl.abstraction_uuid);
export_uuid(nd_label->cxl.abstraction_uuid,
to_abstraction_uuid(claim_class, &uuid));
return;
guid_copy(&nd_label->abstraction_guid,
}
if (!efi_namespace_label_has(ndd, abstraction_guid))
return;
guid_copy(&nd_label->efi.abstraction_guid,
to_abstraction_guid(claim_class,
&nd_label->abstraction_guid));
&nd_label->efi.abstraction_guid));
}
enum nvdimm_claim_class nsl_get_claim_class(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label)
{
if (!namespace_label_has(ndd, abstraction_guid))
if (ndd->cxl) {
uuid_t uuid;
import_uuid(&uuid, nd_label->cxl.abstraction_uuid);
return uuid_to_nvdimm_cclass(&uuid);
}
if (!efi_namespace_label_has(ndd, abstraction_guid))
return NVDIMM_CCLASS_NONE;
return to_nvdimm_cclass(&nd_label->abstraction_guid);
return guid_to_nvdimm_cclass(&nd_label->efi.abstraction_guid);
}
static int __pmem_label_update(struct nd_region *nd_region,
@@ -942,7 +1004,7 @@ static void nsl_set_blk_isetcookie(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label,
u64 isetcookie)
{
if (namespace_label_has(ndd, type_guid)) {
if (efi_namespace_label_has(ndd, type_guid)) {
nsl_set_isetcookie(ndd, nd_label, isetcookie);
return;
}
@@ -953,7 +1015,7 @@ bool nsl_validate_blk_isetcookie(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label,
u64 isetcookie)
{
if (!namespace_label_has(ndd, type_guid))
if (!efi_namespace_label_has(ndd, type_guid))
return true;
if (nsl_get_isetcookie(ndd, nd_label) != isetcookie) {
@@ -969,7 +1031,7 @@ static void nsl_set_blk_nlabel(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label, int nlabel,
bool first)
{
if (!namespace_label_has(ndd, type_guid)) {
if (!efi_namespace_label_has(ndd, type_guid)) {
nsl_set_nlabel(ndd, nd_label, 0); /* N/A */
return;
}
@@ -980,7 +1042,7 @@ static void nsl_set_blk_position(struct nvdimm_drvdata *ndd,
struct nd_namespace_label *nd_label,
bool first)
{
if (!namespace_label_has(ndd, type_guid)) {
if (!efi_namespace_label_has(ndd, type_guid)) {
nsl_set_position(ndd, nd_label, 0);
return;
}
@@ -1390,5 +1452,13 @@ int __init nd_label_init(void)
WARN_ON(guid_parse(NVDIMM_PFN_GUID, &nvdimm_pfn_guid));
WARN_ON(guid_parse(NVDIMM_DAX_GUID, &nvdimm_dax_guid));
WARN_ON(uuid_parse(NVDIMM_BTT_GUID, &nvdimm_btt_uuid));
WARN_ON(uuid_parse(NVDIMM_BTT2_GUID, &nvdimm_btt2_uuid));
WARN_ON(uuid_parse(NVDIMM_PFN_GUID, &nvdimm_pfn_uuid));
WARN_ON(uuid_parse(NVDIMM_DAX_GUID, &nvdimm_dax_uuid));
WARN_ON(uuid_parse(CXL_REGION_UUID, &cxl_region_uuid));
WARN_ON(uuid_parse(CXL_NAMESPACE_UUID, &cxl_namespace_uuid));
return 0;
}