#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2017 Roman Penyaev. All Rights Reserved. # # FS QA Test 404 # # Regression test which targets two nasty ext4 bugs in a logic which # shifts extents: # # 1) 14d981f468a1 ("ext4: Include forgotten start block on fallocate insert range") # # An incorrect right shift (insert range) for the first extent in # a range. # # Test tries to insert many blocks at the same offset to reproduce # the following layout: # # block #0 block #1 # |ext0 ext1|ext2 ext3 ...| # ^ # insert of a new block # # Because of an incorrect range first block is never reached, # thus ext1 is untouched, resulting to a hole at a wrong offset: # # What we got: # # block #0 block #1 # |ext0 ext1| ext2 ext3 ...| # ^ # hole at a wrong offset # # What we expect: # # block #0 block #1 # |ext0 ext1|ext2 ext3 ...| # ^ # hole at a correct offset # # 2) 2b3864b32403 ("ext4: do not polute the extents cache while shifting extents") # # Extents status tree is filled in with outdated offsets while doing # extents shift, that leads to wrong data blocks. That is why test # writes unique block content and checks md5sum of a result file after # each block insert. # . ./common/preamble _begin_fstest auto quick insert testfile=$TEST_DIR/$seq.file pattern=$tmp.pattern # Override the default cleanup function. _cleanup() { cd / rm -f $tmp.* rm -f $testfile } # Import common functions. . ./common/filter # real QA test starts here # Modify as appropriate. _supported_fs generic _require_test _require_xfs_io_command "falloc" _require_xfs_io_command "finsert" blksize=`_get_block_size $TEST_DIR` # Generate a block with a repeating number represented as 4 bytes decimal. # The test generates unique pattern for each block in order to observe a # wrong order if any. function generate_pattern() { blkind=$1 printf "%04d" $blkind | awk '{ while (c++ < '$(($blksize/4))') \ printf "%s", $0 }' > $pattern } $XFS_IO_PROG -f -c "falloc 0 $(($blksize * 2))" $testfile \ >> $seqres.full 2>&1 # First block, has 0001 as a pattern generate_pattern 1 $XFS_IO_PROG -c "pwrite -i $pattern 0 $blksize" $testfile \ >> $seqres.full 2>&1 # Second block, has 0002 as a pattern generate_pattern 2 $XFS_IO_PROG -c "pwrite -i $pattern $blksize $blksize" $testfile \ >> $seqres.full 2>&1 # Insert 498 blocks after the first block. We use this quite big # number to increase the reproduction probability. for (( block=3; block<=500; block++ )); do $XFS_IO_PROG -c "finsert $blksize $blksize" $testfile \ >> $seqres.full 2>&1 generate_pattern $block $XFS_IO_PROG -c "pwrite -i $pattern $blksize $blksize" $testfile \ >> $seqres.full 2>&1 # Avoid offsets in hexdump output, because block size can vary. # Here we check md5 after each insert to be sure that zero blocks # do not appear, targets this commit: # 14d981f468a1 ("ext4: Include forgotten start block on fallocate insert range") # or blocks are in correct order, this commit: # 2b3864b32403 ("ext4: do not polute the extents cache while shifting extents") # md5=`hexdump -e '16/1 "%_p" "\n"' $testfile | md5sum` printf "#%d %s\n" "$block" "$md5" done # Eventually output file has 500 blocks in the following order: # 0001 0500 0499 0498 ... 0002 # success, all done status=0 exit