OSDN Git Service

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 1080381..bc2dfac 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 6f47ab8..5d9de9b 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 5738e11..5d1f888 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;