mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									e7b8948101
								
							
						
					
					
						commit
						58f88ca2df
					
				
					 5 changed files with 52 additions and 12 deletions
				
			
		| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue