[PATCH for v5.15 2/2] btrfs: defrag: use the same cluster size for defrag ioctl and autodefrag

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Kernel]     [Kernel Development Newbies]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Hiking]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux