]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs: use realtime EFI to free extents when realtime rmap is enabled
authorDarrick J. Wong <djwong@kernel.org>
Tue, 7 Mar 2023 03:55:54 +0000 (19:55 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Wed, 22 Nov 2023 23:03:38 +0000 (15:03 -0800)
When rmap is enabled, XFS expects a certain order of operations, which
is: 1) remove the file mapping, 2) remove the reverse mapping, and then
3) free the blocks.  xfs_bmap_del_extent_real tries to do 1 and 3 in the
same transaction, which means that when rtrmap is enabled, we have to
use realtime EFIs to maintain the expected order.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
libxfs/xfs_bmap.c

index 0f365723774b80df43a0b496a9c1ae321e2af008..ea16dd3b6d51dbfde1f4ab75e11b9f6b2984bf82 100644 (file)
@@ -5051,7 +5051,6 @@ xfs_bmap_del_extent_real(
 {
        xfs_fsblock_t           del_endblock=0; /* first block past del */
        xfs_fileoff_t           del_endoff;     /* first offset past del */
-       int                     do_fx;  /* free extent at end of routine */
        int                     error;  /* error return value */
        int                     flags = 0;/* inode logging flags */
        struct xfs_bmbt_irec    got;    /* current extent entry */
@@ -5065,6 +5064,8 @@ xfs_bmap_del_extent_real(
        uint                    qfield; /* quota field to update */
        uint32_t                state = xfs_bmap_fork_to_state(whichfork);
        struct xfs_bmbt_irec    old;
+       bool                    isrt = xfs_ifork_is_realtime(ip, whichfork);
+       bool                    want_free = !(bflags & XFS_BMAPI_REMAP);
 
        mp = ip->i_mount;
        XFS_STATS_INC(mp, xs_del_exlist);
@@ -5095,18 +5096,24 @@ xfs_bmap_del_extent_real(
                return -ENOSPC;
 
        flags = XFS_ILOG_CORE;
-       if (xfs_ifork_is_realtime(ip, whichfork)) {
-               if (!(bflags & XFS_BMAPI_REMAP)) {
+       if (isrt) {
+               /*
+                * Historically, we did not use EFIs to free realtime extents.
+                * However, when reverse mapping is enabled, we must maintain
+                * the same order of operations as the data device, which is:
+                * Remove the file mapping, remove the reverse mapping, and
+                * then free the blocks.  This means that we must delay the
+                * freeing until after we've scheduled the rmap update.
+                */
+               if (want_free && !xfs_has_rtrmapbt(mp)) {
                        error = xfs_rtfree_blocks(tp, del->br_startblock,
                                        del->br_blockcount);
                        if (error)
                                goto done;
+                       want_free = false;
                }
-
-               do_fx = 0;
                qfield = XFS_TRANS_DQ_RTBCOUNT;
        } else {
-               do_fx = 1;
                qfield = XFS_TRANS_DQ_BCOUNT;
        }
        nblks = del->br_blockcount;
@@ -5261,7 +5268,7 @@ xfs_bmap_del_extent_real(
        /*
         * If we need to, add to list of extents to delete.
         */
-       if (do_fx && !(bflags & XFS_BMAPI_REMAP)) {
+       if (want_free) {
                if (xfs_is_reflink_inode(ip) && whichfork == XFS_DATA_FORK) {
                        xfs_refcount_decrease_extent(tp, del);
                } else {
@@ -5270,6 +5277,8 @@ xfs_bmap_del_extent_real(
                        if ((bflags & XFS_BMAPI_NODISCARD) ||
                            del->br_state == XFS_EXT_UNWRITTEN)
                                efi_flags |= XFS_FREE_EXTENT_SKIP_DISCARD;
+                       if (isrt)
+                               efi_flags |= XFS_FREE_EXTENT_REALTIME;
 
                        error = xfs_free_extent_later(tp, del->br_startblock,
                                        del->br_blockcount, NULL,