[Top] [All Lists]

[PATCH 3/4] xfs: allow collapse to handle delalloc extents

To: xfs@xxxxxxxxxxx
Subject: [PATCH 3/4] xfs: allow collapse to handle delalloc extents
From: Brian Foster <bfoster@xxxxxxxxxx>
Date: Fri, 29 Aug 2014 16:29:37 -0400
Delivered-to: xfs@xxxxxxxxxxx
In-reply-to: <1409344178-44817-1-git-send-email-bfoster@xxxxxxxxxx>
References: <1409344178-44817-1-git-send-email-bfoster@xxxxxxxxxx>
The xfs_bmap_shift_extents() mechanism currently requires any post-EOF
delalloc blocks to be explicitly trimmed before it can proceed to avoid
hitting delalloc extents during the extent shift sequence. This is
because the implementation doesn't account for delalloc extents and
expects consistency between the in-core extent list and what is on disk
for bmapbt mappings. E.g., it will attempt to look up delalloc extents
on disk and fail.

Since delayed allocation extents have not been written to disk, no
on-disk changes are required to shift such extents. Update
xfs_bmap_shift_extents() to check for delalloc extents. If found, simply
update the start offset of the record and move on. This should only
occur for delalloc blocks that do not have data (e.g., post-eof
preallocation). Such blocks are currently trimmed off by the truncate
that occurs after the extent shift, so we make no attempt to merge
delalloc extents.

This eliminates the need for an eofblocks trim prior to collapse.

Signed-off-by: Brian Foster <bfoster@xxxxxxxxxx>
 fs/xfs/libxfs/xfs_bmap.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 449a016..32598cb 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -5417,6 +5417,11 @@ xfs_bmap_shift_extents_can_merge(
        startoff = got->br_startoff - shift;
+       /* do not merge if either extent is delalloc */
+       if (isnullstartblock(left->br_startblock) ||
+           isnullstartblock(got->br_startblock))
+               return false;
         * The extent, once shifted, must be adjacent in-file and on-disk with
         * the preceding extent.
@@ -5554,6 +5559,7 @@ xfs_bmap_shift_extents(
        int                             whichfork = XFS_DATA_FORK;
        int                             logflags = 0;
        int                             total_extents;
+       bool                            delalloc;
        if (unlikely(XFS_TEST_ERROR(
            (XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_EXTENTS &&
@@ -5618,6 +5624,7 @@ xfs_bmap_shift_extents(
        total_extents = ifp->if_bytes / sizeof(xfs_bmbt_rec_t);
        while (nexts++ < num_exts && current_ext < total_extents) {
                startoff = got.br_startoff - offset_shift_fsb;
+               delalloc = isnullstartblock(got.br_startblock);
                /* grab the left extent and check for a potential merge */
                if (current_ext > 0) {
@@ -5649,9 +5656,14 @@ xfs_bmap_shift_extents(
                 * We didn't merge the extent so do the shift. Update the start
-                * offset in the in-core extent and btree, if necessary.
+                * offset in the in-core extent. If the extent is delalloc,
+                * there's nothing else to do. Otherwise, update the extent
+                * on-disk.
                xfs_bmbt_set_startoff(gotp, startoff);
+               if (delalloc)
+                       goto next;
                logflags |= XFS_ILOG_CORE;
                if (cur) {
                        error = xfs_bmbt_lookup_eq(cur, got.br_startoff,

<Prev in Thread] Current Thread [Next in Thread>