xfs: don't reserve per-AG space for an internal log
authorDarrick J. Wong <darrick.wong@oracle.com>
Mon, 20 May 2019 18:25:39 +0000 (11:25 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Mon, 20 May 2019 18:25:39 +0000 (11:25 -0700)
It turns out that the log can consume nearly all the space in an AG, and
when this happens this it's possible that there will be less free space
in the AG than the reservation would try to hide.  On a debug kernel
this can trigger an ASSERT in xfs/250:

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

The log is permanently allocated, so we know we're never going to have
to expand the btrees to hold any records associated with the log space.
We therefore can treat the space as if it doesn't exist.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Eric Sandeen <sandeen@redhat.com>
fs/xfs/libxfs/xfs_ialloc_btree.c
fs/xfs/libxfs/xfs_refcount_btree.c
fs/xfs/libxfs/xfs_rmap_btree.c

index 1080381ff243e68ee3b6c89fef1e2e78341d8994..bc2dfacd2f4a01c83864361862442ab63c4a73b2 100644 (file)
@@ -549,6 +549,15 @@ xfs_inobt_max_size(
        if (mp->m_inobt_mxr[0] == 0)
                return 0;
 
+       /*
+        * The log is permanently allocated, so the space it occupies will
+        * never be available for the kinds of things that would require btree
+        * expansion.  We therefore can pretend the space isn't there.
+        */
+       if (mp->m_sb.sb_logstart &&
+           XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno)
+               agblocks -= mp->m_sb.sb_logblocks;
+
        return xfs_btree_calc_size(mp->m_inobt_mnr,
                                (uint64_t)agblocks * mp->m_sb.sb_inopblock /
                                        XFS_INODES_PER_CHUNK);
index 6f47ab876d90f229713d2cc8b5c8fc54aee06c5b..5d9de9b217266cfa0d9b9e054047cbb146ad9250 100644 (file)
@@ -427,6 +427,15 @@ xfs_refcountbt_calc_reserves(
        tree_len = be32_to_cpu(agf->agf_refcount_blocks);
        xfs_trans_brelse(tp, agbp);
 
+       /*
+        * The log is permanently allocated, so the space it occupies will
+        * never be available for the kinds of things that would require btree
+        * expansion.  We therefore can pretend the space isn't there.
+        */
+       if (mp->m_sb.sb_logstart &&
+           XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno)
+               agblocks -= mp->m_sb.sb_logblocks;
+
        *ask += xfs_refcountbt_max_size(mp, agblocks);
        *used += tree_len;
 
index 5738e11055e6bbeaf9602b353555450b24908600..5d1f8884c8886eedc81bb54acd90c8445ad62826 100644 (file)
@@ -578,6 +578,15 @@ xfs_rmapbt_calc_reserves(
        tree_len = be32_to_cpu(agf->agf_rmap_blocks);
        xfs_trans_brelse(tp, agbp);
 
+       /*
+        * The log is permanently allocated, so the space it occupies will
+        * never be available for the kinds of things that would require btree
+        * expansion.  We therefore can pretend the space isn't there.
+        */
+       if (mp->m_sb.sb_logstart &&
+           XFS_FSB_TO_AGNO(mp, mp->m_sb.sb_logstart) == agno)
+               agblocks -= mp->m_sb.sb_logblocks;
+
        /* Reserve 1% of the AG or enough for 1 block per record. */
        *ask += max(agblocks / 100, xfs_rmapbt_max_size(mp, agblocks));
        *used += tree_len;