Skip to content

Commit 0b94da8

Browse files
committed
Merge branch 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm
Pull libnvdimm fixes from Dan Williams: "A fix and regression test case for nvdimm namespace label compatibility. Details: - An "nvdimm namespace label" is metadata on an nvdimm that provisions dimm capacity into a "namespace" that can host a block device / dax-filesytem, or a device-dax character device. A namespace is an object that other operating environment and platform firmware needs to comprehend for capabilities like booting from an nvdimm. The label metadata contains a checksum that Linux was not calculating correctly leading to other environments rejecting the Linux label. These have received a build success notification from the kbuild robot, and a positive test result from Nick who reported the problem" * 'libnvdimm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm: nfit, libnvdimm: fix interleave set cookie calculation tools/testing/nvdimm: make iset cookie predictable
2 parents e27fd02 + 86ef58a commit 0b94da8

File tree

6 files changed

+48
-12
lines changed

6 files changed

+48
-12
lines changed

drivers/acpi/nfit/core.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1603,7 +1603,7 @@ static size_t sizeof_nfit_set_info(int num_mappings)
16031603
+ num_mappings * sizeof(struct nfit_set_info_map);
16041604
}
16051605

1606-
static int cmp_map(const void *m0, const void *m1)
1606+
static int cmp_map_compat(const void *m0, const void *m1)
16071607
{
16081608
const struct nfit_set_info_map *map0 = m0;
16091609
const struct nfit_set_info_map *map1 = m1;
@@ -1612,6 +1612,14 @@ static int cmp_map(const void *m0, const void *m1)
16121612
sizeof(u64));
16131613
}
16141614

1615+
static int cmp_map(const void *m0, const void *m1)
1616+
{
1617+
const struct nfit_set_info_map *map0 = m0;
1618+
const struct nfit_set_info_map *map1 = m1;
1619+
1620+
return map0->region_offset - map1->region_offset;
1621+
}
1622+
16151623
/* Retrieve the nth entry referencing this spa */
16161624
static struct acpi_nfit_memory_map *memdev_from_spa(
16171625
struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
@@ -1667,6 +1675,12 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
16671675
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
16681676
cmp_map, NULL);
16691677
nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
1678+
1679+
/* support namespaces created with the wrong sort order */
1680+
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
1681+
cmp_map_compat, NULL);
1682+
nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
1683+
16701684
ndr_desc->nd_set = nd_set;
16711685
devm_kfree(dev, info);
16721686

drivers/nvdimm/namespace_devs.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,6 +1700,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
17001700
struct device *create_namespace_pmem(struct nd_region *nd_region,
17011701
struct nd_namespace_label *nd_label)
17021702
{
1703+
u64 altcookie = nd_region_interleave_set_altcookie(nd_region);
17031704
u64 cookie = nd_region_interleave_set_cookie(nd_region);
17041705
struct nd_label_ent *label_ent;
17051706
struct nd_namespace_pmem *nspm;
@@ -1718,7 +1719,11 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
17181719
if (__le64_to_cpu(nd_label->isetcookie) != cookie) {
17191720
dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n",
17201721
nd_label->uuid);
1721-
return ERR_PTR(-EAGAIN);
1722+
if (__le64_to_cpu(nd_label->isetcookie) != altcookie)
1723+
return ERR_PTR(-EAGAIN);
1724+
1725+
dev_dbg(&nd_region->dev, "valid altcookie in label: %pUb\n",
1726+
nd_label->uuid);
17221727
}
17231728

17241729
nspm = kzalloc(sizeof(*nspm), GFP_KERNEL);
@@ -1733,9 +1738,14 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
17331738
res->name = dev_name(&nd_region->dev);
17341739
res->flags = IORESOURCE_MEM;
17351740

