aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-03-03 19:48:48 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2017-03-03 19:48:48 -0500
commit0b94da8dfc26ec2eb3e6640726e434abf8c53e49 (patch)
tree43bf09811495b0452a7a8714341ec6f36a91d6fa
parente27fd02d92817845471a196b3020c5694cbe5ff3 (diff)
parent86ef58a4e35e8fa66afb5898cf6dec6a3bb29f67 (diff)
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
-rw-r--r--drivers/acpi/nfit/core.c16
-rw-r--r--drivers/nvdimm/namespace_devs.c18
-rw-r--r--drivers/nvdimm/nd.h1
-rw-r--r--drivers/nvdimm/region_devs.c9
-rw-r--r--include/linux/libnvdimm.h2
-rw-r--r--tools/testing/nvdimm/test/nfit.c14
6 files changed, 48 insertions, 12 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 7361d00818e2..662036bdc65e 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1603,7 +1603,7 @@ static size_t sizeof_nfit_set_info(int num_mappings)
1603 + num_mappings * sizeof(struct nfit_set_info_map); 1603 + num_mappings * sizeof(struct nfit_set_info_map);
1604} 1604}
1605 1605
1606static int cmp_map(const void *m0, const void *m1) 1606static int cmp_map_compat(const void *m0, const void *m1)
1607{ 1607{
1608 const struct nfit_set_info_map *map0 = m0; 1608 const struct nfit_set_info_map *map0 = m0;
1609 const struct nfit_set_info_map *map1 = m1; 1609 const struct nfit_set_info_map *map1 = m1;
@@ -1612,6 +1612,14 @@ static int cmp_map(const void *m0, const void *m1)
1612 sizeof(u64)); 1612 sizeof(u64));
1613} 1613}
1614 1614
1615static 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
1615/* Retrieve the nth entry referencing this spa */ 1623/* Retrieve the nth entry referencing this spa */
1616static struct acpi_nfit_memory_map *memdev_from_spa( 1624static struct acpi_nfit_memory_map *memdev_from_spa(
1617 struct acpi_nfit_desc *acpi_desc, u16 range_index, int n) 1625 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,
1667 sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map), 1675 sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
1668 cmp_map, NULL); 1676 cmp_map, NULL);
1669 nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0); 1677 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
1670 ndr_desc->nd_set = nd_set; 1684 ndr_desc->nd_set = nd_set;
1671 devm_kfree(dev, info); 1685 devm_kfree(dev, info);
1672 1686
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index ce3e8dfa10ad..1b481a5fb966 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1700,6 +1700,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
1700struct device *create_namespace_pmem(struct nd_region *nd_region, 1700struct device *create_namespace_pmem(struct nd_region *nd_region,
1701 struct nd_namespace_label *nd_label) 1701 struct nd_namespace_label *nd_label)
1702{ 1702{
1703 u64 altcookie = nd_region_interleave_set_altcookie(nd_region);
1703 u64 cookie = nd_region_interleave_set_cookie(nd_region); 1704 u64 cookie = nd_region_interleave_set_cookie(nd_region);
1704 struct nd_label_ent *label_ent; 1705 struct nd_label_ent *label_ent;
1705 struct nd_namespace_pmem *nspm; 1706 struct nd_namespace_pmem *nspm;
@@ -1718,7 +1719,11 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
1718 if (__le64_to_cpu(nd_label->isetcookie) != cookie) { 1719 if (__le64_to_cpu(nd_label->isetcookie) != cookie) {
1719 dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n", 1720 dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n",
1720 nd_label->uuid); 1721 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);
1722 } 1727 }
1723 1728
1724 nspm = kzalloc(sizeof(*nspm), GFP_KERNEL); 1729 nspm = kzalloc(sizeof(*nspm), GFP_KERNEL);
@@ -1733,9 +1738,14 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
1733 res->name = dev_name(&nd_region->dev); 1738 res->name = dev_name(&nd_region->dev);
1734 res->flags = IORESOURCE_MEM; 1739 res->flags = IORESOURCE_MEM;
1735 1740
1736 for (i = 0; i < nd_region->ndr_mappings; i++) 1741 for (i = 0; i < nd_region->ndr_mappings; i++) {
1737 if (!has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i)) 1742 if (has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
1738 break; 1743 continue;
1744 if (has_uuid_at_pos(nd_region, nd_label->uuid, altcookie, i))
1745 continue;
1746 break;
1747 }
1748
1739 if (i < nd_region->ndr_mappings) { 1749 if (i < nd_region->ndr_mappings) {
1740 struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]); 1750 struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
1741 1751
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 35dd75057e16..2a99c83aa19f 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -328,6 +328,7 @@ struct nd_region *to_nd_region(struct device *dev);
328int nd_region_to_nstype(struct nd_region *nd_region); 328int nd_region_to_nstype(struct nd_region *nd_region);
329int nd_region_register_namespaces(struct nd_region *nd_region, int *err); 329int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
330u64 nd_region_interleave_set_cookie(struct nd_region *nd_region); 330u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
331u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
331void nvdimm_bus_lock(struct device *dev); 332void nvdimm_bus_lock(struct device *dev);
332void nvdimm_bus_unlock(struct device *dev); 333void nvdimm_bus_unlock(struct device *dev);
333bool is_nvdimm_bus_locked(struct device *dev); 334bool is_nvdimm_bus_locked(struct device *dev);
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 7cd705f3247c..b7cb5066d961 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -505,6 +505,15 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region)
505 return 0; 505 return 0;
506} 506}
507 507
508u64 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
508void nd_mapping_free_labels(struct nd_mapping *nd_mapping) 517void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
509{ 518{
510 struct nd_label_ent *label_ent, *e; 519 struct nd_label_ent *label_ent, *e;
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 8458c5351e56..77e7af32543f 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -70,6 +70,8 @@ struct nd_cmd_desc {
70 70
71struct nd_interleave_set { 71struct nd_interleave_set {
72 u64 cookie; 72 u64 cookie;
73 /* compatibility with initial buggy Linux implementation */
74 u64 altcookie;
73}; 75};
74 76
75struct nd_mapping_desc { 77struct nd_mapping_desc {
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 45be8b55a663..798f17655433 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -887,7 +887,7 @@ static void nfit_test0_setup(struct nfit_test *t)
887 memdev->range_index = 0+1; 887 memdev->range_index = 0+1;
888 memdev->region_index = 4+1; 888 memdev->region_index = 4+1;
889 memdev->region_size = SPA0_SIZE/2; 889 memdev->region_size = SPA0_SIZE/2;
890 memdev->region_offset = t->spa_set_dma[0]; 890 memdev->region_offset = 1;
891 memdev->address = 0; 891 memdev->address = 0;
892 memdev->interleave_index = 0; 892 memdev->interleave_index = 0;
893 memdev->interleave_ways = 2; 893 memdev->interleave_ways = 2;
@@ -902,7 +902,7 @@ static void nfit_test0_setup(struct nfit_test *t)
902 memdev->range_index = 0+1; 902 memdev->range_index = 0+1;
903 memdev->region_index = 5+1; 903 memdev->region_index = 5+1;
904 memdev->region_size = SPA0_SIZE/2; 904 memdev->region_size = SPA0_SIZE/2;
905 memdev->region_offset = t->spa_set_dma[0] + SPA0_SIZE/2; 905 memdev->region_offset = (1 << 8);
906 memdev->address = 0; 906 memdev->address = 0;
907 memdev->interleave_index = 0; 907 memdev->interleave_index = 0;
908 memdev->interleave_ways = 2; 908 memdev->interleave_ways = 2;
@@ -917,7 +917,7 @@ static void nfit_test0_setup(struct nfit_test *t)
917 memdev->range_index = 1+1; 917 memdev->range_index = 1+1;
918 memdev->region_index = 4+1; 918 memdev->region_index = 4+1;
919 memdev->region_size = SPA1_SIZE/4; 919 memdev->region_size = SPA1_SIZE/4;
920 memdev->region_offset = t->spa_set_dma[1]; 920 memdev->region_offset = (1 << 16);
921 memdev->address = SPA0_SIZE/2; 921 memdev->address = SPA0_SIZE/2;
922 memdev->interleave_index = 0; 922 memdev->interleave_index = 0;
923 memdev->interleave_ways = 4; 923 memdev->interleave_ways = 4;
@@ -932,7 +932,7 @@ static void nfit_test0_setup(struct nfit_test *t)
932 memdev->range_index = 1+1; 932 memdev->range_index = 1+1;
933 memdev->region_index = 5+1; 933 memdev->region_index = 5+1;
934 memdev->region_size = SPA1_SIZE/4; 934 memdev->region_size = SPA1_SIZE/4;
935 memdev->region_offset = t->spa_set_dma[1] + SPA1_SIZE/4; 935 memdev->region_offset = (1 << 24);
936 memdev->address = SPA0_SIZE/2; 936 memdev->address = SPA0_SIZE/2;
937 memdev->interleave_index = 0; 937 memdev->interleave_index = 0;
938 memdev->interleave_ways = 4; 938 memdev->interleave_ways = 4;
@@ -947,7 +947,7 @@ static void nfit_test0_setup(struct nfit_test *t)
947 memdev->range_index = 1+1; 947 memdev->range_index = 1+1;
948 memdev->region_index = 6+1; 948 memdev->region_index = 6+1;
949 memdev->region_size = SPA1_SIZE/4; 949 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);
951 memdev->address = SPA0_SIZE/2; 951 memdev->address = SPA0_SIZE/2;
952 memdev->interleave_index = 0; 952 memdev->interleave_index = 0;
953 memdev->interleave_ways = 4; 953 memdev->interleave_ways = 4;
@@ -962,7 +962,7 @@ static void nfit_test0_setup(struct nfit_test *t)
962 memdev->range_index = 1+1; 962 memdev->range_index = 1+1;
963 memdev->region_index = 7+1; 963 memdev->region_index = 7+1;
964 memdev->region_size = SPA1_SIZE/4; 964 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);
966 memdev->address = SPA0_SIZE/2; 966 memdev->address = SPA0_SIZE/2;
967 memdev->interleave_index = 0; 967 memdev->interleave_index = 0;
968 memdev->interleave_ways = 4; 968 memdev->interleave_ways = 4;
@@ -1380,7 +1380,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1380 memdev->range_index = 11+1; 1380 memdev->range_index = 11+1;
1381 memdev->region_index = 9+1; 1381 memdev->region_index = 9+1;
1382 memdev->region_size = SPA0_SIZE; 1382 memdev->region_size = SPA0_SIZE;
1383 memdev->region_offset = t->spa_set_dma[2]; 1383 memdev->region_offset = (1ULL << 48);
1384 memdev->address = 0; 1384 memdev->address = 0;
1385 memdev->interleave_index = 0; 1385 memdev->interleave_index = 0;
1386 memdev->interleave_ways = 1; 1386 memdev->interleave_ways = 1;