Commit 98a29c39 authored by Dan Williams's avatar Dan Williams

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: default avatarDan Williams <dan.j.williams@intel.com>
parent 991d9020
...@@ -1860,16 +1860,58 @@ static struct device *nd_namespace_blk_create(struct nd_region *nd_region) ...@@ -1860,16 +1860,58 @@ static struct device *nd_namespace_blk_create(struct nd_region *nd_region)
return &nsblk->common.dev; return &nsblk->common.dev;
} }
void nd_region_create_blk_seed(struct nd_region *nd_region) static struct device *nd_namespace_pmem_create(struct nd_region *nd_region)
{
struct nd_namespace_pmem *nspm;
struct resource *res;
struct device *dev;
if (!is_nd_pmem(&nd_region->dev))
return NULL;
nspm = kzalloc(sizeof(*nspm), GFP_KERNEL);
if (!nspm)
return NULL;
dev = &nspm->nsio.common.dev;
dev->type = &namespace_pmem_device_type;
dev->parent = &nd_region->dev;
res = &nspm->nsio.res;
res->name = dev_name(&nd_region->dev);
res->flags = IORESOURCE_MEM;
nspm->id = ida_simple_get(&nd_region->ns_ida, 0, 0, GFP_KERNEL);
if (nspm->id < 0) {
kfree(nspm);
return NULL;
}
dev_set_name(dev, "namespace%d.%d", nd_region->id, nspm->id);
dev->parent = &nd_region->dev;
dev->groups = nd_namespace_attribute_groups;
nd_namespace_pmem_set_resource(nd_region, nspm, 0);
return dev;
}
void nd_region_create_ns_seed(struct nd_region *nd_region)
{ {
WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev)); WARN_ON(!is_nvdimm_bus_locked(&nd_region->dev));
nd_region->ns_seed = nd_namespace_blk_create(nd_region);
if (nd_region_to_nstype(nd_region) == ND_DEVICE_NAMESPACE_IO)
return;
if (is_nd_blk(&nd_region->dev))
nd_region->ns_seed = nd_namespace_blk_create(nd_region);
else
nd_region->ns_seed = nd_namespace_pmem_create(nd_region);
/* /*
* Seed creation failures are not fatal, provisioning is simply * Seed creation failures are not fatal, provisioning is simply
* disabled until memory becomes available * disabled until memory becomes available
*/ */
if (!nd_region->ns_seed) if (!nd_region->ns_seed)
dev_err(&nd_region->dev, "failed to create blk namespace\n"); dev_err(&nd_region->dev, "failed to create %s namespace\n",
is_nd_blk(&nd_region->dev) ? "blk" : "pmem");
else else
nd_device_register(nd_region->ns_seed); nd_device_register(nd_region->ns_seed);
} }
......
...@@ -71,7 +71,7 @@ void nvdimm_devs_exit(void); ...@@ -71,7 +71,7 @@ void nvdimm_devs_exit(void);
void nd_region_devs_exit(void); void nd_region_devs_exit(void);
void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev); void nd_region_probe_success(struct nvdimm_bus *nvdimm_bus, struct device *dev);
struct nd_region; struct nd_region;
void nd_region_create_blk_seed(struct nd_region *nd_region); void nd_region_create_ns_seed(struct nd_region *nd_region);
void nd_region_create_btt_seed(struct nd_region *nd_region); void nd_region_create_btt_seed(struct nd_region *nd_region);
void nd_region_create_pfn_seed(struct nd_region *nd_region); void nd_region_create_pfn_seed(struct nd_region *nd_region);
void nd_region_create_dax_seed(struct nd_region *nd_region); void nd_region_create_dax_seed(struct nd_region *nd_region);
......
...@@ -530,11 +530,12 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, ...@@ -530,11 +530,12 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus,
if (is_nd_pmem(dev)) if (is_nd_pmem(dev))
return; return;
} }
if (dev->parent && is_nd_blk(dev->parent) && probe) { if (dev->parent && (is_nd_blk(dev->parent) || is_nd_pmem(dev->parent))
&& probe) {
nd_region = to_nd_region(dev->parent); nd_region = to_nd_region(dev->parent);
nvdimm_bus_lock(dev); nvdimm_bus_lock(dev);
if (nd_region->ns_seed == dev) if (nd_region->ns_seed == dev)
nd_region_create_blk_seed(nd_region); nd_region_create_ns_seed(nd_region);
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
} }
if (is_nd_btt(dev) && probe) { if (is_nd_btt(dev) && probe) {
...@@ -544,23 +545,30 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus, ...@@ -544,23 +545,30 @@ static void nd_region_notify_driver_action(struct nvdimm_bus *nvdimm_bus,
nvdimm_bus_lock(dev); nvdimm_bus_lock(dev);
if (nd_region->btt_seed == dev) if (nd_region->btt_seed == dev)
nd_region_create_btt_seed(nd_region); nd_region_create_btt_seed(nd_region);
if (nd_region->ns_seed == &nd_btt->ndns->dev && if (nd_region->ns_seed == &nd_btt->ndns->dev)
is_nd_blk(dev->parent)) nd_region_create_ns_seed(nd_region);
nd_region_create_blk_seed(nd_region);
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
} }
if (is_nd_pfn(dev) && probe) { if (is_nd_pfn(dev) && probe) {
struct nd_pfn *nd_pfn = to_nd_pfn(dev);
nd_region = to_nd_region(dev->parent); nd_region = to_nd_region(dev->parent);
nvdimm_bus_lock(dev); nvdimm_bus_lock(dev);
if (nd_region->pfn_seed == dev) if (nd_region->pfn_seed == dev)
nd_region_create_pfn_seed(nd_region); nd_region_create_pfn_seed(nd_region);
if (nd_region->ns_seed == &nd_pfn->ndns->dev)
nd_region_create_ns_seed(nd_region);
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
} }
if (is_nd_dax(dev) && probe) { if (is_nd_dax(dev) && probe) {
struct nd_dax *nd_dax = to_nd_dax(dev);
nd_region = to_nd_region(dev->parent); nd_region = to_nd_region(dev->parent);
nvdimm_bus_lock(dev); nvdimm_bus_lock(dev);
if (nd_region->dax_seed == dev) if (nd_region->dax_seed == dev)
nd_region_create_dax_seed(nd_region); nd_region_create_dax_seed(nd_region);
if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
nd_region_create_ns_seed(nd_region);
nvdimm_bus_unlock(dev); nvdimm_bus_unlock(dev);
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment