From 983997ce4b8de736c5c10c33c6cf4e40076dcbdf Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 29 Sep 2023 09:53:36 +0000 Subject: [PATCH 01/11] xfs: create a new inode flag to require extsize alignment of file data space Conflict: m_feature is not supported in struct xfs_mount, some feature related functions are deleted or renamed Add a new inode flag to require that all file data extent mappings must be aligned (both the file offset range and the allocated space itself) to the extent size hint. Having a separate COW extent size hint is no longer allowed. The goal here is to enable sysadmins and users to mandate that all space mappings in a file must have a startoff/blockcount that are aligned to (say) a 2MB alignment and that the startblock/blockcount will follow the same alignment. Signed-off-by: "Darrick J. Wong" Co-developed-by: John Garry Signed-off-by: John Garry --- include/linux.h | 5 +++++ include/xfs_inode.h | 5 +++++ libxfs/util.c | 2 ++ libxfs/xfs_format.h | 13 ++++++++++++- libxfs/xfs_inode_buf.c | 40 ++++++++++++++++++++++++++++++++++++++++ libxfs/xfs_inode_buf.h | 3 +++ 6 files changed, 67 insertions(+), 1 deletion(-) diff --git a/include/linux.h b/include/linux.h index 2465022..d95365b 100644 --- a/include/linux.h +++ b/include/linux.h @@ -246,6 +246,11 @@ struct fsxattr { #define FS_XFLAG_COWEXTSIZE 0x00010000 /* CoW extent size allocator hint */ #endif +/* data extent mappings for regular files must be aligned to extent size hint */ +#ifndef FS_XFLAG_FORCEALIGN +#define FS_XFLAG_FORCEALIGN 0x00020000 +#endif + #ifdef HAVE_GETFSMAP # include #else diff --git a/include/xfs_inode.h b/include/xfs_inode.h index 08a62d8..6d52a1d 100644 --- a/include/xfs_inode.h +++ b/include/xfs_inode.h @@ -164,6 +164,11 @@ static inline bool xfs_inode_has_bigtime(struct xfs_inode *ip) return ip->i_diflags2 & XFS_DIFLAG2_BIGTIME; } +static inline bool xfs_inode_forcealign(struct xfs_inode *ip) +{ + return ip->i_diflags2 & XFS_DIFLAG2_FORCEALIGN; +} + typedef struct cred { uid_t cr_uid; gid_t cr_gid; diff --git a/libxfs/util.c b/libxfs/util.c index 905f178..5750b3f 100644 --- a/libxfs/util.c +++ b/libxfs/util.c @@ -204,6 +204,8 @@ xfs_flags2diflags2( di_flags2 |= XFS_DIFLAG2_DAX; if (xflags & FS_XFLAG_COWEXTSIZE) di_flags2 |= XFS_DIFLAG2_COWEXTSIZE; + if (xflags & FS_XFLAG_FORCEALIGN) + di_flags2 |= XFS_DIFLAG2_FORCEALIGN; return di_flags2; } diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index 37570cf..c2db380 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -450,10 +450,12 @@ xfs_sb_has_compat_feature( #define XFS_SB_FEAT_RO_COMPAT_RMAPBT (1 << 1) /* reverse map btree */ #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_ALL \ (XFS_SB_FEAT_RO_COMPAT_FINOBT | \ XFS_SB_FEAT_RO_COMPAT_RMAPBT | \ XFS_SB_FEAT_RO_COMPAT_REFLINK| \ + XFS_SB_FEAT_RO_COMPAT_FORCEALIGN| \ XFS_SB_FEAT_RO_COMPAT_INOBTCNT) #define XFS_SB_FEAT_RO_COMPAT_UNKNOWN ~XFS_SB_FEAT_RO_COMPAT_ALL static inline bool @@ -586,6 +588,12 @@ static inline bool xfs_sb_version_hasinobtcounts(struct xfs_sb *sbp) (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_INOBTCNT); } +static inline bool xfs_sb_version_hasforcealign(struct xfs_sb *sbp) +{ + return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && + (sbp->sb_features_ro_compat & XFS_SB_FEAT_RO_COMPAT_FORCEALIGN); +} + static inline bool xfs_sb_version_needsrepair(struct xfs_sb *sbp) { return XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5 && @@ -1170,15 +1178,18 @@ static inline void xfs_dinode_put_rdev(struct xfs_dinode *dip, xfs_dev_t rdev) #define XFS_DIFLAG2_REFLINK_BIT 1 /* file's blocks may be shared */ #define XFS_DIFLAG2_COWEXTSIZE_BIT 2 /* copy on write extent size hint */ #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_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_ANY \ (XFS_DIFLAG2_DAX | XFS_DIFLAG2_REFLINK | XFS_DIFLAG2_COWEXTSIZE | \ - XFS_DIFLAG2_BIGTIME) + XFS_DIFLAG2_BIGTIME | XFS_DIFLAG2_FORCEALIGN) static inline bool xfs_dinode_has_bigtime(const struct xfs_dinode *dip) { diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index 7ecbfad..8a89685 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -551,6 +551,14 @@ xfs_dinode_verify( !xfs_sb_version_hasbigtime(&mp->m_sb)) return __this_address; + if (flags2 & XFS_DIFLAG2_FORCEALIGN) { + fa = xfs_inode_validate_forcealign(mp, mode, flags, + be32_to_cpu(dip->di_extsize), + be32_to_cpu(dip->di_cowextsize)); + if (fa) + return fa; + } + return NULL; } @@ -718,3 +726,35 @@ xfs_inode_validate_cowextsize( return NULL; } + +/* Validate the forcealign inode flag */ +xfs_failaddr_t +xfs_inode_validate_forcealign( + struct xfs_mount *mp, + uint16_t mode, + uint16_t flags, + uint32_t extsize, + uint32_t cowextsize) +{ + /* superblock rocompat feature flag */ + if (!xfs_sb_version_hasforcealign(&mp->m_sb)) + return __this_address; + + /* Only regular files and directories */ + if (!S_ISDIR(mode) && !S_ISREG(mode)) + return __this_address; + + /* Doesn't apply to realtime files */ + if (flags & XFS_DIFLAG_REALTIME) + return __this_address; + + /* Requires a nonzero extent size hint */ + if (extsize == 0) + return __this_address; + + /* Requires no cow extent size hint */ + if (cowextsize != 0) + return __this_address; + + return NULL; +} diff --git a/libxfs/xfs_inode_buf.h b/libxfs/xfs_inode_buf.h index 7f865bb..56ed6d7 100644 --- a/libxfs/xfs_inode_buf.h +++ b/libxfs/xfs_inode_buf.h @@ -33,6 +33,9 @@ xfs_failaddr_t xfs_inode_validate_extsize(struct xfs_mount *mp, xfs_failaddr_t xfs_inode_validate_cowextsize(struct xfs_mount *mp, uint32_t cowextsize, uint16_t mode, uint16_t flags, uint64_t flags2); +xfs_failaddr_t xfs_inode_validate_forcealign(struct xfs_mount *mp, + uint16_t mode, uint16_t flags, uint32_t extsize, + uint32_t cowextsize); static inline uint64_t xfs_inode_encode_bigtime(struct timespec64 tv) { -- 2.33.0