diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-03 19:48:48 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-03-03 19:48:48 -0500 |
| commit | 0b94da8dfc26ec2eb3e6640726e434abf8c53e49 (patch) | |
| tree | 43bf09811495b0452a7a8714341ec6f36a91d6fa /drivers | |
| parent | e27fd02d92817845471a196b3020c5694cbe5ff3 (diff) | |
| parent | 86ef58a4e35e8fa66afb5898cf6dec6a3bb29f67 (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
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/acpi/nfit/core.c | 16 | ||||
| -rw-r--r-- | drivers/nvdimm/namespace_devs.c | 18 | ||||
| -rw-r--r-- | drivers/nvdimm/nd.h | 1 | ||||
| -rw-r--r-- | drivers/nvdimm/region_devs.c | 9 |
4 files changed, 39 insertions, 5 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 | ||
| 1606 | static int cmp_map(const void *m0, const void *m1) | 1606 | static 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 | ||
| 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 | |||
| 1615 | /* Retrieve the nth entry referencing this spa */ | 1623 | /* Retrieve the nth entry referencing this spa */ |
| 1616 | static struct acpi_nfit_memory_map *memdev_from_spa( | 1624 | static 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) | |||
| 1700 | struct device *create_namespace_pmem(struct nd_region *nd_region, | 1700 | struct 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); | |||
| 328 | int nd_region_to_nstype(struct nd_region *nd_region); | 328 | int nd_region_to_nstype(struct nd_region *nd_region); |
| 329 | int nd_region_register_namespaces(struct nd_region *nd_region, int *err); | 329 | int nd_region_register_namespaces(struct nd_region *nd_region, int *err); |
| 330 | u64 nd_region_interleave_set_cookie(struct nd_region *nd_region); | 330 | u64 nd_region_interleave_set_cookie(struct nd_region *nd_region); |
| 331 | u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region); | ||
| 331 | void nvdimm_bus_lock(struct device *dev); | 332 | void nvdimm_bus_lock(struct device *dev); |
| 332 | void nvdimm_bus_unlock(struct device *dev); | 333 | void nvdimm_bus_unlock(struct device *dev); |
| 333 | bool is_nvdimm_bus_locked(struct device *dev); | 334 | bool 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 | ||
| 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 | |||
| 508 | void nd_mapping_free_labels(struct nd_mapping *nd_mapping) | 517 | void 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; |
