]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs: don't reserve per-AG space for an internal log
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 24 Jul 2019 19:54:07 +0000 (15:54 -0400)
committerEric Sandeen <sandeen@redhat.com>
Wed, 24 Jul 2019 19:54:07 +0000 (15:54 -0400)
Source kernel commit: 5cd213b0fec640a46adc5e6e4dfc7763aa54b3b2

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>
Signed-off-by: Eric Sandeen <sandeen@sandeen.net>
libxfs/xfs_ialloc_btree.c
libxfs/xfs_refcount_btree.c
libxfs/xfs_rmap_btree.c

index 599c79da51cbe31b2de8baa4c5506273d6424bf1..ea1f068c8938e804f21c6b3a4d120da06630f7e0 100644 (file)
@@ -548,6 +548,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 65018b12a2dfc8a69d26cf3bc4176c5e28e85f02..0d8d5c22329808f240cd791a96ec49b10d9a2cc0 100644 (file)
@@ -426,6 +426,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 59abe4136824d0f5098ad48a8fc1d1ac735efb52..36860e71150e4d2df3edc8ca9812c8e0292b8f4a 100644 (file)
@@ -576,6 +576,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;