1736-
for (i = 0; i < nd_region->ndr_mappings; i++)
1737-
if (!has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
1738-
break;
1741+
for (i = 0; i < nd_region->ndr_mappings; i++) {
1742+
if (has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
1743+
continue;
1744+
if (has_uuid_at_pos(nd_region, nd_label->uuid, altcookie, i))
1745+
continue;
1746+
break;
1747+
}
1748+
17391749
if (i < nd_region->ndr_mappings) {
17401750
struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
17411751

drivers/nvdimm/nd.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ struct nd_region *to_nd_region(struct device *dev);
328328
int nd_region_to_nstype(struct nd_region *nd_region);
329329
int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
330330
u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
331+
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
331332
void nvdimm_bus_lock(struct device *dev);
332333
void nvdimm_bus_unlock(struct device *dev);
333334
bool is_nvdimm_bus_locked(struct device *dev);

drivers/nvdimm/region_devs.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,6 +505,15 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region)
505505
return 0;
506506
}
507507

508+
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
509+
{
510+
struct nd_interleave_set *nd_set = nd_region->nd_set;
511+
512+
if (nd_set)
513+
return nd_set->altcookie;
514+
return 0;
515+
}
516+
508517
void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
509518
{
510519
struct nd_label_ent *label_ent, *e;

include/linux/libnvdimm.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ struct nd_cmd_desc {
7070

7171
struct nd_interleave_set {
7272
u64 cookie;
73+
/* compatibility with initial buggy Linux implementation */
74+
u64 altcookie;
7375
};
7476

7577
struct nd_mapping_desc {

tools/testing/nvdimm/test/nfit.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ static void nfit_test0_setup(struct nfit_test *t)
887887
memdev->range_index = 0+1;
888888
memdev->region_index = 4+1;
889889
memdev->region_size = SPA0_SIZE/2;
890-
memdev->region_offset = t->spa_set_dma[0];
890+
memdev->region_offset = 1;
891891
memdev->address = 0;
892892
memdev->interleave_index = 0;
893893
memdev->interleave_ways = 2;
@@ -902,7 +902,7 @@ static void nfit_test0_setup(struct nfit_test *t)
902902
memdev->range_index = 0+1;
903903
memdev->region_index = 5+1;
904904
memdev->region_size = SPA0_SIZE/2;
905-
memdev->region_offset = t->spa_set_dma[0] + SPA0_SIZE/2;
905+
memdev->region_offset = (1 << 8);
906906
memdev->address = 0;
907907
memdev->interleave_index = 0;
908908
memdev->interleave_ways = 2;
@@ -917,7 +917,7 @@ static void nfit_test0_setup(struct nfit_test *t)
917917
memdev->range_index = 1+1;
918918
memdev->region_index = 4+1;
919919
memdev->region_size = SPA1_SIZE/4;
920-
memdev->region_offset = t->spa_set_dma[1];
920+
memdev->region_offset = (1 << 16);
921921
memdev->address = SPA0_SIZE/2;
922922
memdev->interleave_index = 0;
923923
memdev->interleave_ways = 4;
@@ -932,7 +932,7 @@ static void nfit_test0_setup(struct nfit_test *t)
932932
memdev->range_index = 1+1;
933933
memdev->region_index = 5+1;
934934
memdev->region_size = SPA1_SIZE/4;
935-
memdev->region_offset = t->spa_set_dma[1] + SPA1_SIZE/4;
935+
memdev->region_offset = (1 << 24);
936936
memdev->address = SPA0_SIZE/2;
937937
memdev->interleave_index = 0;
938938
memdev->interleave_ways = 4;
@@ -947,7 +947,7 @@ static void nfit_test0_setup(struct nfit_test *t)
947947
memdev->range_index = 1+1;
948948
memdev->region_index = 6+1;
949949
memdev->region_size = SPA1_SIZE/4;
950-
memdev->region_offset = t->spa_set_dma[1] + 2*SPA1_SIZE/4;
950+
memdev->region_offset = (1ULL << 32);
951951
memdev->address = SPA0_SIZE/2;
952952
memdev->interleave_index = 0;
953953
memdev->interleave_ways = 4;
@@ -962,7 +962,7 @@ static void nfit_test0_setup(struct nfit_test *t)
962962
memdev->range_index = 1+1;
963963
memdev->region_index = 7+1;
964964
memdev->region_size = SPA1_SIZE/4;
965-
memdev->region_offset = t->spa_set_dma[1] + 3*SPA1_SIZE/4;
965+
memdev->region_offset = (1ULL << 40);
966966
memdev->address = SPA0_SIZE/2;
967967
memdev->interleave_index = 0;
968968
memdev->interleave_ways = 4;
@@ -1380,7 +1380,7 @@ static void nfit_test0_setup(struct nfit_test *t)
13801380
memdev->range_index = 11+1;
13811381
memdev->region_index = 9+1;
13821382
memdev->region_size = SPA0_SIZE;
1383-
memdev->region_offset = t->spa_set_dma[2];
1383+
memdev->region_offset = (1ULL << 48);
13841384
memdev->address = 0;
13851385
memdev->interleave_index = 0;
13861386
memdev->interleave_ways = 1;

0 commit comments

Comments
 (0)