Skip to content

Commit a95ff94

Browse files
committed
Merge: xfs: fix sparse inode limits on runt AG
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/5846 JIRA: https://issues.redhat.com/browse/RHEL-68541 Upstream Status: https://git.kernel.org/pub/scm/fs/xfs/xfs-linux.git for-next Conflicts: changed context due to unbackported upstream commit 6abd82a xfs: add a xfs_agino_to_ino helper e9c4d8b xfs: factor out a generic xfs_group structure The runt AG at the end of a filesystem is almost always smaller than the mp->m_sb.sb_agblocks. Unfortunately, when setting the max_agbno limit for the inode chunk allocation, we do not take this into account. This means we can allocate a sparse inode chunk that overlaps beyond the end of an AG. When we go to allocate an inode from that sparse chunk, the irec fails validation because the agbno of the start of the irec is beyond valid limits for the runt AG. Prevent this from happening by taking into account the size of the runt AG when allocating inode chunks. Also convert the various checks for valid inode chunk agbnos to use xfs_ag_block_count() so that they will also catch such issues in the future. Fixes: 56d1115 ("xfs: allocate sparse inode chunks on full chunk allocation failure") Signed-off-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Pavel Reichl <preichl@redhat.com> Approved-by: Carlos Maiolino <cmaiolino@redhat.com> Approved-by: Bill O'Donnell <bodonnel@redhat.com> Approved-by: Ian Kent <ikent@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Rado Vrbovsky <rvrbovsk@redhat.com>
2 parents 971e66d + 660de44 commit a95ff94

File tree

1 file changed

+9
-7
lines changed

1 file changed

+9
-7
lines changed

fs/xfs/libxfs/xfs_ialloc.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -796,7 +796,8 @@ xfs_ialloc_ag_alloc(
796796
* the end of the AG.
797797
*/
798798
args.min_agbno = args.mp->m_sb.sb_inoalignmt;
799-
args.max_agbno = round_down(args.mp->m_sb.sb_agblocks,
799+
args.max_agbno = round_down(xfs_ag_block_count(args.mp,
800+
pag->pag_agno),
800801
args.mp->m_sb.sb_inoalignmt) -
801802
igeo->ialloc_blks;
802803

@@ -2190,9 +2191,9 @@ xfs_difree(
21902191
return -EINVAL;
21912192
}
21922193
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
2193-
if (agbno >= mp->m_sb.sb_agblocks) {
2194-
xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
2195-
__func__, agbno, mp->m_sb.sb_agblocks);
2194+
if (agbno >= xfs_ag_block_count(mp, pag->pag_agno)) {
2195+
xfs_warn(mp, "%s: agbno >= xfs_ag_block_count (%d >= %d).",
2196+
__func__, agbno, xfs_ag_block_count(mp, pag->pag_agno));
21962197
ASSERT(0);
21972198
return -EINVAL;
21982199
}
@@ -2315,7 +2316,7 @@ xfs_imap(
23152316
*/
23162317
agino = XFS_INO_TO_AGINO(mp, ino);
23172318
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
2318-
if (agbno >= mp->m_sb.sb_agblocks ||
2319+
if (agbno >= xfs_ag_block_count(mp, pag->pag_agno) ||
23192320
ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
23202321
error = -EINVAL;
23212322
#ifdef DEBUG
@@ -2325,11 +2326,12 @@ xfs_imap(
23252326
*/
23262327
if (flags & XFS_IGET_UNTRUSTED)
23272328
return error;
2328-
if (agbno >= mp->m_sb.sb_agblocks) {
2329+
if (agbno >= xfs_ag_block_count(mp, pag->pag_agno)) {
23292330
xfs_alert(mp,
23302331
"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
23312332
__func__, (unsigned long long)agbno,
2332-
(unsigned long)mp->m_sb.sb_agblocks);
2333+
(unsigned long)xfs_ag_block_count(mp,
2334+
pag->pag_agno));
23332335
}
23342336
if (ino != XFS_AGINO_TO_INO(mp, pag->pag_agno, agino)) {
23352337
xfs_alert(mp,

0 commit comments

Comments
 (0)