]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: finobt AG reserves don't consider last AG can be a runt
authorDave Chinner <dchinner@redhat.com>
Sat, 24 Nov 2018 18:56:09 +0000 (12:56 -0600)
committerEric Sandeen <sandeen@redhat.com>
Sat, 24 Nov 2018 18:56:09 +0000 (12:56 -0600)
Source kernel commit: c08768977b9a65cab9bcfd1ba30ffb686b2b7c69

The last AG may be very small comapred to all other AGs, and hence
AG reservations based on the superblock AG size may actually consume
more space than the AG actually has. This results on assert failures
like:

XFS: Assertion failed: xfs_perag_resv(pag, XFS_AG_RESV_METADATA)->ar_reserved + xfs_perag_resv(pag, XFS_AG_RESV_RMAPBT)->ar_reserved <= pag->pagf_freeblks + pag->pagf_flcount, file: fs/xfs/libxfs/xfs_ag_resv.c, line: 319
[   48.932891]  xfs_ag_resv_init+0x1bd/0x1d0
[   48.933853]  xfs_fs_reserve_ag_blocks+0x37/0xb0
[   48.934939]  xfs_mountfs+0x5b3/0x920
[   48.935804]  xfs_fs_fill_super+0x462/0x640
[   48.936784]  ? xfs_test_remount_options+0x60/0x60
[   48.937908]  mount_bdev+0x178/0x1b0
[   48.938751]  mount_fs+0x36/0x170
[   48.939533]  vfs_kern_mount.part.43+0x54/0x130
[   48.940596]  do_mount+0x20e/0xcb0
[   48.941396]  ? memdup_user+0x3e/0x70
[   48.942249]  ksys_mount+0xba/0xd0
[   48.943046]  __x64_sys_mount+0x21/0x30
[   48.943953]  do_syscall_64+0x54/0x170
[   48.944835]  entry_SYSCALL_64_after_hwframe+0x49/0xbe

Hence we need to ensure the finobt per-ag space reservations take
into account the size of the last AG rather than treat it like all
the other full size AGs.

Note that both refcountbt and rmapbt already take the size of the AG
into account via reading the AGF length directly.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_ialloc_btree.c

index 6c7769ee8e6576277b35f5100437177879fd83b5..5e0ef91e28a6dfbcefd22a1d4ddb5ab808698c25 100644 (file)
@@ -537,15 +537,18 @@ xfs_inobt_rec_check_count(
 
 static xfs_extlen_t
 xfs_inobt_max_size(
-       struct xfs_mount        *mp)
+       struct xfs_mount        *mp,
+       xfs_agnumber_t          agno)
 {
+       xfs_agblock_t           agblocks = xfs_ag_block_count(mp, agno);
+
        /* Bail out if we're uninitialized, which can happen in mkfs. */
        if (mp->m_inobt_mxr[0] == 0)
                return 0;
 
        return xfs_btree_calc_size(mp->m_inobt_mnr,
-               (uint64_t)mp->m_sb.sb_agblocks * mp->m_sb.sb_inopblock /
-                               XFS_INODES_PER_CHUNK);
+                               (uint64_t)agblocks * mp->m_sb.sb_inopblock /
+                                       XFS_INODES_PER_CHUNK);
 }
 
 static int
@@ -593,7 +596,7 @@ xfs_finobt_calc_reserves(
        if (error)
                return error;
 
-       *ask += xfs_inobt_max_size(mp);
+       *ask += xfs_inobt_max_size(mp, agno);
        *used += tree_len;
        return 0;
 }