No upstream commit. Since the bug only exists between v5.11 and v5.15. In v5.16 btrfs reworked defrag and no longer has this bug. [BUG] Since commit 7f458a3873ae ("btrfs: fix race when defragmenting leads to unnecessary IO") autodefrag no longer works with the following script: mkfs.btrfs -f $dev mount $dev $mnt -o datacow,autodefrag # Create a layout where we have fragmented extents at [0, 64k) (sync write in # reserve order), then a hole at [64k, 128k) xfs_io -f -s -c "pwrite 48k 16k" -c "pwrite 32k 16k" \ -c "pwrite 16k 16k" -c "pwrite 0 16k" \ $mnt/foobar truncate -s 128k $mnt/foobar echo "=== File extent layout before autodefrag ===" xfs_io -c "fiemap -v" "$mnt/foobar" # Now trigger autodefrag, autodefrag is triggered in the cleaner thread, # which will be woken up by commit thread mount -o remount,commit=1 $mnt sleep 3 sync echo "=== File extent layout after autodefrag ===" xfs_io -c "fiemap -v" "$mnt/foobar" The file "foobar" will not be autodefraged even it should. [CAUSE] Commit 7f458a3873ae ("btrfs: fix race when defragmenting leads to unnecessary IO") fixes the race by rejecting the cluster if there is any hole in the cluster. But unlike regular defrag ioctl, autodefrag ignores the @defrag_end parameter, and always uses a fixed cluster size 256K. While defrag ioctl uses @defrag_end to skip existing holes. This hidden autodefrag only behavior prevents autodefrag from working in above script. [FIX] Remove the special cluster size, and unify the behavior for both autodefrag and defrag ioctl. This fix is only needed for v5.15 (and maybe v5.10) stable branch, as in v5.16 the whole defrag get reworked in btrfs, which at least solves this particular bug. (although introduced quite some other regressions) CC: stable@xxxxxxxxxxxxxxx # 5.15 Signed-off-by: Qu Wenruo <wqu@xxxxxxxx> --- fs/btrfs/ioctl.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index 38a1b68c7851..61f6e77698a2 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c @@ -1521,13 +1521,8 @@ int btrfs_defrag_file(struct inode *inode, struct file *file, continue; } - if (!newer_than) { - cluster = (PAGE_ALIGN(defrag_end) >> - PAGE_SHIFT) - i; - cluster = min(cluster, max_cluster); - } else { - cluster = max_cluster; - } + cluster = (PAGE_ALIGN(defrag_end) >> PAGE_SHIFT) - i; + cluster = min(cluster, max_cluster); if (i + cluster > ra_index) { ra_index = max(i, ra_index); -- 2.35.1