forked from mirrors/linux
		
	block, dax: move "select DAX" from BLOCK to FS_DAX
For configurations that do not enable DAX filesystems or drivers, do not require the DAX core to be built. Given that the 'direct_access' method has been removed from 'block_device_operations', we can also go ahead and remove the block-related dax helper functions from fs/block_dev.c to drivers/dax/super.c. This keeps dax details out of the block layer and lets the DAX core be built as a module in the FS_DAX=n case. Filesystems need to include dax.h to call bdev_dax_supported(). Cc: linux-xfs@vger.kernel.org Cc: Jens Axboe <axboe@kernel.dk> Cc: "Theodore Ts'o" <tytso@mit.edu> Cc: Matthew Wilcox <mawilcox@microsoft.com> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: "Darrick J. Wong" <darrick.wong@oracle.com> Cc: Ross Zwisler <ross.zwisler@linux.intel.com> Reviewed-by: Jan Kara <jack@suse.com> Reported-by: Geert Uytterhoeven <geert@linux-m68k.org> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
This commit is contained in:
		
							parent
							
								
									74d71a01ab
								
							
						
					
					
						commit
						ef51042472
					
				
					 9 changed files with 102 additions and 71 deletions
				
			
		|  | @ -6,7 +6,6 @@ menuconfig BLOCK | |||
|        default y | ||||
|        select SBITMAP | ||||
|        select SRCU | ||||
|        select DAX | ||||
|        help | ||||
| 	 Provide block layer support for the kernel. | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,7 @@ | |||
| #include <linux/module.h> | ||||
| #include <linux/mount.h> | ||||
| #include <linux/magic.h> | ||||
| #include <linux/genhd.h> | ||||
| #include <linux/cdev.h> | ||||
| #include <linux/hash.h> | ||||
| #include <linux/slab.h> | ||||
|  | @ -47,6 +48,75 @@ void dax_read_unlock(int id) | |||
| } | ||||
| EXPORT_SYMBOL_GPL(dax_read_unlock); | ||||
| 
 | ||||
