mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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