diff options
author | Dan Williams <dan.j.williams@intel.com> | 2016-09-30 18:28:27 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2016-10-07 12:22:53 -0400 |
commit | 98a29c39dc689298d2f834f40102cba752eb49c0 (patch) | |
tree | e1b3551216f9181641c35bbf4cd76f0562f45030 | |
parent | 991d9020f3e0447ea00c7c7f11fed364d977320a (diff) |
libnvdimm, namespace: allow creation of multiple pmem-namespaces per region
Similar to BLK regions, publish new seed namespace devices to allow
unused PMEM region capacity to be consumed by additional namespaces.
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | drivers/nvdimm/namespace_devs.c | 48 | ||||
-rw-r--r-- | drivers/nvdimm/nd-core.h | 2 | ||||
-rw-r--r-- | drivers/nvdimm/region_devs.c | 18 |
3 files changed, 59 insertions, 9 deletions
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c index fa51d751ccf7..3509cff68ef9 100644 --- a/drivers/nvdimm/namespace_devs.c +++ b/drivers/nvdimm/namespace_devs.c | |||
@@ -1860,16 +1860,58 @@ static struct device *nd_namespace_blk_create(struct nd_region *nd_region) | |||
1860 | return &nsblk->common.dev; | 1860 | return &nsblk->common.dev; |
1861 | } | 1861 | } |
1862 | 1862 | ||
1863 | void nd_region_create_blk_seed(struct nd_region *nd_region) | 1863 | static struct device *nd_namespace_pmem_create(struct nd_region *nd_region) |
1864 | { | ||
1865 | struct nd_namespace_pmem *nspm; | ||
1866 | struct resource *res; | ||
1867 | struct device *dev; | ||
1868 | |||
1869 | if (!is_nd_pmem(&nd_region->dev)) | ||
1870 | return NULL; | ||
1871 | |||
1872 | nspm = kzalloc(sizeof(*nspm), GFP_KERNEL); | ||
1873 | if (!nspm) | ||
1874 | return NULL; | ||
1875 | |||
1876 | dev = &nspm->nsio.common.dev; | ||
1877 | dev->type = &namespace_pmem_device_type; | ||
1878 | dev->parent = &nd_region->dev; | ||
1879 | res = &nspm->nsio.res; | ||
1880 | res->name = dev_name(&nd_region->dev); | ||
1881 | res->flags = IORESOURCE_MEM; | ||
1882 | |||
1883 | nspm->id = ida_simple_get(&nd_region->ns_ida, 0, 0, GFP_KERNEL); | ||
1884 | if (nspm->id < 0) { | ||
1885 | kfree(nspm); | ||
1886 | return NULL; | ||
1887 | } | ||
1888 | dev_set_name(dev, "namespace%d.%d", nd_region->id, nspm->id); | ||
1889 | dev->parent = &nd_region->dev; | ||
1890 | dev->groups = nd_namespace_attribute_groups; | ||
1891 | nd_namespace_pmem_set_resource(nd_region, nspm, 0); | ||
1892 | |||
1893 | return dev; | ||
1894 | } | ||
1895 | |||
1896 | void nd_region_create_ns_seed(struct nd_region *nd_region) | ||
1864 | { | 1897 | { |
1865 | WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev)); | 1898 | WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev)); |
1866 | nd_region->ns_seed = nd_namespace_blk_create(nd_region); | 1899 | |
1900 | if (nd_region_to_nstype(nd_region) == ND_DEVICE_NAMESPACE_IO) | ||
1901 | return; | ||
1902 | |||
1903 | if (is_nd_blk(&nd_region->dev)) | ||
1904 | nd_region->ns_seed = nd_namespace_blk_create(nd_region); | ||
1905 | else | ||
1906 | nd_region->ns_seed = nd_namespace_pmem_create(nd_region); | ||
1907 | |||
1867 | /* | 1908 | /* |
1868 | * Seed creation failures are not fatal, provisioning is simply | 1909 | * Seed creation failures are not fatal, provisioning is simply |
1869 | * disabled until memory becomes available | 1910 | * disabled until memory becomes available |
1870 | */ | 1911 | */ |
1871 | if (!nd_region->ns_seed) | 1912 | if (!nd_region->ns_seed) |
1872 | dev_err(&nd_region->dev, "failed to create blk namespace\n"); | 1913 | dev_err(&nd_region->dev, "failed to create %s namespace\n", |
1914 | is_nd_blk(&nd_region->dev) ? "blk" : "pmem"); | ||
1873 | else | 1915 | else |
1874 | nd_device_register(nd_region->ns_seed); | 1916 | nd_device_register(nd_region->ns_seed); |
1875 | } | 1917 | } |
diff --git a/drivers/nvdimm/nd-core.h b/drivers/nvdimm/nd-core.h index 3ba0b96ce7de..8623e57c2ce3 100644 --- a/drivers/nvdimm/nd-core.h +++ b/drivers/nvdimm/nd-core.h | |||
@@ -71,7 +71,7 @@ void nvdimm_devs_exit(void); | |||
71 | void nd_region_devs_exit(void); | 71 | void nd_region_devs_exit(void); |
72 | void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev); | 72 | void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev); |
73 | struct nd_region; | 73 | struct nd_region; |
74 | void nd_region_create_blk_seed(struct nd_region *nd_region); | 74 | void nd_region_create_ns_seed(struct nd_region *nd_region); |
75 | void nd_region_create_btt_seed(struct nd_region *nd_region); | 75 | void nd_region_create_btt_seed(struct nd_region *nd_region); |
76 | void nd_region_create_pfn_seed(struct nd_region *nd_region); | 76 | void nd_region_create_pfn_seed(struct nd_region *nd_region); |
77 | void nd_region_create_dax_seed(struct nd_region *nd_region); | 77 | void nd_region_create_dax_seed(struct nd_region *nd_region); |
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 3ac534aec60c..4f74e009b135 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c | |||
@@ -530,11 +530,12 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, | |||
530 | if (is_nd_pmem(dev)) | 530 | if (is_nd_pmem(dev)) |
531 | return; | 531 | return; |
532 | } | 532 | } |
533 | if (dev->parent && is_nd_blk(dev->parent) && probe) { | 533 | if (dev->parent && (is_nd_blk(dev->parent) || is_nd_pmem(dev->parent)) |
534 | && probe) { | ||
534 | nd_region = to_nd_region(dev->parent); | 535 | nd_region = to_nd_region(dev->parent); |
535 | nvdimm_bus_lock(dev); | 536 | nvdimm_bus_lock(dev); |
536 | if (nd_region->ns_seed == dev) | 537 | if (nd_region->ns_seed == dev) |
537 | nd_region_create_blk_seed(nd_region); | 538 | nd_region_create_ns_seed(nd_region); |
538 | nvdimm_bus_unlock(dev); | 539 | nvdimm_bus_unlock(dev); |
539 | } | 540 | } |
540 | if (is_nd_btt(dev) && probe) { | 541 | if (is_nd_btt(dev) && probe) { |
@@ -544,23 +545,30 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, | |||
544 | nvdimm_bus_lock(dev); | 545 | nvdimm_bus_lock(dev); |
545 | if (nd_region->btt_seed == dev) | 546 | if (nd_region->btt_seed == dev) |
546 | nd_region_create_btt_seed(nd_region); | 547 | nd_region_create_btt_seed(nd_region); |
547 | if (nd_region->ns_seed == &nd_btt->ndns->dev && | 548 | if (nd_region->ns_seed == &nd_btt->ndns->dev) |
548 | is_nd_blk(dev->parent)) | 549 | nd_region_create_ns_seed(nd_region); |
549 | nd_region_create_blk_seed(nd_region); | ||
550 | nvdimm_bus_unlock(dev); | 550 | nvdimm_bus_unlock(dev); |
551 | } | 551 | } |
552 | if (is_nd_pfn(dev) && probe) { | 552 | if (is_nd_pfn(dev) && probe) { |
553 | struct nd_pfn *nd_pfn = to_nd_pfn(dev); | ||
554 | |||
553 | nd_region = to_nd_region(dev->parent); | 555 | nd_region = to_nd_region(dev->parent); |
554 | nvdimm_bus_lock(dev); | 556 | nvdimm_bus_lock(dev); |
555 | if (nd_region->pfn_seed == dev) | 557 | if (nd_region->pfn_seed == dev) |
556 | nd_region_create_pfn_seed(nd_region); | 558 | nd_region_create_pfn_seed(nd_region); |
559 | if (nd_region->ns_seed == &nd_pfn->ndns->dev) | ||
560 | nd_region_create_ns_seed(nd_region); | ||
557 | nvdimm_bus_unlock(dev); | 561 | nvdimm_bus_unlock(dev); |
558 | } | 562 | } |
559 | if (is_nd_dax(dev) && probe) { | 563 | if (is_nd_dax(dev) && probe) { |
564 | struct nd_dax *nd_dax = to_nd_dax(dev); | ||
565 | |||
560 | nd_region = to_nd_region(dev->parent); | 566 | nd_region = to_nd_region(dev->parent); |
561 | nvdimm_bus_lock(dev); | 567 | nvdimm_bus_lock(dev); |
562 | if (nd_region->dax_seed == dev) | 568 | if (nd_region->dax_seed == dev) |
563 | nd_region_create_dax_seed(nd_region); | 569 | nd_region_create_dax_seed(nd_region); |
570 | if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev) | ||
571 | nd_region_create_ns_seed(nd_region); | ||
564 | nvdimm_bus_unlock(dev); | 572 | nvdimm_bus_unlock(dev); |
565 | } | 573 | } |
566 | } | 574 | } |