For when forcealign is enabled, blocks in an inode need to be unmapped according to extent alignment, like what is already done for rtvol. Signed-off-by: John Garry <john.g.garry@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_bmap.c | 39 +++++++++++++++++++++++++++++++++------ fs/xfs/xfs_inode.h | 5 +++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index 4f39a43d78a7..4a78ab193753 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5339,6 +5339,15 @@ xfs_bmap_del_extent_real( return 0; } +/* Return the offset of an block number within an extent for forcealign. */ +static xfs_extlen_t +xfs_forcealign_extent_offset( + struct xfs_inode *ip, + xfs_fsblock_t bno) +{ + return bno & (ip->i_extsize - 1); +} + /* * Unmap (remove) blocks from a file. * If nexts is nonzero then the number of extents to remove is limited to @@ -5361,6 +5370,7 @@ __xfs_bunmapi( struct xfs_bmbt_irec got; /* current extent record */ struct xfs_ifork *ifp; /* inode fork pointer */ int isrt; /* freeing in rt area */ + int isforcealign; /* freeing for file inode with forcealign */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ struct xfs_mount *mp = ip->i_mount; @@ -5397,7 +5407,10 @@ __xfs_bunmapi( return 0; } XFS_STATS_INC(mp, xs_blk_unmap); - isrt = xfs_ifork_is_realtime(ip, whichfork); + isrt = (whichfork == XFS_DATA_FORK) && XFS_IS_REALTIME_INODE(ip); + isforcealign = (whichfork == XFS_DATA_FORK) && + xfs_inode_has_forcealign(ip) && + xfs_inode_has_extsize(ip) && ip->i_extsize > 1; end = start + len; if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) { @@ -5459,11 +5472,15 @@ __xfs_bunmapi( if (del.br_startoff + del.br_blockcount > end + 1) del.br_blockcount = end + 1 - del.br_startoff; - if (!isrt || (flags & XFS_BMAPI_REMAP)) + if ((!isrt && !isforcealign) || (flags & XFS_BMAPI_REMAP)) goto delete; - mod = xfs_rtb_to_rtxoff(mp, - del.br_startblock + del.br_blockcount); + if (isrt) + mod = xfs_rtb_to_rtxoff(mp, + del.br_startblock + del.br_blockcount); + else if (isforcealign) + mod = xfs_forcealign_extent_offset(ip, + del.br_startblock + del.br_blockcount); if (mod) { /* * Realtime extent not lined up at the end. @@ -5511,9 +5528,19 @@ __xfs_bunmapi( goto nodelete; } - mod = xfs_rtb_to_rtxoff(mp, del.br_startblock); + if (isrt) + mod = xfs_rtb_to_rtxoff(mp, del.br_startblock); + else if (isforcealign) + mod = xfs_forcealign_extent_offset(ip, + del.br_startblock); + if (mod) { - xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; + xfs_extlen_t off; + + if (isrt) + off = mp->m_sb.sb_rextsize - mod; + else if (isforcealign) + off = ip->i_extsize - mod; /* * Realtime extent is lined up at the end but not diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 065028789473..3f13943ab3a3 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h @@ -316,6 +316,11 @@ static inline bool xfs_inode_has_forcealign(struct xfs_inode *ip) return ip->i_diflags2 & XFS_DIFLAG2_FORCEALIGN; } +static inline bool xfs_inode_has_extsize(struct xfs_inode *ip) +{ + return ip->i_diflags & XFS_DIFLAG_EXTSIZE; +} + /* * Return the buftarg used for data allocations on a given inode. */ -- 2.31.1