mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
xfs: Fix xfs_last_rt_bmblock()
Bug description: If the size of the last rtgroup i.e, the rtg passed to xfs_last_rt_bmblock() is such that the last rtextent falls in 0th word offset of a bmblock of the bitmap file tracking this (last) rtgroup, then in that case xfs_last_rt_bmblock() incorrectly returns the next bmblock number instead of the current/last used bmblock number. When xfs_last_rt_bmblock() incorrectly returns the next bmblock, the loop to grow/modify the bmblocks in xfs_growfs_rtg() doesn't execute and xfs_growfs basically does a nop in certain cases. xfs_growfs will do a nop when the new size of the fs will have the same number of rtgroups i.e, we are only growing the last rtgroup. Reproduce: $ mkfs.xfs -m metadir=0 -r rtdev=/dev/loop1 /dev/loop0 \ -r size=32769b -f $ mount -o rtdev=/dev/loop1 /dev/loop0 /mnt/scratch $ xfs_growfs -R $(( 32769 + 1 )) /mnt/scratch $ xfs_info /mnt/scratch | grep rtextents $ # We can see that rtextents hasn't changed Fix: Fix this by returning the current/last used bmblock when the last rtgroup size is not a multiple xfs_rtbitmap_rtx_per_rbmblock() and the next bmblock when the rtgroup size is a multiple of xfs_rtbitmap_rtx_per_rbmblock() i.e, the existing blocks are completely used up. Also, I have renamed xfs_last_rt_bmblock() to xfs_last_rt_bmblock_to_extend() to signify that this function returns the bmblock number to extend and NOT always the last used bmblock number. Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Nirjhar Roy (IBM) <nirjhar.roy.lists@gmail.com> Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
committed by
Carlos Maiolino
parent
115ea07b94
commit
8baa9bccc0
@@ -1082,17 +1082,27 @@ xfs_last_rtgroup_extents(
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the last rbmblock currently used.
|
||||
* This will return the bitmap block number (indexed at 0) that will be
|
||||
* extended/modified. There are 2 cases here:
|
||||
* 1. The size of the rtg is such that it is a multiple of
|
||||
* xfs_rtbitmap_rtx_per_rbmblock() i.e, an integral number of bitmap blocks
|
||||
* are completely filled up. In this case, we should return
|
||||
* 1 + (the last used bitmap block number).
|
||||
* 2. The size of the rtg is not an multiple of xfs_rtbitmap_rtx_per_rbmblock().
|
||||
* Here we will return the block number of last used block number. In this
|
||||
* case, we will modify the last used bitmap block to extend the size of the
|
||||
* rtgroup.
|
||||
*
|
||||
* This also deals with the case where there were no rtextents before.
|
||||
*/
|
||||
static xfs_fileoff_t
|
||||
xfs_last_rt_bmblock(
|
||||
xfs_last_rt_bmblock_to_extend(
|
||||
struct xfs_rtgroup *rtg)
|
||||
{
|
||||
struct xfs_mount *mp = rtg_mount(rtg);
|
||||
xfs_rgnumber_t rgno = rtg_rgno(rtg);
|
||||
xfs_fileoff_t bmbno = 0;
|
||||
unsigned int mod = 0;
|
||||
|
||||
ASSERT(!mp->m_sb.sb_rgcount || rgno >= mp->m_sb.sb_rgcount - 1);
|
||||
|
||||
@@ -1100,9 +1110,16 @@ xfs_last_rt_bmblock(
|
||||
xfs_rtxnum_t nrext = xfs_last_rtgroup_extents(mp);
|
||||
|
||||
/* Also fill up the previous block if not entirely full. */
|
||||
bmbno = xfs_rtbitmap_blockcount_len(mp, nrext);
|
||||
if (xfs_rtx_to_rbmword(mp, nrext) != 0)
|
||||
bmbno--;
|
||||
/* We are doing a -1 to convert it to a 0 based index */
|
||||
bmbno = xfs_rtbitmap_blockcount_len(mp, nrext) - 1;
|
||||
div_u64_rem(nrext, xfs_rtbitmap_rtx_per_rbmblock(mp), &mod);
|
||||
/*
|
||||
* mod = 0 means that all the current blocks are full. So
|
||||
* return the next block number to be used for the rtgroup
|
||||
* growth.
|
||||
*/
|
||||
if (mod == 0)
|
||||
bmbno++;
|
||||
}
|
||||
|
||||
return bmbno;
|
||||
@@ -1207,7 +1224,8 @@ xfs_growfs_rtg(
|
||||
goto out_rele;
|
||||
}
|
||||
|
||||
for (bmbno = xfs_last_rt_bmblock(rtg); bmbno < bmblocks; bmbno++) {
|
||||
for (bmbno = xfs_last_rt_bmblock_to_extend(rtg); bmbno < bmblocks;
|
||||
bmbno++) {
|
||||
error = xfs_growfs_rt_bmblock(rtg, nrblocks, rextsize, bmbno);
|
||||
if (error)
|
||||
goto out_error;
|
||||
|
||||
Reference in New Issue
Block a user