From: Ira Weiny <ira.we...@intel.com>

Switching between DAX and non-DAX on a file is racy with respect to data
operations.  However, if no data is involved the flag is safe to switch.

Allow toggling the physical flag if a file is empty.  The file length
check is not racy with respect to other operations as it is performed
under XFS_MMAPLOCK_EXCL and XFS_IOLOCK_EXCL locks.

Signed-off-by: Ira Weiny <ira.we...@intel.com>
---
 fs/xfs/xfs_ioctl.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index d3a7340d3209..3839684c249b 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -33,6 +33,7 @@
 #include "xfs_sb.h"
 #include "xfs_ag.h"
 #include "xfs_health.h"
+#include "libxfs/xfs_dir2.h"
 
 #include <linux/mount.h>
 #include <linux/namei.h>
@@ -1232,12 +1233,10 @@ xfs_diflags_to_linux(
                inode->i_flags |= S_NOATIME;
        else
                inode->i_flags &= ~S_NOATIME;
-#if 0  /* disabled until the flag switching races are sorted out */
        if (xflags & FS_XFLAG_DAX)
                inode->i_flags |= S_DAX;
        else
                inode->i_flags &= ~S_DAX;
-#endif
 }
 
 static int
@@ -1320,6 +1319,12 @@ xfs_ioctl_setattr_dax_invalidate(
 
        /* lock, flush and invalidate mapping in preparation for flag change */
        xfs_ilock(ip, XFS_MMAPLOCK_EXCL | XFS_IOLOCK_EXCL);
+
+       if (i_size_read(inode) != 0) {
+               error = -EOPNOTSUPP;
+               goto out_unlock;
+       }
+
        error = filemap_write_and_wait(inode->i_mapping);
        if (error)
                goto out_unlock;
-- 
2.20.1

Reply via email to