Skip to content

Commit 8baa9bc

Browse files
Nirjhar-Roy-0211cmaiolino
authored andcommitted
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>
1 parent 115ea07 commit 8baa9bc

1 file changed

Lines changed: 24 additions & 6 deletions

File tree

fs/xfs/xfs_rtalloc.c

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,27 +1082,44 @@ xfs_last_rtgroup_extents(
10821082
}
10831083

10841084
/*
1085-
* Calculate the last rbmblock currently used.
1085+
* This will return the bitmap block number (indexed at 0) that will be
1086+
* extended/modified. There are 2 cases here:
1087+
* 1. The size of the rtg is such that it is a multiple of
1088+
* xfs_rtbitmap_rtx_per_rbmblock() i.e, an integral number of bitmap blocks
1089+
* are completely filled up. In this case, we should return
1090+
* 1 + (the last used bitmap block number).
1091+
* 2. The size of the rtg is not an multiple of xfs_rtbitmap_rtx_per_rbmblock().
1092+
* Here we will return the block number of last used block number. In this
1093+
* case, we will modify the last used bitmap block to extend the size of the
1094+
* rtgroup.
10861095
*
10871096
* This also deals with the case where there were no rtextents before.
10881097
*/
10891098
static xfs_fileoff_t
1090-
xfs_last_rt_bmblock(
1099+
xfs_last_rt_bmblock_to_extend(
10911100
struct xfs_rtgroup *rtg)
10921101
{
10931102
struct xfs_mount *mp = rtg_mount(rtg);
10941103
xfs_rgnumber_t rgno = rtg_rgno(rtg);
10951104
xfs_fileoff_t bmbno = 0;
1105+
unsigned int mod = 0;
10961106

10971107
ASSERT(!mp->m_sb.sb_rgcount || rgno >= mp->m_sb.sb_rgcount - 1);
10981108

10991109
if (mp->m_sb.sb_rgcount && rgno == mp->m_sb.sb_rgcount - 1) {
11001110
xfs_rtxnum_t nrext = xfs_last_rtgroup_extents(mp);
11011111

11021112
/* Also fill up the previous block if not entirely full. */
1103-
bmbno = xfs_rtbitmap_blockcount_len(mp, nrext);
1104-
if (xfs_rtx_to_rbmword(mp, nrext) != 0)
1105-
bmbno--;
1113+
/* We are doing a -1 to convert it to a 0 based index */
1114+
bmbno = xfs_rtbitmap_blockcount_len(mp, nrext) - 1;
1115+
div_u64_rem(nrext, xfs_rtbitmap_rtx_per_rbmblock(mp), &mod);
1116+
/*
1117+
* mod = 0 means that all the current blocks are full. So
1118+
* return the next block number to be used for the rtgroup
1119+
* growth.
1120+
*/
1121+
if (mod == 0)
1122+
bmbno++;
11061123
}
11071124

11081125
return bmbno;
@@ -1207,7 +1224,8 @@ xfs_growfs_rtg(
12071224
goto out_rele;
12081225
}
12091226

1210-
for (bmbno = xfs_last_rt_bmblock(rtg); bmbno < bmblocks; bmbno++) {
1227+
for (bmbno = xfs_last_rt_bmblock_to_extend(rtg); bmbno < bmblocks;
1228+
bmbno++) {
12111229
error = xfs_growfs_rt_bmblock(rtg, nrblocks, rextsize, bmbno);
12121230
if (error)
12131231
goto out_error;

0 commit comments

Comments
 (0)