summaryrefslogtreecommitdiff
path: root/tests/generic/404
blob: ddbc04d59037b14673d4d3b2f9c3c010986f95e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#! /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 prealloc

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_file_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