mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
147 lines
4.2 KiB
Bash
147 lines
4.2 KiB
Bash
|
|
#! /bin/bash
|
||
|
|
# 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.
|
||
|
|
#
|
||
|
|
#-----------------------------------------------------------------------
|
||
|
|
# Copyright (c) 2017 Roman Penyaev. All Rights Reserved.
|
||
|
|
#
|
||
|
|
# This program is free software; you can redistribute it and/or
|
||
|
|
# modify it under the terms of the GNU General Public License as
|
||
|
|
# published by the Free Software Foundation.
|
||
|
|
#
|
||
|
|
# This program is distributed in the hope that it would be useful,
|
||
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
|
# GNU General Public License for more details.
|
||
|
|
#
|
||
|
|
# You should have received a copy of the GNU General Public License
|
||
|
|
# along with this program; if not, write the Free Software Foundation,
|
||
|
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||
|
|
#-----------------------------------------------------------------------
|
||
|
|
#
|
||
|
|
|
||
|
|
seq=`basename $0`
|
||
|
|
seqres=$RESULT_DIR/$seq
|
||
|
|
echo "QA output created by $seq"
|
||
|
|
|
||
|
|
here=`pwd`
|
||
|
|
tmp=/tmp/$$
|
||
|
|
status=1 # failure is the default!
|
||
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
||
|
|
|
||
|
|
testfile=$TEST_DIR/$seq.file
|
||
|
|
pattern=$tmp.pattern
|
||
|
|
|
||
|
|
_cleanup()
|
||
|
|
{
|
||
|
|
cd /
|
||
|
|
rm -f $tmp.*
|
||
|
|
rm -f $testfile
|
||
|
|
}
|
||
|
|
|
||
|
|
# get standard environment, filters and checks
|
||
|
|
. ./common/rc
|
||
|
|
. ./common/filter
|
||
|
|
|
||
|
|
# remove previous $seqres.full before test
|
||
|
|
rm -f $seqres.full
|
||
|
|
|
||
|
|
# real QA test starts here
|
||
|
|
|
||
|
|
# Modify as appropriate.
|
||
|
|
_supported_fs generic
|
||
|
|
_supported_os Linux
|
||
|
|
_require_test
|
||
|
|
_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
|