mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	dax: Move mandatory ->zero_page_range() check in alloc_dax()
zero_page_range() dax operation is mandatory for dax devices. Right now that check happens in dax_zero_page_range() function. Dan thinks that's too late and its better to do the check earlier in alloc_dax(). I also modified alloc_dax() to return pointer with error code in it in case of failure. Right now it returns NULL and caller assumes failure happened due to -ENOMEM. But with this ->zero_page_range() check, I need to return -EINVAL instead. Signed-off-by: Vivek Goyal <vgoyal@redhat.com> Link: https://lore.kernel.org/r/20200401161125.GB9398@redhat.com Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
		
							parent
							
								
									4f3b4f161d
								
							
						
					
					
						commit
						4e4ced9379
					
				
					 5 changed files with 18 additions and 11 deletions
				
			
		| 
						 | 
					@ -421,8 +421,10 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
 | 
				
			||||||
	 * device outside of mmap of the resulting character device.
 | 
						 * device outside of mmap of the resulting character device.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	dax_dev = alloc_dax(dev_dax, NULL, NULL, DAXDEV_F_SYNC);
 | 
						dax_dev = alloc_dax(dev_dax, NULL, NULL, DAXDEV_F_SYNC);
 | 
				
			||||||
	if (!dax_dev)
 | 
						if (IS_ERR(dax_dev)) {
 | 
				
			||||||
 | 
							rc = PTR_ERR(dax_dev);
 | 
				
			||||||
		goto err;
 | 
							goto err;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* a device_dax instance is dead while the driver is not attached */
 | 
						/* a device_dax instance is dead while the driver is not attached */
 | 
				
			||||||
	kill_dax(dax_dev);
 | 
						kill_dax(dax_dev);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -349,9 +349,6 @@ int dax_zero_page_range(struct dax_device *dax_dev, pgoff_t pgoff,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!dax_alive(dax_dev))
 | 
						if (!dax_alive(dax_dev))
 | 
				
			||||||
		return -ENXIO;
 | 
							return -ENXIO;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (!dax_dev->ops->zero_page_range)
 | 
					 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * There are no callers that want to zero more than one page as of now.
 | 
						 * There are no callers that want to zero more than one page as of now.
 | 
				
			||||||
	 * Once users are there, this check can be removed after the
 | 
						 * Once users are there, this check can be removed after the
 | 
				
			||||||
| 
						 | 
					@ -571,9 +568,16 @@ struct dax_device *alloc_dax(void *private, const char *__host,
 | 
				
			||||||
	dev_t devt;
 | 
						dev_t devt;
 | 
				
			||||||
	int minor;
 | 
						int minor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (ops && !ops->zero_page_range) {
 | 
				
			||||||
 | 
							pr_debug("%s: error: device does not provide dax"
 | 
				
			||||||
 | 
								 " operation zero_page_range()\n",
 | 
				
			||||||
 | 
								 __host ? __host : "Unknown");
 | 
				
			||||||
 | 
							return ERR_PTR(-EINVAL);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	host = kstrdup(__host, GFP_KERNEL);
 | 
						host = kstrdup(__host, GFP_KERNEL);
 | 
				
			||||||
	if (__host && !host)
 | 
						if (__host && !host)
 | 
				
			||||||
		return NULL;
 | 
							return ERR_PTR(-ENOMEM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	minor = ida_simple_get(&dax_minor_ida, 0, MINORMASK+1, GFP_KERNEL);
 | 
						minor = ida_simple_get(&dax_minor_ida, 0, MINORMASK+1, GFP_KERNEL);
 | 
				
			||||||
	if (minor < 0)
 | 
						if (minor < 0)
 | 
				
			||||||
| 
						 | 
					@ -596,7 +600,7 @@ struct dax_device *alloc_dax(void *private, const char *__host,
 | 
				
			||||||
	ida_simple_remove(&dax_minor_ida, minor);
 | 
						ida_simple_remove(&dax_minor_ida, minor);
 | 
				
			||||||
 err_minor:
 | 
					 err_minor:
 | 
				
			||||||
	kfree(host);
 | 
						kfree(host);
 | 
				
			||||||
	return NULL;
 | 
						return ERR_PTR(-ENOMEM);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
EXPORT_SYMBOL_GPL(alloc_dax);
 | 
					EXPORT_SYMBOL_GPL(alloc_dax);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2005,7 +2005,7 @@ static struct mapped_device *alloc_dev(int minor)
 | 
				
			||||||
	if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
 | 
						if (IS_ENABLED(CONFIG_DAX_DRIVER)) {
 | 
				
			||||||
		md->dax_dev = alloc_dax(md, md->disk->disk_name,
 | 
							md->dax_dev = alloc_dax(md, md->disk->disk_name,
 | 
				
			||||||
					&dm_dax_ops, 0);
 | 
										&dm_dax_ops, 0);
 | 
				
			||||||
		if (!md->dax_dev)
 | 
							if (IS_ERR(md->dax_dev))
 | 
				
			||||||
			goto bad;
 | 
								goto bad;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -487,9 +487,9 @@ static int pmem_attach_disk(struct device *dev,
 | 
				
			||||||
	if (is_nvdimm_sync(nd_region))
 | 
						if (is_nvdimm_sync(nd_region))
 | 
				
			||||||
		flags = DAXDEV_F_SYNC;
 | 
							flags = DAXDEV_F_SYNC;
 | 
				
			||||||
	dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags);
 | 
						dax_dev = alloc_dax(pmem, disk->disk_name, &pmem_dax_ops, flags);
 | 
				
			||||||
	if (!dax_dev) {
 | 
						if (IS_ERR(dax_dev)) {
 | 
				
			||||||
		put_disk(disk);
 | 
							put_disk(disk);
 | 
				
			||||||
		return -ENOMEM;
 | 
							return PTR_ERR(dax_dev);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dax_write_cache(dax_dev, nvdimm_has_cache(nd_region));
 | 
						dax_write_cache(dax_dev, nvdimm_has_cache(nd_region));
 | 
				
			||||||
	pmem->dax_dev = dax_dev;
 | 
						pmem->dax_dev = dax_dev;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -695,8 +695,9 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name,
 | 
						dev_info->dax_dev = alloc_dax(dev_info, dev_info->gd->disk_name,
 | 
				
			||||||
			&dcssblk_dax_ops, DAXDEV_F_SYNC);
 | 
								&dcssblk_dax_ops, DAXDEV_F_SYNC);
 | 
				
			||||||
	if (!dev_info->dax_dev) {
 | 
						if (IS_ERR(dev_info->dax_dev)) {
 | 
				
			||||||
		rc = -ENOMEM;
 | 
							rc = PTR_ERR(dev_info->dax_dev);
 | 
				
			||||||
 | 
							dev_info->dax_dev = NULL;
 | 
				
			||||||
		goto put_dev;
 | 
							goto put_dev;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue