Commit d10050f6 authored by John Garry's avatar John Garry Committed by Long Li
Browse files

fs: xfs: Support FS_XFLAG_ATOMICWRITES for forcealign

maillist inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I9VTE3
CVE: NA

Reference: https://lore.kernel.org/all/20240326133813.3224593-1-john.g.garry@oracle.com/



--------------------------------

Add initial support for FS_XFLAG_ATOMICWRITES for forcealign enaabled.

Current kernel support for atomic writes is based on HW support (for atomic
writes). As such, it is required to ensure extent alignment with
atomic_write_unit_max so that an atomic write can result in a single
HW-compliant IO operation.

rtvol also guarantees extent alignment, but we are basing support initially
on forcealign, which is not supported for rtvol yet.

Signed-off-by: default avatarJohn Garry <john.g.garry@oracle.com>
Signed-off-by: default avatarLong Li <leo.lilong@huawei.com>
parent 8dc00053
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -354,12 +354,16 @@ xfs_sb_has_compat_feature(
#define XFS_SB_FEAT_RO_COMPAT_REFLINK  (1 << 2)		/* reflinked files */
#define XFS_SB_FEAT_RO_COMPAT_INOBTCNT (1 << 3)		/* inobt block counts */
#define XFS_SB_FEAT_RO_COMPAT_FORCEALIGN (1 << 30)	/* aligned file data extents */
#define XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES (1 << 31)	/* atomicwrites enabled */

#define XFS_SB_FEAT_RO_COMPAT_ALL \
		(XFS_SB_FEAT_RO_COMPAT_FINOBT | \
		 XFS_SB_FEAT_RO_COMPAT_RMAPBT | \
		 XFS_SB_FEAT_RO_COMPAT_REFLINK| \
		 XFS_SB_FEAT_RO_COMPAT_INOBTCNT| \
		 XFS_SB_FEAT_RO_COMPAT_FORCEALIGN)
		 XFS_SB_FEAT_RO_COMPAT_FORCEALIGN| \
		 XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES)

#define XFS_SB_FEAT_RO_COMPAT_UNKNOWN	~XFS_SB_FEAT_RO_COMPAT_ALL
static inline bool
xfs_sb_has_ro_compat_feature(
@@ -976,16 +980,18 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev)
#define XFS_DIFLAG2_BIGTIME_BIT	3	/* big timestamps */
/* data extent mappings for regular files must be aligned to extent size hint */
#define XFS_DIFLAG2_FORCEALIGN_BIT 5
#define XFS_DIFLAG2_ATOMICWRITES_BIT 6

#define XFS_DIFLAG2_DAX		(1 << XFS_DIFLAG2_DAX_BIT)
#define XFS_DIFLAG2_REFLINK     (1 << XFS_DIFLAG2_REFLINK_BIT)
#define XFS_DIFLAG2_COWEXTSIZE  (1 << XFS_DIFLAG2_COWEXTSIZE_BIT)
#define XFS_DIFLAG2_BIGTIME	(1 << XFS_DIFLAG2_BIGTIME_BIT)
#define XFS_DIFLAG2_FORCEALIGN	(1 << XFS_DIFLAG2_FORCEALIGN_BIT)
#define XFS_DIFLAG2_ATOMICWRITES	(1 << XFS_DIFLAG2_ATOMICWRITES_BIT)

#define XFS_DIFLAG2_ANY \
	(XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \
	 XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN)
	 XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN | XFS_DIFLAG2_ATOMICWRITES)

static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip)
{
+2 −0
Original line number Diff line number Diff line
@@ -118,6 +118,8 @@ xfs_sb_version_to_features(
		features |= XFS_FEAT_INOBTCNT;
	if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FORCEALIGN)
		features |= XFS_FEAT_FORCEALIGN;
	if (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_ATOMICWRITES)
		features |= XFS_FEAT_ATOMICWRITES;
	if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_FTYPE)
		features |= XFS_FEAT_FTYPE;
	if (sbp->sb_features_incompat & XFS_SB_FEAT_INCOMPAT_SPINODES)
+2 −0
Original line number Diff line number Diff line
@@ -659,6 +659,8 @@ _xfs_dic2xflags(
			flags |= FS_XFLAG_COWEXTSIZE;
		if (di_flags2 & XFS_DIFLAG2_FORCEALIGN)
			flags |= FS_XFLAG_FORCEALIGN;
		if (di_flags2 & XFS_DIFLAG2_ATOMICWRITES)
			flags |= FS_XFLAG_ATOMICWRITES;
	}

	if (has_attr)
+6 −0
Original line number Diff line number Diff line
@@ -272,6 +272,12 @@ static inline bool xfs_inode_forcealign(struct xfs_inode *ip)
{
	return ip->i_d.di_flags2 & XFS_DIFLAG2_FORCEALIGN;
}

static inline bool xfs_inode_atomicwrites(struct xfs_inode *ip)
{
	return ip->i_d.di_flags2 & XFS_DIFLAG2_ATOMICWRITES;
}

/*
 * Return the buftarg used for data allocations on a given inode.
 */
+13 −2
Original line number Diff line number Diff line
@@ -1200,6 +1200,8 @@ xfs_flags2diflags2(
		di_flags2 |= XFS_DIFLAG2_COWEXTSIZE;
	if (xflags & FS_XFLAG_FORCEALIGN)
		di_flags2 |= XFS_DIFLAG2_FORCEALIGN;
	if (xflags & FS_XFLAG_ATOMICWRITES)
		di_flags2 |= XFS_DIFLAG2_ATOMICWRITES;

	return di_flags2;
}
@@ -1212,10 +1214,12 @@ xfs_ioctl_setattr_xflags(
{
	struct xfs_mount	*mp = ip->i_mount;
	uint64_t		di_flags2;
	bool			atomic_writes = fa->fsx_xflags & FS_XFLAG_ATOMICWRITES;

	/* Can't change realtime flag if any extents are allocated. */
	/* Can't change realtime or atomic flag if any extents are allocated. */
	if ((ip->i_df.if_nextents || ip->i_delayed_blks) &&
	    XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME))
	    (XFS_IS_REALTIME_INODE(ip) != (fa->fsx_xflags & FS_XFLAG_REALTIME) ||
	     atomic_writes != xfs_inode_atomicwrites(ip)))
		return -EINVAL;

	/* If realtime flag is set then must have realtime device */
@@ -1254,6 +1258,13 @@ xfs_ioctl_setattr_xflags(
			return -EINVAL;
	}

	if (atomic_writes) {
		if (!xfs_has_atomicwrites(mp))
			return -EINVAL;
		if (!(fa->fsx_xflags & FS_XFLAG_FORCEALIGN))
			return -EINVAL;
	}

	ip->i_d.di_flags = xfs_flags2diflags(ip, fa->fsx_xflags);
	ip->i_d.di_flags2 = di_flags2;

Loading