mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									991d9020f3
								
							
						
					
					
						commit
						98a29c39dc
					
				
					 3 changed files with 59 additions and 9 deletions
				
			
		| 
						 | 
					@ -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));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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);
 | 
							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);
 | 
				
			||||||
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,
 | 
				
			||||||
		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,
 | 
				
			||||||
		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);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue