nfit, libnvdimm: fix interleave set cookie calculation

am: 66dd58f56e

Change-Id: If1b31bbd5fe6a404d167a6b207bef928b998fba0
This commit is contained in:
Dan Williams
2017-03-18 11:24:51 +00:00
committed by android-build-merger
5 changed files with 48 additions and 8 deletions

View File

@@ -965,7 +965,7 @@ static size_t sizeof_nfit_set_info(int num_mappings)
+ num_mappings * sizeof(struct nfit_set_info_map);
}
static int cmp_map(const void *m0, const void *m1)
static int cmp_map_compat(const void *m0, const void *m1)
{
const struct nfit_set_info_map *map0 = m0;
const struct nfit_set_info_map *map1 = m1;
@@ -974,6 +974,14 @@ static int cmp_map(const void *m0, const void *m1)
sizeof(u64));
}
static int cmp_map(const void *m0, const void *m1)
{
const struct nfit_set_info_map *map0 = m0;
const struct nfit_set_info_map *map1 = m1;
return map0->region_offset - map1->region_offset;
}
/* Retrieve the nth entry referencing this spa */
static struct acpi_nfit_memory_map *memdev_from_spa(
struct acpi_nfit_desc *acpi_desc, u16 range_index, int n)
@@ -1029,6 +1037,12 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
cmp_map, NULL);
nd_set->cookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
/* support namespaces created with the wrong sort order */
sort(&info->mapping[0], nr, sizeof(struct nfit_set_info_map),
cmp_map_compat, NULL);
nd_set->altcookie = nd_fletcher64(info, sizeof_nfit_set_info(nr), 0);
ndr_desc->nd_set = nd_set;
devm_kfree(dev, info);

View File

@@ -1534,6 +1534,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
static int find_pmem_label_set(struct nd_region *nd_region,
struct nd_namespace_pmem *nspm)
{
u64 altcookie = nd_region_interleave_set_altcookie(nd_region);
u64 cookie = nd_region_interleave_set_cookie(nd_region);
struct nd_namespace_label *nd_label;
u8 select_id[NSLABEL_UUID_LEN];
@@ -1542,8 +1543,10 @@ static int find_pmem_label_set(struct nd_region *nd_region,
int rc = -ENODEV, l;
u16 i;
if (cookie == 0)
if (cookie == 0) {
dev_dbg(&nd_region->dev, "invalid interleave-set-cookie\n");
return -ENXIO;
}
/*
* Find a complete set of labels by uuid. By definition we can start
@@ -1552,13 +1555,24 @@ static int find_pmem_label_set(struct nd_region *nd_region,
for_each_label(l, nd_label, nd_region->mapping[0].labels) {
u64 isetcookie = __le64_to_cpu(nd_label->isetcookie);
if (isetcookie != cookie)
continue;
if (isetcookie != cookie) {
dev_dbg(&nd_region->dev, "invalid cookie in label: %pUb\n",
nd_label->uuid);
if (isetcookie != altcookie)
continue;
dev_dbg(&nd_region->dev, "valid altcookie in label: %pUb\n",
nd_label->uuid);
}
for (i = 0; nd_region->ndr_mappings; i++) {
if (has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
continue;
if (has_uuid_at_pos(nd_region, nd_label->uuid, altcookie, i))
continue;
break;
}
for (i = 0; nd_region->ndr_mappings; i++)
if (!has_uuid_at_pos(nd_region, nd_label->uuid,
cookie, i))
break;
if (i < nd_region->ndr_mappings) {
/*
* Give up if we don't find an instance of a

View File

@@ -245,6 +245,7 @@ struct nd_region *to_nd_region(struct device *dev);
int nd_region_to_nstype(struct nd_region *nd_region);
int nd_region_register_namespaces(struct nd_region *nd_region, int *err);
u64 nd_region_interleave_set_cookie(struct nd_region *nd_region);
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region);
void nvdimm_bus_lock(struct device *dev);
void nvdimm_bus_unlock(struct device *dev);
bool is_nvdimm_bus_locked(struct device *dev);

View File

@@ -379,6 +379,15 @@ u64 nd_region_interleave_set_cookie(struct nd_region *nd_region)
return 0;
}
u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
{
struct nd_interleave_set *nd_set = nd_region->nd_set;
if (nd_set)
return nd_set->altcookie;
return 0;
}
/*
* Upon successful probe/remove, take/release a reference on the
* associated interleave set (if present), and plant new btt + namespace

View File

@@ -83,6 +83,8 @@ struct nd_cmd_desc {
struct nd_interleave_set {
u64 cookie;
/* compatibility with initial buggy Linux implementation */
u64 altcookie;
};
struct nd_region_desc {