| int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, | ||||
| 		pgoff_t *pgoff) | ||||
| { | ||||
| 	phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512; | ||||
| 
 | ||||
| 	if (pgoff) | ||||
| 		*pgoff = PHYS_PFN(phys_off); | ||||
| 	if (phys_off % PAGE_SIZE || size % PAGE_SIZE) | ||||
| 		return -EINVAL; | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(bdev_dax_pgoff); | ||||
| 
 | ||||
| /**
 | ||||
|  * __bdev_dax_supported() - Check if the device supports dax for filesystem | ||||
|  * @sb: The superblock of the device | ||||
|  * @blocksize: The block size of the device | ||||
|  * | ||||
|  * This is a library function for filesystems to check if the block device | ||||
|  * can be mounted with dax option. | ||||
|  * | ||||
|  * Return: negative errno if unsupported, 0 if supported. | ||||
|  */ | ||||
| int __bdev_dax_supported(struct super_block *sb, int blocksize) | ||||
| { | ||||
| 	struct block_device *bdev = sb->s_bdev; | ||||
| 	struct dax_device *dax_dev; | ||||
| 	pgoff_t pgoff; | ||||
| 	int err, id; | ||||
| 	void *kaddr; | ||||
| 	pfn_t pfn; | ||||
| 	long len; | ||||
| 
 | ||||
| 	if (blocksize != PAGE_SIZE) { | ||||
| 		pr_err("VFS (%s): error: unsupported blocksize for dax\n", | ||||
| 				sb->s_id); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff); | ||||
| 	if (err) { | ||||
| 		pr_err("VFS (%s): error: unaligned partition for dax\n", | ||||
| 				sb->s_id); | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); | ||||
| 	if (!dax_dev) { | ||||
| 		pr_err("VFS (%s): error: device does not support dax\n", | ||||
| 				sb->s_id); | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| 
 | ||||
| 	id = dax_read_lock(); | ||||
| 	len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn); | ||||
| 	dax_read_unlock(id); | ||||
| 
 | ||||
| 	put_dax(dax_dev); | ||||
| 
 | ||||
| 	if (len < 1) { | ||||
| 		pr_err("VFS (%s): error: dax access failed (%ld)", | ||||
| 				sb->s_id, len); | ||||
| 		return len < 0 ? len : -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(__bdev_dax_supported); | ||||
| 
 | ||||
| /**
 | ||||
|  * struct dax_device - anchor object for dax services | ||||
|  * @inode: core vfs | ||||
|  |  | |||
|  | @ -39,6 +39,7 @@ config FS_DAX | |||
| 	depends on MMU | ||||
| 	depends on !(ARM || MIPS || SPARC) | ||||
| 	select FS_IOMAP | ||||
| 	select DAX | ||||
| 	help | ||||
| 	  Direct Access (DAX) can be used on memory-backed block devices. | ||||
| 	  If the block device supports DAX and the filesystem supports DAX, | ||||
|  |  | |||
|  | @ -718,72 +718,6 @@ int bdev_write_page(struct block_device *bdev, sector_t sector, | |||
| } | ||||
| EXPORT_SYMBOL_GPL(bdev_write_page); | ||||
| 
 | ||||
| int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size, | ||||
| 		pgoff_t *pgoff) | ||||
| { | ||||
| 	phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512; | ||||
| 
 | ||||
| 	if (pgoff) | ||||
| 		*pgoff = PHYS_PFN(phys_off); | ||||
| 	if (phys_off % PAGE_SIZE || size % PAGE_SIZE) | ||||
| 		return -EINVAL; | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(bdev_dax_pgoff); | ||||
| 
 | ||||
| /**
 | ||||
|  * bdev_dax_supported() - Check if the device supports dax for filesystem | ||||
|  * @sb: The superblock of the device | ||||
|  * @blocksize: The block size of the device | ||||
|  * | ||||
|  * This is a library function for filesystems to check if the block device | ||||
|  * can be mounted with dax option. | ||||
|  * | ||||
|  * Return: negative errno if unsupported, 0 if supported. | ||||
|  */ | ||||
| int bdev_dax_supported(struct super_block *sb, int blocksize) | ||||
| { | ||||
| 	struct block_device *bdev = sb->s_bdev; | ||||
| 	struct dax_device *dax_dev; | ||||
| 	pgoff_t pgoff; | ||||
| 	int err, id; | ||||
| 	void *kaddr; | ||||
| 	pfn_t pfn; | ||||
| 	long len; | ||||
| 
 | ||||
| 	if (blocksize != PAGE_SIZE) { | ||||
| 		vfs_msg(sb, KERN_ERR, "error: unsupported blocksize for dax"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff); | ||||
| 	if (err) { | ||||
| 		vfs_msg(sb, KERN_ERR, "error: unaligned partition for dax"); | ||||
| 		return err; | ||||
| 	} | ||||
| 
 | ||||
| 	dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); | ||||
| 	if (!dax_dev) { | ||||
| 		vfs_msg(sb, KERN_ERR, "error: device does not support dax"); | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| 
 | ||||
| 	id = dax_read_lock(); | ||||
| 	len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn); | ||||
| 	dax_read_unlock(id); | ||||
| 
 | ||||
| 	put_dax(dax_dev); | ||||
| 
 | ||||
| 	if (len < 1) { | ||||
| 		vfs_msg(sb, KERN_ERR, | ||||
| 				"error: dax access failed (%ld)", len); | ||||
| 		return len < 0 ? len : -EIO; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL_GPL(bdev_dax_supported); | ||||
| 
 | ||||
| /*
 | ||||
|  * pseudo-fs | ||||
|  */ | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ | |||
| #include <linux/log2.h> | ||||
| #include <linux/quotaops.h> | ||||
| #include <linux/uaccess.h> | ||||
| #include <linux/dax.h> | ||||
| #include "ext2.h" | ||||
| #include "xattr.h" | ||||
| #include "acl.h" | ||||
|  |  | |||
|  | @ -37,6 +37,7 @@ | |||
| #include <linux/ctype.h> | ||||
| #include <linux/log2.h> | ||||
| #include <linux/crc16.h> | ||||
| #include <linux/dax.h> | ||||
| #include <linux/cleancache.h> | ||||
| #include <linux/uaccess.h> | ||||
| 
 | ||||
|  |  | |||
|  | @ -52,6 +52,7 @@ | |||
| #include "xfs_reflink.h" | ||||
| 
 | ||||
| #include <linux/namei.h> | ||||
| #include <linux/dax.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/mount.h> | ||||
|  |  | |||
|  | @ -1940,8 +1940,6 @@ extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int, | |||
| extern int bdev_read_page(struct block_device *, sector_t, struct page *); | ||||
| extern int bdev_write_page(struct block_device *, sector_t, struct page *, | ||||
| 						struct writeback_control *); | ||||
| extern int bdev_dax_supported(struct super_block *, int); | ||||
| int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff); | ||||
| #else /* CONFIG_BLOCK */ | ||||
| 
 | ||||
| struct block_device; | ||||
|  |  | |||
|  | @ -18,12 +18,38 @@ struct dax_operations { | |||
| 			void **, pfn_t *); | ||||
| }; | ||||
| 
 | ||||
| int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff); | ||||
| #if IS_ENABLED(CONFIG_FS_DAX) | ||||
| int __bdev_dax_supported(struct super_block *sb, int blocksize); | ||||
| static inline int bdev_dax_supported(struct super_block *sb, int blocksize) | ||||
| { | ||||
| 	return __bdev_dax_supported(sb, blocksize); | ||||
| } | ||||
| #else | ||||
| static inline int bdev_dax_supported(struct super_block *sb, int blocksize) | ||||
| { | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| #if IS_ENABLED(CONFIG_DAX) | ||||
| struct dax_device *dax_get_by_host(const char *host); | ||||
| void put_dax(struct dax_device *dax_dev); | ||||
| #else | ||||
| static inline struct dax_device *dax_get_by_host(const char *host) | ||||
| { | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
| static inline void put_dax(struct dax_device *dax_dev) | ||||
| { | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| int dax_read_lock(void); | ||||
| void dax_read_unlock(int id); | ||||
| struct dax_device *dax_get_by_host(const char *host); | ||||
| struct dax_device *alloc_dax(void *private, const char *host, | ||||
| 		const struct dax_operations *ops); | ||||
| void put_dax(struct dax_device *dax_dev); | ||||
| bool dax_alive(struct dax_device *dax_dev); | ||||
| void kill_dax(struct dax_device *dax_dev); | ||||
| void *dax_get_private(struct dax_device *dax_dev); | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue
	
	 Dan Williams
						Dan Williams