xfs: store rmapbt block count in the AGF
[cascardo/linux.git] / fs / xfs / libxfs / xfs_alloc.c
index 73ab1ea..af1a72e 100644 (file)
@@ -2090,9 +2090,21 @@ xfs_alloc_fix_freelist(
         * anything other than extra overhead when we need to put more blocks
         * back on the free list? Maybe we should only do this when space is
         * getting low or the AGFL is more than half full?
+        *
+        * The NOSHRINK flag prevents the AGFL from being shrunk if it's too
+        * big; the NORMAP flag prevents AGFL expand/shrink operations from
+        * updating the rmapbt.  Both flags are used in xfs_repair while we're
+        * rebuilding the rmapbt, and neither are used by the kernel.  They're
+        * both required to ensure that rmaps are correctly recorded for the
+        * regenerated AGFL, bnobt, and cntbt.  See repair/phase5.c and
+        * repair/rmap.c in xfsprogs for details.
         */
-       xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
-       while (pag->pagf_flcount > need) {
+       memset(&targs, 0, sizeof(targs));
+       if (flags & XFS_ALLOC_FLAG_NORMAP)
+               xfs_rmap_skip_owner_update(&targs.oinfo);
+       else
+               xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
+       while (!(flags & XFS_ALLOC_FLAG_NOSHRINK) && pag->pagf_flcount > need) {
                struct xfs_buf  *bp;
 
                error = xfs_alloc_get_freelist(tp, agbp, &bno, 0);
@@ -2106,10 +2118,8 @@ xfs_alloc_fix_freelist(
                xfs_trans_binval(tp, bp);
        }
 
-       memset(&targs, 0, sizeof(targs));
        targs.tp = tp;
        targs.mp = mp;
-       xfs_rmap_ag_owner(&targs.oinfo, XFS_RMAP_OWN_AG);
        targs.agbp = agbp;
        targs.agno = args->agno;
        targs.alignment = targs.minlen = targs.prod = targs.isfl = 1;
@@ -2254,6 +2264,7 @@ xfs_alloc_log_agf(
                offsetof(xfs_agf_t, agf_longest),
                offsetof(xfs_agf_t, agf_btreeblks),
                offsetof(xfs_agf_t, agf_uuid),
+               offsetof(xfs_agf_t, agf_rmap_blocks),
                sizeof(xfs_agf_t)
        };
 
@@ -2809,8 +2820,6 @@ xfs_free_extent(
 
        ASSERT(len != 0);
 
-       trace_xfs_bmap_free_deferred(mp, agno, 0, agbno, len);
-
        if (XFS_TEST_ERROR(false, mp,
                        XFS_ERRTAG_FREE_EXTENT,
                        XFS_RANDOM_FREE_EXTENT))