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 |        default y | ||||||
|        select SBITMAP |        select SBITMAP | ||||||
|        select SRCU |        select SRCU | ||||||
|        select DAX |  | ||||||
|        help |        help | ||||||
| 	 Provide block layer support for the kernel. | 	 Provide block layer support for the kernel. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,6 +14,7 @@ | ||||||
| #include <linux/module.h> | #include <linux/module.h> | ||||||
| #include <linux/mount.h> | #include <linux/mount.h> | ||||||
| #include <linux/magic.h> | #include <linux/magic.h> | ||||||
|  | #include <linux/genhd.h> | ||||||
| #include <linux/cdev.h> | #include <linux/cdev.h> | ||||||
| #include <linux/hash.h> | #include <linux/hash.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
|  | @ -47,6 +48,75 @@ void dax_read_unlock(int id) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL_GPL(dax_read_unlock); | 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 |  * struct dax_device - anchor object for dax services | ||||||
|  * @inode: core vfs |  * @inode: core vfs | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ config FS_DAX | ||||||
| 	depends on MMU | 	depends on MMU | ||||||
| 	depends on !(ARM || MIPS || SPARC) | 	depends on !(ARM || MIPS || SPARC) | ||||||
| 	select FS_IOMAP | 	select FS_IOMAP | ||||||
|  | 	select DAX | ||||||
| 	help | 	help | ||||||
| 	  Direct Access (DAX) can be used on memory-backed block devices. | 	  Direct Access (DAX) can be used on memory-backed block devices. | ||||||
| 	  If the block device supports DAX and the filesystem supports DAX, | 	  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); | 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 |  * pseudo-fs | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ | ||||||
| #include <linux/log2.h> | #include <linux/log2.h> | ||||||
| #include <linux/quotaops.h> | #include <linux/quotaops.h> | ||||||
| #include <linux/uaccess.h> | #include <linux/uaccess.h> | ||||||
|  | #include <linux/dax.h> | ||||||
| #include "ext2.h" | #include "ext2.h" | ||||||
| #include "xattr.h" | #include "xattr.h" | ||||||
| #include "acl.h" | #include "acl.h" | ||||||
|  |  | ||||||
|  | @ -37,6 +37,7 @@ | ||||||
| #include <linux/ctype.h> | #include <linux/ctype.h> | ||||||
| #include <linux/log2.h> | #include <linux/log2.h> | ||||||
| #include <linux/crc16.h> | #include <linux/crc16.h> | ||||||
|  | #include <linux/dax.h> | ||||||
| #include <linux/cleancache.h> | #include <linux/cleancache.h> | ||||||
| #include <linux/uaccess.h> | #include <linux/uaccess.h> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -52,6 +52,7 @@ | ||||||
| #include "xfs_reflink.h" | #include "xfs_reflink.h" | ||||||
| 
 | 
 | ||||||
| #include <linux/namei.h> | #include <linux/namei.h> | ||||||
|  | #include <linux/dax.h> | ||||||
| #include <linux/init.h> | #include <linux/init.h> | ||||||
| #include <linux/slab.h> | #include <linux/slab.h> | ||||||
| #include <linux/mount.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_read_page(struct block_device *, sector_t, struct page *); | ||||||
| extern int bdev_write_page(struct block_device *, sector_t, struct page *, | extern int bdev_write_page(struct block_device *, sector_t, struct page *, | ||||||
| 						struct writeback_control *); | 						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 */ | #else /* CONFIG_BLOCK */ | ||||||
| 
 | 
 | ||||||
| struct block_device; | struct block_device; | ||||||
|  |  | ||||||
|  | @ -18,12 +18,38 @@ struct dax_operations { | ||||||
| 			void **, pfn_t *); | 			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); | int dax_read_lock(void); | ||||||
| void dax_read_unlock(int id); | 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, | struct dax_device *alloc_dax(void *private, const char *host, | ||||||
| 		const struct dax_operations *ops); | 		const struct dax_operations *ops); | ||||||
| void put_dax(struct dax_device *dax_dev); |  | ||||||
| bool dax_alive(struct dax_device *dax_dev); | bool dax_alive(struct dax_device *dax_dev); | ||||||
| void kill_dax(struct dax_device *dax_dev); | void kill_dax(struct dax_device *dax_dev); | ||||||
| void *dax_get_private(struct dax_device *dax_dev); | void *dax_get_private(struct dax_device *dax_dev); | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Dan Williams
						Dan Williams