aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/nvdimm/namespace_devs.c
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2016-10-07 02:13:15 -0400
committerDan Williams <dan.j.williams@intel.com>2016-10-07 12:20:53 -0400
commit0e3b0d123c8fd5c42f364aea3ab663b1f18dad39 (patch)
tree08e6a8ed499310bba97b8a3b96d33428d70b0bc8 /drivers/nvdimm/namespace_devs.c
parentbd4cd745b3b412ac93227640e3b337962f41d932 (diff)
libnvdimm, namespace: allow multiple pmem-namespaces per region at scan time
If label scanning finds multiple valid pmem namespaces allow them to be surfaced rather than fail namespace scanning. Support for creating multiple namespaces per region is saved for a later patch. Note that this adds some new error messages to clarify which of the pmem namespaces in the set are potentially impacted by invalid labels. Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Diffstat (limited to 'drivers/nvdimm/namespace_devs.c')
-rw-r--r--drivers/nvdimm/namespace_devs.c84
1 files changed, 72 insertions, 12 deletions
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index fbcadc7cb8fd..47d29632b937 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -29,7 +29,10 @@ static void namespace_io_release(struct device *dev)
29static void namespace_pmem_release(struct device *dev) 29static void namespace_pmem_release(struct device *dev)
30{ 30{
31 struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); 31 struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
32 struct nd_region *nd_region = to_nd_region(dev->parent);
32 33
34 if (nspm->id >= 0)
35 ida_simple_remove(&nd_region->ns_ida, nspm->id);
33 kfree(nspm->alt_name); 36 kfree(nspm->alt_name);
34 kfree(nspm->uuid); 37 kfree(nspm->uuid);
35 kfree(nspm); 38 kfree(nspm);
@@ -833,13 +836,45 @@ static int grow_dpa_allocation(struct nd_region *nd_region,
833 return 0; 836 return 0;
834} 837}
835 838
836static void nd_namespace_pmem_set_size(struct nd_region *nd_region, 839static void nd_namespace_pmem_set_resource(struct nd_region *nd_region,
837 struct nd_namespace_pmem *nspm, resource_size_t size) 840 struct nd_namespace_pmem *nspm, resource_size_t size)
838{ 841{
839 struct resource *res = &nspm->nsio.res; 842 struct resource *res = &nspm->nsio.res;
843 resource_size_t offset = 0;
840 844
841 res->start = nd_region->ndr_start; 845 if (size && !nspm->uuid) {
842 res->end = nd_region->ndr_start + size - 1; 846 WARN_ON_ONCE(1);
847 size = 0;
848 }
849
850 if (size && nspm->uuid) {
851 struct nd_mapping *nd_mapping = &nd_region->mapping[0];
852 struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
853 struct nd_label_id label_id;
854 struct resource *res;
855
856 if (!ndd) {
857 size = 0;
858 goto out;
859 }
860
861 nd_label_gen_id(&label_id, nspm->uuid, 0);
862
863 /* calculate a spa offset from the dpa allocation offset */
864 for_each_dpa_resource(ndd, res)
865 if (strcmp(res->name, label_id.id) == 0) {
866 offset = (res->start - nd_mapping->start)
867 * nd_region->ndr_mappings;
868 goto out;
869 }
870
871 WARN_ON_ONCE(1);
872 size = 0;
873 }
874
875 out:
876 res->start = nd_region->ndr_start + offset;
877 res->end = res->start + size - 1;
843} 878}
844 879
845static bool uuid_not_set(const u8 *uuid, struct device *dev, const char *where) 880static bool uuid_not_set(const u8 *uuid, struct device *dev, const char *where)
@@ -930,7 +965,7 @@ static ssize_t __size_store(struct device *dev, unsigned long long val)
930 if (is_namespace_pmem(dev)) { 965 if (is_namespace_pmem(dev)) {
931 struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev); 966 struct nd_namespace_pmem *nspm = to_nd_namespace_pmem(dev);
932 967
933 nd_namespace_pmem_set_size(nd_region, nspm, 968 nd_namespace_pmem_set_resource(nd_region, nspm,
934 val * nd_region->ndr_mappings); 969 val * nd_region->ndr_mappings);
935 } else if (is_namespace_blk(dev)) { 970 } else if (is_namespace_blk(dev)) {
936 struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev); 971 struct nd_namespace_blk *nsblk = to_nd_namespace_blk(dev);
@@ -1546,6 +1581,7 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
1546 1581
1547 for (i = 0; i < nd_region->ndr_mappings; i++) { 1582 for (i = 0; i < nd_region->ndr_mappings; i++) {
1548 struct nd_mapping *nd_mapping = &nd_region->mapping[i]; 1583 struct nd_mapping *nd_mapping = &nd_region->mapping[i];
1584 struct nvdimm_drvdata *ndd = to_ndd(nd_mapping);
1549 struct nd_namespace_label *nd_label = NULL; 1585 struct nd_namespace_label *nd_label = NULL;
1550 u64 hw_start, hw_end, pmem_start, pmem_end; 1586 u64 hw_start, hw_end, pmem_start, pmem_end;
1551 struct nd_label_ent *label_ent; 1587 struct nd_label_ent *label_ent;
@@ -1573,10 +1609,14 @@ static int select_pmem_id(struct nd_region *nd_region, u8 *pmem_id)
1573 hw_end = hw_start + nd_mapping->size; 1609 hw_end = hw_start + nd_mapping->size;
1574 pmem_start = __le64_to_cpu(nd_label->dpa); 1610 pmem_start = __le64_to_cpu(nd_label->dpa);
1575 pmem_end = pmem_start + __le64_to_cpu(nd_label->rawsize); 1611 pmem_end = pmem_start + __le64_to_cpu(nd_label->rawsize);
1576 if (pmem_start == hw_start && pmem_end <= hw_end) 1612 if (pmem_start >= hw_start && pmem_start < hw_end
1613 && pmem_end <= hw_end && pmem_end > hw_start)
1577 /* pass */; 1614 /* pass */;
1578 else 1615 else {
1616 dev_dbg(&nd_region->dev, "%s invalid label for %pUb\n",
1617 dev_name(ndd->dev), nd_label->uuid);
1579 return -EINVAL; 1618 return -EINVAL;
1619 }
1580 1620
1581 /* move recently validated label to the front of the list */ 1621 /* move recently validated label to the front of the list */
1582 list_move(&label_ent->list, &nd_mapping->labels); 1622 list_move(&label_ent->list, &nd_mapping->labels);
@@ -1618,6 +1658,7 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
1618 if (!nspm) 1658 if (!nspm)
1619 return ERR_PTR(-ENOMEM); 1659 return ERR_PTR(-ENOMEM);
1620 1660
1661 nspm->id = -1;
1621 dev = &nspm->nsio.common.dev; 1662 dev = &nspm->nsio.common.dev;
1622 dev->type = &namespace_pmem_device_type; 1663 dev->type = &namespace_pmem_device_type;
1623 dev->parent = &nd_region->dev; 1664 dev->parent = &nd_region->dev;
@@ -1629,11 +1670,15 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
1629 if (!has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i)) 1670 if (!has_uuid_at_pos(nd_region, nd_label->uuid, cookie, i))
1630 break; 1671 break;
1631 if (i < nd_region->ndr_mappings) { 1672 if (i < nd_region->ndr_mappings) {
1673 struct nvdimm_drvdata *ndd = to_ndd(&nd_region->mapping[i]);
1674
1632 /* 1675 /*
1633 * Give up if we don't find an instance of a uuid at each 1676 * Give up if we don't find an instance of a uuid at each
1634 * position (from 0 to nd_region->ndr_mappings - 1), or if we 1677 * position (from 0 to nd_region->ndr_mappings - 1), or if we
1635 * find a dimm with two instances of the same uuid. 1678 * find a dimm with two instances of the same uuid.
1636 */ 1679 */
1680 dev_err(&nd_region->dev, "%s missing label for %pUb\n",
1681 dev_name(ndd->dev), nd_label->uuid);
1637 rc = -EINVAL; 1682 rc = -EINVAL;
1638 goto err; 1683 goto err;
1639 } 1684 }
@@ -1679,7 +1724,7 @@ struct device *create_namespace_pmem(struct nd_region *nd_region,
1679 goto err; 1724 goto err;
1680 } 1725 }
1681 1726
1682 nd_namespace_pmem_set_size(nd_region, nspm, size); 1727 nd_namespace_pmem_set_resource(nd_region, nspm, size);
1683 1728
1684 return dev; 1729 return dev;
1685 err: 1730 err:
@@ -1961,23 +2006,31 @@ static struct device **scan_labels(struct nd_region *nd_region)
1961 goto err; 2006 goto err;
1962 dev = &nspm->nsio.common.dev; 2007 dev = &nspm->nsio.common.dev;
1963 dev->type = &namespace_pmem_device_type; 2008 dev->type = &namespace_pmem_device_type;
1964 nd_namespace_pmem_set_size(nd_region, nspm, 0); 2009 nd_namespace_pmem_set_resource(nd_region, nspm, 0);
1965 } 2010 }
1966 dev->parent = &nd_region->dev; 2011 dev->parent = &nd_region->dev;
1967 devs[count++] = dev; 2012 devs[count++] = dev;
1968 } else if (is_nd_pmem(&nd_region->dev)) { 2013 } else if (is_nd_pmem(&nd_region->dev)) {
1969 /* clean unselected labels */ 2014 /* clean unselected labels */
1970 for (i = 0; i < nd_region->ndr_mappings; i++) { 2015 for (i = 0; i < nd_region->ndr_mappings; i++) {
2016 struct list_head *l, *e;
2017 LIST_HEAD(list);
2018 int j;
2019
1971 nd_mapping = &nd_region->mapping[i]; 2020 nd_mapping = &nd_region->mapping[i];
1972 if (list_empty(&nd_mapping->labels)) { 2021 if (list_empty(&nd_mapping->labels)) {
1973 WARN_ON(1); 2022 WARN_ON(1);
1974 continue; 2023 continue;
1975 } 2024 }
1976 label_ent = list_first_entry(&nd_mapping->labels, 2025
1977 typeof(*label_ent), list); 2026 j = count;
1978 list_del(&label_ent->list); 2027 list_for_each_safe(l, e, &nd_mapping->labels) {
2028 if (!j--)
2029 break;
2030 list_move_tail(l, &list);
2031 }
1979 nd_mapping_free_labels(nd_mapping); 2032 nd_mapping_free_labels(nd_mapping);
1980 list_add(&label_ent->list, &nd_mapping->labels); 2033 list_splice_init(&list, &nd_mapping->labels);
1981 } 2034 }
1982 } 2035 }
1983 2036
@@ -2117,6 +2170,13 @@ int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
2117 id = ida_simple_get(&nd_region->ns_ida, 0, 0, 2170 id = ida_simple_get(&nd_region->ns_ida, 0, 0,
2118 GFP_KERNEL); 2171 GFP_KERNEL);
2119 nsblk->id = id; 2172 nsblk->id = id;
2173 } else if (type == ND_DEVICE_NAMESPACE_PMEM) {
2174 struct nd_namespace_pmem *nspm;
2175
2176 nspm = to_nd_namespace_pmem(dev);
2177 id = ida_simple_get(&nd_region->ns_ida, 0, 0,
2178 GFP_KERNEL);
2179 nspm->id = id;
2120 } else 2180 } else
2121 id = i; 2181 id = i;
2122 2182