| #! /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=`od -An -c $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 |