Message ID | 20240621100540.2976618-11-john.g.garry@oracle.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | forcealign for xfs | expand |
On Fri, Jun 21, 2024 at 10:05:37AM +0000, John Garry wrote: > 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@oracle.com> > --- > fs/xfs/libxfs/xfs_bmap.c | 38 +++++++++++++++++++++++++++++++++----- > 1 file changed, 33 insertions(+), 5 deletions(-) > > diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c > index c9cf138e13c4..ebeb2969b289 100644 > --- a/fs/xfs/libxfs/xfs_bmap.c > +++ b/fs/xfs/libxfs/xfs_bmap.c > @@ -5380,6 +5380,25 @@ xfs_bmap_del_extent_real( > return 0; > } > > +static xfs_extlen_t > +xfs_bunmapi_align( > + struct xfs_inode *ip, > + xfs_fsblock_t bno) > +{ > + struct xfs_mount *mp = ip->i_mount; > + xfs_agblock_t agbno; > + > + if (xfs_inode_has_forcealign(ip)) { > + if (is_power_of_2(ip->i_extsize)) > + return bno & (ip->i_extsize - 1); > + > + agbno = XFS_FSB_TO_AGBNO(mp, bno); > + return do_div(agbno, ip->i_extsize); Huh. The inode verifier allows realtime forcealign files, but this code will not handle that properly. Either don't allow realtime files, or make this handle them correctly: if (XFS_IS_REALTIME_INODE(ip)) { if (xfs_inode_has_forcealign(ip)) return offset_in_block(bno, ip->i_extsize); return xfs_rtb_to_rtxoff(ip->i_mount, bno); } else if (xfs_inode_has_forcealign(ip)) { xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); return offset_in_block(agbno, ip->i_extsize); } return 1; /* or assert, or whatever */ > + } > + ASSERT(XFS_IS_REALTIME_INODE(ip)); > + return xfs_rtb_to_rtxoff(ip->i_mount, bno); > +} > + > /* > * Unmap (remove) blocks from a file. > * If nexts is nonzero then the number of extents to remove is limited to > @@ -5402,6 +5421,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 inode with forcealign */ > int logflags; /* transaction logging flags */ > xfs_extlen_t mod; /* rt extent offset */ > struct xfs_mount *mp = ip->i_mount; > @@ -5439,6 +5459,8 @@ __xfs_bunmapi( > } > XFS_STATS_INC(mp, xs_blk_unmap); > isrt = xfs_ifork_is_realtime(ip, whichfork); > + isforcealign = (whichfork != XFS_ATTR_FORK) && > + xfs_inode_has_forcealign(ip); > end = start + len; > > if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) { > @@ -5490,11 +5512,10 @@ __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); > + mod = xfs_bunmapi_align(ip, del.br_startblock + del.br_blockcount); > if (mod) { > /* > * Realtime extent not lined up at the end. "Not aligned to allocation unit on the end." ? > @@ -5542,9 +5563,16 @@ __xfs_bunmapi( > goto nodelete; > } > > - mod = xfs_rtb_to_rtxoff(mp, del.br_startblock); > + mod = xfs_bunmapi_align(ip, del.br_startblock); > if (mod) { > - xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; > + xfs_extlen_t off; > + > + if (isforcealign) { > + off = ip->i_extsize - mod; > + } else { > + ASSERT(isrt); > + off = mp->m_sb.sb_rextsize - mod; > + } > > /* > * Realtime extent is lined up at the end but not Same here -- now this code is handling more than just rt extents. --D > -- > 2.31.1 > >
On 21/06/2024 20:12, Darrick J. Wong wrote: > On Fri, Jun 21, 2024 at 10:05:37AM +0000, John Garry wrote: >> 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@oracle.com> >> --- >> fs/xfs/libxfs/xfs_bmap.c | 38 +++++++++++++++++++++++++++++++++----- >> 1 file changed, 33 insertions(+), 5 deletions(-) >> >> diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c >> index c9cf138e13c4..ebeb2969b289 100644 >> --- a/fs/xfs/libxfs/xfs_bmap.c >> +++ b/fs/xfs/libxfs/xfs_bmap.c >> @@ -5380,6 +5380,25 @@ xfs_bmap_del_extent_real( >> return 0; >> } >> >> +static xfs_extlen_t >> +xfs_bunmapi_align( >> + struct xfs_inode *ip, >> + xfs_fsblock_t bno) >> +{ >> + struct xfs_mount *mp = ip->i_mount; >> + xfs_agblock_t agbno; >> + >> + if (xfs_inode_has_forcealign(ip)) { >> + if (is_power_of_2(ip->i_extsize)) >> + return bno & (ip->i_extsize - 1); >> + >> + agbno = XFS_FSB_TO_AGBNO(mp, bno); >> + return do_div(agbno, ip->i_extsize); > > Huh. The inode verifier allows realtime forcealign files, but this code > will not handle that properly. Either don't allow realtime files, or > make this handle them correctly: ok, so XFS_FSB_TO_AGBNO() is not always suitable > > if (XFS_IS_REALTIME_INODE(ip)) { > if (xfs_inode_has_forcealign(ip)) > return offset_in_block(bno, ip->i_extsize); > return xfs_rtb_to_rtxoff(ip->i_mount, bno); > } else if (xfs_inode_has_forcealign(ip)) { > xfs_agblock_t agbno = XFS_FSB_TO_AGBNO(mp, bno); > > return offset_in_block(agbno, ip->i_extsize); > } > > return 1; /* or assert, or whatever */ > >> + } >> + ASSERT(XFS_IS_REALTIME_INODE(ip)); >> + return xfs_rtb_to_rtxoff(ip->i_mount, bno); >> +} >> + >> /* >> * Unmap (remove) blocks from a file. >> * If nexts is nonzero then the number of extents to remove is limited to >> @@ -5402,6 +5421,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 inode with forcealign */ >> int logflags; /* transaction logging flags */ >> xfs_extlen_t mod; /* rt extent offset */ >> struct xfs_mount *mp = ip->i_mount; >> @@ -5439,6 +5459,8 @@ __xfs_bunmapi( >> } >> XFS_STATS_INC(mp, xs_blk_unmap); >> isrt = xfs_ifork_is_realtime(ip, whichfork); >> + isforcealign = (whichfork != XFS_ATTR_FORK) && >> + xfs_inode_has_forcealign(ip); >> end = start + len; >> >> if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) { >> @@ -5490,11 +5512,10 @@ __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); >> + mod = xfs_bunmapi_align(ip, del.br_startblock + del.br_blockcount); >> if (mod) { >> /* >> * Realtime extent not lined up at the end. > > "Not aligned to allocation unit on the end." ? ok > >> @@ -5542,9 +5563,16 @@ __xfs_bunmapi( >> goto nodelete; >> } >> >> - mod = xfs_rtb_to_rtxoff(mp, del.br_startblock); >> + mod = xfs_bunmapi_align(ip, del.br_startblock); >> if (mod) { >> - xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; >> + xfs_extlen_t off; >> + >> + if (isforcealign) { >> + off = ip->i_extsize - mod; >> + } else { >> + ASSERT(isrt); >> + off = mp->m_sb.sb_rextsize - mod; >> + } >> >> /* >> * Realtime extent is lined up at the end but not > > Same here -- now this code is handling more than just rt extents. > ok Thanks!
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c index c9cf138e13c4..ebeb2969b289 100644 --- a/fs/xfs/libxfs/xfs_bmap.c +++ b/fs/xfs/libxfs/xfs_bmap.c @@ -5380,6 +5380,25 @@ xfs_bmap_del_extent_real( return 0; } +static xfs_extlen_t +xfs_bunmapi_align( + struct xfs_inode *ip, + xfs_fsblock_t bno) +{ + struct xfs_mount *mp = ip->i_mount; + xfs_agblock_t agbno; + + if (xfs_inode_has_forcealign(ip)) { + if (is_power_of_2(ip->i_extsize)) + return bno & (ip->i_extsize - 1); + + agbno = XFS_FSB_TO_AGBNO(mp, bno); + return do_div(agbno, ip->i_extsize); + } + ASSERT(XFS_IS_REALTIME_INODE(ip)); + return xfs_rtb_to_rtxoff(ip->i_mount, bno); +} + /* * Unmap (remove) blocks from a file. * If nexts is nonzero then the number of extents to remove is limited to @@ -5402,6 +5421,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 inode with forcealign */ int logflags; /* transaction logging flags */ xfs_extlen_t mod; /* rt extent offset */ struct xfs_mount *mp = ip->i_mount; @@ -5439,6 +5459,8 @@ __xfs_bunmapi( } XFS_STATS_INC(mp, xs_blk_unmap); isrt = xfs_ifork_is_realtime(ip, whichfork); + isforcealign = (whichfork != XFS_ATTR_FORK) && + xfs_inode_has_forcealign(ip); end = start + len; if (!xfs_iext_lookup_extent_before(ip, ifp, &end, &icur, &got)) { @@ -5490,11 +5512,10 @@ __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); + mod = xfs_bunmapi_align(ip, del.br_startblock + del.br_blockcount); if (mod) { /* * Realtime extent not lined up at the end. @@ -5542,9 +5563,16 @@ __xfs_bunmapi( goto nodelete; } - mod = xfs_rtb_to_rtxoff(mp, del.br_startblock); + mod = xfs_bunmapi_align(ip, del.br_startblock); if (mod) { - xfs_extlen_t off = mp->m_sb.sb_rextsize - mod; + xfs_extlen_t off; + + if (isforcealign) { + off = ip->i_extsize - mod; + } else { + ASSERT(isrt); + off = mp->m_sb.sb_rextsize - mod; + } /* * Realtime extent is lined up at the end but not
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@oracle.com> --- fs/xfs/libxfs/xfs_bmap.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-)