|  | #! /bin/bash | 
|  | # SPDX-License-Identifier: GPL-2.0 | 
|  | # Copyright (C) 2022 SUSE Linux Products GmbH. All Rights Reserved. | 
|  | # | 
|  | # FS QA Test 258 | 
|  | # | 
|  | # Make sure btrfs auto defrag can properly defrag clusters which has hole | 
|  | # in the middle | 
|  | # | 
|  | . ./common/preamble | 
|  | _begin_fstest auto defrag quick fiemap remount | 
|  |  | 
|  | . ./common/filter | 
|  |  | 
|  | _require_scratch | 
|  | _require_xfs_io_command "fiemap" | 
|  |  | 
|  | # Needs 4K sectorsize, as larger sectorsize can change the file layout. | 
|  | _require_btrfs_support_sectorsize 4096 | 
|  |  | 
|  | _scratch_mkfs >> $seqres.full | 
|  |  | 
|  | # Need datacow to show which range is defragged, and we're testing | 
|  | # autodefrag | 
|  | _scratch_mount -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_PROG -f -s -c "pwrite 48k 16k" -c "pwrite 32k 16k" \ | 
|  | -c "pwrite 16k 16k" -c "pwrite 0 16k" \ | 
|  | $SCRATCH_MNT/foobar >> $seqres.full | 
|  | truncate -s 128k $SCRATCH_MNT/foobar | 
|  |  | 
|  | old_csum=$(_md5_checksum $SCRATCH_MNT/foobar) | 
|  | echo "=== File extent layout before autodefrag ===" >> $seqres.full | 
|  | $XFS_IO_PROG -c "fiemap -v" "$SCRATCH_MNT/foobar" >> $seqres.full | 
|  | echo "old md5=$old_csum" >> $seqres.full | 
|  |  | 
|  | old_regular=$(_get_file_extent_sector "$SCRATCH_MNT/foobar" 0) | 
|  | old_hole=$(_get_file_extent_sector "$SCRATCH_MNT/foobar" 64k) | 
|  |  | 
|  | # Now trigger autodefrag, autodefrag is triggered in the cleaner thread, | 
|  | # which will be woken up by commit thread | 
|  | _scratch_remount commit=1 | 
|  | sleep 3 | 
|  | sync | 
|  |  | 
|  | new_csum=$(_md5_checksum $SCRATCH_MNT/foobar) | 
|  | new_regular=$(_get_file_extent_sector "$SCRATCH_MNT/foobar" 0) | 
|  | new_hole=$(_get_file_extent_sector "$SCRATCH_MNT/foobar" 64k) | 
|  |  | 
|  | echo "=== File extent layout after autodefrag ===" >> $seqres.full | 
|  | $XFS_IO_PROG -c "fiemap -v" "$SCRATCH_MNT/foobar" >> $seqres.full | 
|  | echo "new md5=$new_csum" >> $seqres.full | 
|  |  | 
|  | # In v5.11~v5.15 kernels, regular extents won't get defragged, and would trigger | 
|  | # the following output | 
|  | if [ $new_regular == $old_regular ]; then | 
|  | echo "regular extents didn't get defragged" | 
|  | fi | 
|  |  | 
|  | # In v5.10 and earlier kernel, autodefrag may choose to defrag holes, | 
|  | # which should be avoided. | 
|  | if [ "$new_hole" != "$old_hole" ]; then | 
|  | echo "hole extents got defragged" | 
|  | fi | 
|  |  | 
|  | # Defrag should not change file content | 
|  | if [ "$new_csum" != "$old_csum" ]; then | 
|  | echo "file content changed" | 
|  | fi | 
|  |  | 
|  | echo "Silence is golden" | 
|  | # success, all done | 
|  | status=0 | 
|  | exit |