]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
xfs: introduce per-inode DAX enablement
authorDave Chinner <dchinner@redhat.com>
Mon, 4 Jan 2016 05:44:15 +0000 (16:44 +1100)
committerDave Chinner <david@fromorbit.com>
Mon, 4 Jan 2016 05:44:15 +0000 (16:44 +1100)
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>
fs/xfs/libxfs/xfs_format.h
fs/xfs/xfs_inode.c
fs/xfs/xfs_ioctl.c
fs/xfs/xfs_iops.c
include/uapi/linux/fs.h

index f28eeabb9454ecc5eb5887fe5b9bf834500f3c68..b4ae7cef028a20721d49166df34b0e5a989ec6f9 100644 (file)
@@ -1023,6 +1023,15 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
         XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \
         XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG | XFS_DIFLAG_FILESTREAM)
 
+/*
+ * Values for di_flags2 These start by being exposed to userspace in the upper
+ * 16 bits of the XFS_XFLAG_s range.
+ */
+#define XFS_DIFLAG2_DAX_BIT    0       /* use DAX for this inode */
+#define XFS_DIFLAG2_DAX                (1 << XFS_DIFLAG2_DAX_BIT)
+
+#define XFS_DIFLAG2_ANY                (XFS_DIFLAG2_DAX)
+
 /*
  * Inode number format:
  * low inopblog bits - offset in block
index ca9ca5a3c53510c11cd61b3f11355d94c9090ce4..89299085450eb72304e68d1d4c3b1b6cf697e14d 100644 (file)
@@ -610,7 +610,9 @@ __xfs_iflock(
 
 STATIC uint
 _xfs_dic2xflags(
-       __uint16_t              di_flags)
+       __uint16_t              di_flags,
+       uint64_t                di_flags2,
+       bool                    has_attr)
 {
        uint                    flags = 0;
 
@@ -645,25 +647,32 @@ _xfs_dic2xflags(
                        flags |= FS_XFLAG_FILESTREAM;
        }
 
+       if (di_flags2 & XFS_DIFLAG2_ANY) {
+               if (di_flags2 & XFS_DIFLAG2_DAX)
+                       flags |= FS_XFLAG_DAX;
+       }
+
+       if (has_attr)
+               flags |= FS_XFLAG_HASATTR;
+
        return flags;
 }
 
 uint
 xfs_ip2xflags(
-       xfs_inode_t             *ip)
+       struct xfs_inode        *ip)
 {
-       xfs_icdinode_t          *dic = &ip->i_d;
+       struct xfs_icdinode     *dic = &ip->i_d;
 
-       return _xfs_dic2xflags(dic->di_flags) |
-                               (XFS_IFORK_Q(ip) ? FS_XFLAG_HASATTR : 0);
+       return _xfs_dic2xflags(dic->di_flags, dic->di_flags2, XFS_IFORK_Q(ip));
 }
 
 uint
 xfs_dic2xflags(
-       xfs_dinode_t            *dip)
+       struct xfs_dinode       *dip)
 {
-       return _xfs_dic2xflags(be16_to_cpu(dip->di_flags)) |
-                               (XFS_DFORK_Q(dip) ? FS_XFLAG_HASATTR : 0);
+       return _xfs_dic2xflags(be16_to_cpu(dip->di_flags),
+                               be64_to_cpu(dip->di_flags2), XFS_DFORK_Q(dip));
 }
 
 /*
@@ -862,7 +871,8 @@ xfs_ialloc(
        case S_IFREG:
        case S_IFDIR:
                if (pip && (pip->i_d.di_flags & XFS_DIFLAG_ANY)) {
-                       uint    di_flags = 0;
+                       uint64_t        di_flags2 = 0;
+                       uint            di_flags = 0;
 
                        if (S_ISDIR(mode)) {
                                if (pip->i_d.di_flags & XFS_DIFLAG_RTINHERIT)
@@ -898,7 +908,11 @@ xfs_ialloc(
                                di_flags |= XFS_DIFLAG_NODEFRAG;
                        if (pip->i_d.di_flags & XFS_DIFLAG_FILESTREAM)
                                di_flags |= XFS_DIFLAG_FILESTREAM;
+                       if (pip->i_d.di_flags2 & XFS_DIFLAG2_DAX)
+                               di_flags2 |= XFS_DIFLAG2_DAX;
+
                        ip->i_d.di_flags |= di_flags;
+                       ip->i_d.di_flags2 |= di_flags2;
                }
                /* FALLTHROUGH */
        case S_IFLNK:
index 94b35eb32cb6af40c4114442eec0c92c1b9cbae2..478d04e07f9500d6ceed20231deb6b474161c708 100644 (file)
@@ -945,6 +945,7 @@ xfs_set_diflags(
        unsigned int            xflags)
 {
        unsigned int            di_flags;
+       uint64_t                di_flags2;
 
        /* can't set PREALLOC this way, just preserve it */
        di_flags = (ip->i_d.di_flags & XFS_DIFLAG_PREALLOC);
@@ -977,8 +978,18 @@ xfs_set_diflags(
                if (xflags & FS_XFLAG_EXTSIZE)
                        di_flags |= XFS_DIFLAG_EXTSIZE;
        }
-
        ip->i_d.di_flags = di_flags;
+
+       /* diflags2 only valid for v3 inodes. */
+       if (ip->i_d.di_version < 3)
+               return;
+
+       di_flags2 = 0;
+       if (xflags & FS_XFLAG_DAX)
+               di_flags2 |= XFS_DIFLAG2_DAX;
+
+       ip->i_d.di_flags2 = di_flags2;
+
 }
 
 STATIC void
@@ -1004,6 +1015,11 @@ xfs_diflags_to_linux(
                inode->i_flags |= S_NOATIME;
        else
                inode->i_flags &= ~S_NOATIME;
+       if (xflags & FS_XFLAG_DAX)
+               inode->i_flags |= S_DAX;
+       else
+               inode->i_flags &= ~S_DAX;
+
 }
 
 static int
index 245268a0cdf06e4d518ee915a0add70ef5a42dc6..a1b8af158d0599c1174853d5061a9fb538d77b80 100644 (file)
@@ -1201,8 +1201,8 @@ xfs_diflags_to_iflags(
                inode->i_flags |= S_SYNC;
        if (flags & XFS_DIFLAG_NOATIME)
                inode->i_flags |= S_NOATIME;
-       /* XXX: Also needs an on-disk per inode flag! */
-       if (ip->i_mount->m_flags & XFS_MOUNT_DAX)
+       if (ip->i_mount->m_flags & XFS_MOUNT_DAX ||
+           ip->i_d.di_flags2 & XFS_DIFLAG2_DAX)
                inode->i_flags |= S_DAX;
 }
 
index df175dddd07f68f77da90e7b292b379553a6ca45..4cad4c8ab6b2ac461b8f00c57495b3bf19f26531 100644 (file)
@@ -138,6 +138,7 @@ struct fsxattr {
 #define FS_XFLAG_EXTSZINHERIT  0x00001000      /* inherit inode extent size */
 #define FS_XFLAG_NODEFRAG      0x00002000      /* do not defragment */
 #define FS_XFLAG_FILESTREAM    0x00004000      /* use filestream allocator */
+#define FS_XFLAG_DAX           0x00008000      /* use DAX for IO */
 #define FS_XFLAG_HASATTR       0x80000000      /* no DIFLAG for this   */
 
 /* the read-only stuff doesn't really belong here, but any other place is