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, -- 1.8.3.1 _______________________________________________ xfs mailing list xfs@xxxxxxxxxxx http://oss.sgi.com/mailman/listinfo/xfs