aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2016-01-04 00:44:15 -0500
committerDave Chinner <david@fromorbit.com>2016-01-04 00:44:15 -0500
commit58f88ca2df7270881de2034c8286233a89efe71c (patch)
tree216088a0e082b5458f570a31f5507fb63053de1a /fs/xfs
parente7b89481017b2111d188afd70bbd0da9e9b94cc9 (diff)
xfs: introduce per-inode DAX enablement
Rather than just being able to turn DAX on and off via a mount option, some applications may only want to enable DAX for certain performance critical files in a filesystem. This patch introduces a new inode flag to enable DAX in the v3 inode di_flags2 field. It adds support for setting and clearing flags in the di_flags2 field via the XFS_IOC_FSSETXATTR ioctl, and sets the S_DAX inode flag appropriately when it is seen. When this flag is set on a directory, it acts as an "inherit flag". That is, inodes created in the directory will automatically inherit the on-disk inode DAX flag, enabling administrators to set up directory heirarchies that automatically use DAX. Setting this flag on an empty root directory will make the entire filesystem use DAX by default. Signed-off-by: Dave Chinner <dchinner@redhat.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/libxfs/xfs_format.h9
-rw-r--r--fs/xfs/xfs_inode.c32
-rw-r--r--fs/xfs/xfs_ioctl.c18
-rw-r--r--fs/xfs/xfs_iops.c4
4 files changed, 51 insertions, 12 deletions
diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h
index f28eeabb9454..b4ae7cef028a 100644
--- a/fs/xfs/libxfs/xfs_format.h
+++ b/fs/xfs/libxfs/xfs_format.h
@@ -1024,6 +1024,15 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
1024 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM) 1024 XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
1025 1025
1026/* 1026/*
1027 * Values for di_flags2 These start by being exposed to userspace in the upper
1028 * 16 bits of the XFS_XFLAG_s range.
1029 */
1030#define XFS_DIFLAG2_DAX_BIT 0 /* use DAX for this inode */
1031#define XFS_DIFLAG2_DAX (1 << XFS_DIFLAG2_DAX_BIT)
1032
1033#define XFS_DIFLAG2_ANY (XFS_DIFLAG2_DAX)
1034
1035/*
1027 * Inode number format: 1036 * Inode number format:
1028 * low inopblog bits - offset in block 1037 * low inopblog bits - offset in block
1029 * next agblklog bits - block number in ag 1038 * next agblklog bits - block number in ag
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c
index ca9ca5a3c535..89299085450e 100644
--- a/fs/xfs/xfs_inode.c
+++ b/fs/xfs/xfs_inode.c
@@ -610,7 +610,9 @@ __xfs_iflock(
610 610
611STATIC uint 611STATIC uint
612_xfs_dic2xflags( 612_xfs_dic2xflags(
613 __uint16_t di_flags) 613 __uint16_t di_flags,
614 uint64_t di_flags2,
615 bool has_attr)
614{ 616{
615 uint flags = 0; 617 uint flags = 0;
616 618
@@ -645,25 +647,32 @@ _xfs_dic2xflags(
645 flags |= FS_XFLAG_FILESTREAM; 647 flags |= FS_XFLAG_FILESTREAM;
646 } 648 }
647 649
650 if (di_flags2 & XFS_DIFLAG2_ANY) {
651 if (di_flags2 & XFS_DIFLAG2_DAX)
652 flags |= FS_XFLAG_DAX;
653 }
654
655 if (has_attr)
656 flags |= FS_XFLAG_HASATTR;
657
648 return flags; 658 return flags;
649} 659}
650 660
651uint 661uint
652xfs_ip2xflags( 662xfs_ip2xflags(
653 xfs_inode_t *ip) 663 struct xfs_inode *ip)
654{ 664{
655 xfs_icdinode_t *dic = &ip->i_d; 665 struct xfs_icdinode *dic = &ip->i_d;
656 666
657 return _xfs_dic2xflags(dic->di_flags) | 667 return _xfs_dic2xflags(dic->di_flags, dic->di_flags2, XFS_IFORK_Q(ip));
658 (XFS_IFORK_Q(ip) ? FS_XFLAG_HASATTR : 0);
659} 668}
660 669
661uint 670uint
662xfs_dic2xflags( 671xfs_dic2xflags(
663 xfs_dinode_t *dip) 672 struct xfs_dinode *dip)
664{ 673{
665 return _xfs_dic2xflags(be16_to_cpu(dip->di_flags)) | 674 return _xfs_dic2xflags(be16_to_cpu(dip->di_flags),
666 (XFS_DFORK_Q(dip) ? FS_XFLAG_HASATTR : 0); 675 be64_to_cpu(dip->di_flags2), XFS_DFORK_Q(dip));
667} 676}
668 677
669/* 678/*
@@ -862,7 +871,8 @@ xfs_ialloc(
862 case S_IFREG: 871 case S_IFREG:
863 case S_IFDIR: 872 case S_IFDIR:
864 if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) { 873 if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
865 uint di_flags = 0; 874 uint64_t di_flags2 = 0;
875 uint di_flags = 0;
866 876
867 if (S_ISDIR(mode)) { 877 if (S_ISDIR(mode)) {
868 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT) 878 if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
@@ -898,7 +908,11 @@ xfs_ialloc(
898 di_flags |= XFS_DIFLAG_NODEFRAG; 908 di_flags |= XFS_DIFLAG_NODEFRAG;
899 if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM) 909 if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
900 di_flags |= XFS_DIFLAG_FILESTREAM; 910 di_flags |= XFS_DIFLAG_FILESTREAM;
911 if (pip->i_d.di_flags2 & XFS_DIFLAG2_DAX)
912 di_flags2 |= XFS_DIFLAG2_DAX;
913
901 ip->i_d.di_flags |= di_flags; 914 ip->i_d.di_flags |= di_flags;
915 ip->i_d.di_flags2 |= di_flags2;
902 } 916 }
903 /* FALLTHROUGH */ 917 /* FALLTHROUGH */
904 case S_IFLNK: 918 case S_IFLNK:
diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c
index 94b35eb32cb6..478d04e07f95 100644
--- a/fs/xfs/xfs_ioctl.c
+++ b/fs/xfs/xfs_ioctl.c
@@ -945,6 +945,7 @@ xfs_set_diflags(
945 unsigned int xflags) 945 unsigned int xflags)
946{ 946{
947 unsigned int di_flags; 947 unsigned int di_flags;
948 uint64_t di_flags2;
948 949
949 /* can't set PREALLOC this way, just preserve it */ 950 /* can't set PREALLOC this way, just preserve it */
950 di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC); 951 di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
@@ -977,8 +978,18 @@ xfs_set_diflags(
977 if (xflags & FS_XFLAG_EXTSIZE) 978 if (xflags & FS_XFLAG_EXTSIZE)
978 di_flags |= XFS_DIFLAG_EXTSIZE; 979 di_flags |= XFS_DIFLAG_EXTSIZE;
979 } 980 }
980
981 ip->i_d.di_flags = di_flags; 981 ip->i_d.di_flags = di_flags;
982
983 /* diflags2 only valid for v3 inodes. */
984 if (ip->i_d.di_version < 3)
985 return;
986
987 di_flags2 = 0;
988 if (xflags & FS_XFLAG_DAX)
989 di_flags2 |= XFS_DIFLAG2_DAX;
990
991 ip->i_d.di_flags2 = di_flags2;
992
982} 993}
983 994
984STATIC void 995STATIC void
@@ -1004,6 +1015,11 @@ xfs_diflags_to_linux(
1004 inode->i_flags |= S_NOATIME; 1015 inode->i_flags |= S_NOATIME;
1005 else 1016 else
1006 inode->i_flags &= ~S_NOATIME; 1017 inode->i_flags &= ~S_NOATIME;
1018 if (xflags & FS_XFLAG_DAX)
1019 inode->i_flags |= S_DAX;
1020 else
1021 inode->i_flags &= ~S_DAX;
1022
1007} 1023}
1008 1024
1009static int 1025static int
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 245268a0cdf0..a1b8af158d05 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -1201,8 +1201,8 @@ xfs_diflags_to_iflags(
1201 inode->i_flags |= S_SYNC; 1201 inode->i_flags |= S_SYNC;
1202 if (flags & XFS_DIFLAG_NOATIME) 1202 if (flags & XFS_DIFLAG_NOATIME)
1203 inode->i_flags |= S_NOATIME; 1203 inode->i_flags |= S_NOATIME;
1204 /* XXX: Also needs an on-disk per inode flag! */ 1204 if (ip->i_mount->m_flags & XFS_MOUNT_DAX ||
1205 if (ip->i_mount->m_flags & XFS_MOUNT_DAX) 1205 ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)
1206 inode->i_flags |= S_DAX; 1206 inode->i_flags |= S_DAX;
1207} 1207}
1208 1208