summaryrefslogtreecommitdiff
path: root/fs/xfs/scrub/reap.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/scrub/reap.c')
-rw-r--r--fs/xfs/scrub/reap.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/fs/xfs/scrub/reap.c b/fs/xfs/scrub/reap.c
index 3da372bc6eaa..79d43b9448a3 100644
--- a/fs/xfs/scrub/reap.c
+++ b/fs/xfs/scrub/reap.c
@@ -20,6 +20,7 @@
#include "xfs_ialloc_btree.h"
#include "xfs_rmap.h"
#include "xfs_rmap_btree.h"
+#include "xfs_refcount.h"
#include "xfs_refcount_btree.h"
#include "xfs_extent_busy.h"
#include "xfs_ag.h"
@@ -313,6 +314,14 @@ xreap_agextent(
trace_xreap_dispose_unmap_extent(sc->sa.pag, agbno, *aglenp);
rs->force_roll = true;
+ if (rs->oinfo == &XFS_RMAP_OINFO_COW) {
+ /*
+ * If we're unmapping CoW staging extents, remove the
+ * records from the refcountbt as well.
+ */
+ xfs_refcount_free_cow_extent(sc->tp, fsbno, *aglenp);
+ return 0;
+ }
return xfs_rmap_free(sc->tp, sc->sa.agf_bp, sc->sa.pag, agbno,
*aglenp, rs->oinfo);
}
@@ -331,6 +340,22 @@ xreap_agextent(
return 0;
}
+ /*
+ * If we're getting rid of CoW staging extents, use deferred work items
+ * to remove the refcountbt records (which removes the rmap records)
+ * and free the extent. We're not worried about the system going down
+ * here because log recovery walks the refcount btree to clean out the
+ * CoW staging extents.
+ */
+ if (rs->oinfo == &XFS_RMAP_OINFO_COW) {
+ ASSERT(rs->resv == XFS_AG_RESV_NONE);
+
+ rs->force_roll = true;
+ xfs_refcount_free_cow_extent(sc->tp, fsbno, *aglenp);
+ __xfs_free_extent_later(sc->tp, fsbno, *aglenp, NULL, true);
+ return 0;
+ }
+
switch (rs->resv) {
case XFS_AG_RESV_AGFL:
ASSERT(*aglenp == 1);