aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-05-30 16:03:45 -0400
committerDarrick J. Wong <darrick.wong@oracle.com>2018-05-31 11:58:33 -0400
commitba23cba9b3bdc967aabdc6ff1e3e9b11ce05bb4f (patch)
treeab508ad6c442fa52b4b59a27edb5084279dbb6d9
parentd25522f10cfa342a20867086a516c45c87b0877c (diff)
fs: allow per-device dax status checking for filesystems
Change bdev_dax_supported so it takes a bdev parameter. This enables multi-device filesystems like xfs to check that a dax device can work for the particular filesystem. Once that's in place, actually fix all the parts of XFS where we need to be able to distinguish between datadev and rtdev. This patch fixes the problem where we screw up the dax support checking in xfs if the datadev and rtdev have different dax capabilities. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> [rez: Re-added __bdev_dax_supported() for !CONFIG_FS_DAX cases] Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com> Reviewed-by: Eric Sandeen <sandeen@redhat.com>
-rw-r--r--drivers/dax/super.c26
-rw-r--r--fs/ext2/super.c2
-rw-r--r--fs/ext4/super.c2
-rw-r--r--fs/xfs/xfs_ioctl.c3
-rw-r--r--fs/xfs/xfs_iops.c30
-rw-r--r--fs/xfs/xfs_super.c10
-rw-r--r--include/linux/dax.h9
7 files changed, 55 insertions, 27 deletions
diff --git a/drivers/dax/super.c b/drivers/dax/super.c
index 2b2332b605e4..3943feb9a090 100644
--- a/drivers/dax/super.c
+++ b/drivers/dax/super.c
@@ -74,7 +74,7 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
74 74
75/** 75/**
76 * __bdev_dax_supported() - Check if the device supports dax for filesystem 76 * __bdev_dax_supported() - Check if the device supports dax for filesystem
77 * @sb: The superblock of the device 77 * @bdev: block device to check
78 * @blocksize: The block size of the device 78 * @blocksize: The block size of the device
79 * 79 *
80 * This is a library function for filesystems to check if the block device 80 * This is a library function for filesystems to check if the block device
@@ -82,33 +82,33 @@ EXPORT_SYMBOL_GPL(fs_dax_get_by_bdev);
82 * 82 *
83 * Return: negative errno if unsupported, 0 if supported. 83 * Return: negative errno if unsupported, 0 if supported.
84 */ 84 */
85int __bdev_dax_supported(struct super_block *sb, int blocksize) 85int __bdev_dax_supported(struct block_device *bdev, int blocksize)
86{ 86{
87 struct block_device *bdev = sb->s_bdev;
88 struct dax_device *dax_dev; 87 struct dax_device *dax_dev;
89 pgoff_t pgoff; 88 pgoff_t pgoff;
90 int err, id; 89 int err, id;
91 void *kaddr; 90 void *kaddr;
92 pfn_t pfn; 91 pfn_t pfn;
93 long len; 92 long len;
93 char buf[BDEVNAME_SIZE];
94 94
95 if (blocksize != PAGE_SIZE) { 95 if (blocksize != PAGE_SIZE) {
96 pr_debug("VFS (%s): error: unsupported blocksize for dax\n", 96 pr_debug("%s: error: unsupported blocksize for dax\n",
97 sb->s_id); 97 bdevname(bdev, buf));
98 return -EINVAL; 98 return -EINVAL;
99 } 99 }
100 100
101 err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff); 101 err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
102 if (err) { 102 if (err) {
103 pr_debug("VFS (%s): error: unaligned partition for dax\n", 103 pr_debug("%s: error: unaligned partition for dax\n",
104 sb->s_id); 104 bdevname(bdev, buf));
105 return err; 105 return err;
106 } 106 }
107 107
108 dax_dev = dax_get_by_host(bdev->bd_disk->disk_name); 108 dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
109 if (!dax_dev) { 109 if (!dax_dev) {
110 pr_debug("VFS (%s): error: device does not support dax\n", 110 pr_debug("%s: error: device does not support dax\n",
111 sb->s_id); 111 bdevname(bdev, buf));
112 return -EOPNOTSUPP; 112 return -EOPNOTSUPP;
113 } 113 }
114 114
@@ -119,8 +119,8 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize)
119 put_dax(dax_dev); 119 put_dax(dax_dev);
120 120
121 if (len < 1) { 121 if (len < 1) {
122 pr_debug("VFS (%s): error: dax access failed (%ld)\n", 122 pr_debug("%s: error: dax access failed (%ld)\n",
123 sb->s_id, len); 123 bdevname(bdev, buf), len);
124 return len < 0 ? len : -EIO; 124 return len < 0 ? len : -EIO;
125 } 125 }
126 126
@@ -137,8 +137,8 @@ int __bdev_dax_supported(struct super_block *sb, int blocksize)
137 } else if (pfn_t_devmap(pfn)) { 137 } else if (pfn_t_devmap(pfn)) {
138 /* pass */; 138 /* pass */;
139 } else { 139 } else {
140 pr_debug("VFS (%s): error: dax support not enabled\n", 140 pr_debug("%s: error: dax support not enabled\n",
141 sb->s_id); 141 bdevname(bdev, buf));
142 return -EOPNOTSUPP; 142 return -EOPNOTSUPP;
143 } 143 }
144 144
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index de1694512f1f..9627c3054b5c 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -961,7 +961,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent)
961 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size); 961 blocksize = BLOCK_SIZE << le32_to_cpu(sbi->s_es->s_log_block_size);
962 962
963 if (sbi->s_mount_opt & EXT2_MOUNT_DAX) { 963 if (sbi->s_mount_opt & EXT2_MOUNT_DAX) {
964 err = bdev_dax_supported(sb, blocksize); 964 err = bdev_dax_supported(sb->s_bdev, blocksize);
965 if (err) { 965 if (err) {
966 ext2_msg(sb, KERN_ERR, 966 ext2_msg(sb, KERN_ERR,
967 "DAX unsupported by block device. Turning off DAX."); 967 "DAX unsupported by block device. Turning off DAX.");
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index eb104e8476f0..089170e99895 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3732,7 +3732,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3732 " that may contain inline data"); 3732 " that may contain inline data");
3733 sbi->s_mount_opt &= ~EXT4_MOUNT_DAX; 3733 sbi->s_mount_opt &= ~EXT4_MOUNT_DAX;
3734 } 3734 }
3735 err = bdev_dax_supported(sb, blocksize); 3735 err = bdev_dax_supported(sb->s_bdev, blocksize);
3736 if (err) { 3736 if (err) {
3737 ext4_msg(sb, KERN_ERR, 3737 ext4_msg(sb, KERN_ERR,
3738 "DAX unsupported by block device. Turning off DAX."); 3738 "DAX unsupported by block device. Turning off DAX.");
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index f9c97ea52961..c9a5b75a73a8 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -1103,7 +1103,8 @@ xfs_ioctl_setattr_dax_invalidate(
1103 if (fa->fsx_xflags & FS_XFLAG_DAX) { 1103 if (fa->fsx_xflags & FS_XFLAG_DAX) {
1104 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) 1104 if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode)))
1105 return -EINVAL; 1105 return -EINVAL;
1106 if (bdev_dax_supported(sb, sb->s_blocksize) < 0) 1106 if (bdev_dax_supported(xfs_find_bdev_for_inode(VFS_I(ip)),
1107 sb->s_blocksize) < 0)
1107 return -EINVAL; 1108 return -EINVAL;
1108 } 1109 }
1109 1110
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 5afe3c2234b3..9925d75411bb 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1195,6 +1195,30 @@ static const struct inode_operations xfs_inline_symlink_inode_operations = {
1195 .update_time = xfs_vn_update_time, 1195 .update_time = xfs_vn_update_time,
1196}; 1196};
1197 1197
1198/* Figure out if this file actually supports DAX. */
1199static bool
1200xfs_inode_supports_dax(
1201 struct xfs_inode *ip)
1202{
1203 struct xfs_mount *mp = ip->i_mount;
1204
1205 /* Only supported on non-reflinked files. */
1206 if (!S_ISREG(VFS_I(ip)->i_mode) || xfs_is_reflink_inode(ip))
1207 return false;
1208
1209 /* DAX mount option or DAX iflag must be set. */
1210 if (!(mp->m_flags & XFS_MOUNT_DAX) &&
1211 !(ip->i_d.di_flags2 & XFS_DIFLAG2_DAX))
1212 return false;
1213
1214 /* Block size must match page size */
1215 if (mp->m_sb.sb_blocksize != PAGE_SIZE)
1216 return false;
1217
1218 /* Device has to support DAX too. */
1219 return xfs_find_daxdev_for_inode(VFS_I(ip)) != NULL;
1220}
1221
1198STATIC void 1222STATIC void
1199xfs_diflags_to_iflags( 1223xfs_diflags_to_iflags(
1200 struct inode *inode, 1224 struct inode *inode,
@@ -1213,11 +1237,7 @@ xfs_diflags_to_iflags(
1213 inode->i_flags |= S_SYNC; 1237 inode->i_flags |= S_SYNC;
1214 if (flags & XFS_DIFLAG_NOATIME) 1238 if (flags & XFS_DIFLAG_NOATIME)
1215 inode->i_flags |= S_NOATIME; 1239 inode->i_flags |= S_NOATIME;
1216 if (S_ISREG(inode->i_mode) && 1240 if (xfs_inode_supports_dax(ip))
1217 ip->i_mount->m_sb.sb_blocksize == PAGE_SIZE &&
1218 !xfs_is_reflink_inode(ip) &&
1219 (ip->i_mount->m_flags & XFS_MOUNT_DAX ||
1220 ip->i_d.di_flags2 & XFS_DIFLAG2_DAX))
1221 inode->i_flags |= S_DAX; 1241 inode->i_flags |= S_DAX;
1222} 1242}
1223 1243
diff --git a/fs/xfs/xfs_super.c b/fs/xfs/xfs_super.c
index 39e5ec3d407f..fed63e0b8f4d 100644
--- a/fs/xfs/xfs_super.c
+++ b/fs/xfs/xfs_super.c
@@ -1701,11 +1701,17 @@ xfs_fs_fill_super(
1701 sb->s_flags |= SB_I_VERSION; 1701 sb->s_flags |= SB_I_VERSION;
1702 1702
1703 if (mp->m_flags & XFS_MOUNT_DAX) { 1703 if (mp->m_flags & XFS_MOUNT_DAX) {
1704 int error2 = 0;
1705
1704 xfs_warn(mp, 1706 xfs_warn(mp,
1705 "DAX enabled. Warning: EXPERIMENTAL, use at your own risk"); 1707 "DAX enabled. Warning: EXPERIMENTAL, use at your own risk");
1706 1708
1707 error = bdev_dax_supported(sb, sb->s_blocksize); 1709 error = bdev_dax_supported(mp->m_ddev_targp->bt_bdev,
1708 if (error) { 1710 sb->s_blocksize);
1711 if (mp->m_rtdev_targp)
1712 error2 = bdev_dax_supported(mp->m_rtdev_targp->bt_bdev,
1713 sb->s_blocksize);
1714 if (error && error2) {
1709 xfs_alert(mp, 1715 xfs_alert(mp,
1710 "DAX unsupported by block device. Turning off DAX."); 1716 "DAX unsupported by block device. Turning off DAX.");
1711 mp->m_flags &= ~XFS_MOUNT_DAX; 1717 mp->m_flags &= ~XFS_MOUNT_DAX;
diff --git a/include/linux/dax.h b/include/linux/dax.h
index f9eb22ad341e..2a4f7295c12b 100644
--- a/include/linux/dax.h
+++ b/include/linux/dax.h
@@ -64,10 +64,10 @@ static inline bool dax_write_cache_enabled(struct dax_device *dax_dev)
64struct writeback_control; 64struct writeback_control;
65int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff); 65int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
66#if IS_ENABLED(CONFIG_FS_DAX) 66#if IS_ENABLED(CONFIG_FS_DAX)
67int __bdev_dax_supported(struct super_block *sb, int blocksize); 67int __bdev_dax_supported(struct block_device *bdev, int blocksize);
68static inline int bdev_dax_supported(struct super_block *sb, int blocksize) 68static inline int bdev_dax_supported(struct block_device *bdev, int blocksize)
69{ 69{
70 return __bdev_dax_supported(sb, blocksize); 70 return __bdev_dax_supported(bdev, blocksize);
71} 71}
72 72
73static inline struct dax_device *fs_dax_get_by_host(const char *host) 73static inline struct dax_device *fs_dax_get_by_host(const char *host)
@@ -84,7 +84,8 @@ struct dax_device *fs_dax_get_by_bdev(struct block_device *bdev);
84int dax_writeback_mapping_range(struct address_space *mapping, 84int dax_writeback_mapping_range(struct address_space *mapping,
85 struct block_device *bdev, struct writeback_control *wbc); 85 struct block_device *bdev, struct writeback_control *wbc);
86#else 86#else
87static inline int bdev_dax_supported(struct super_block *sb, int blocksize) 87static inline int bdev_dax_supported(struct block_device *bdev,
88 int blocksize)
88{ 89{
89 return -EOPNOTSUPP; 90 return -EOPNOTSUPP;
90} 91}