summaryrefslogtreecommitdiff
path: root/tests/btrfs/142
blob: 1a6ebb62d3e2b4e96d307066c3553e8b94265816 (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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#! /bin/bash
# FS QA Test 142
#
# Regression test for btrfs DIO read's repair during read without checksum.
#
# Commit 2dabb3248453 ("Btrfs: Direct I/O read: Work on sectorsized blocks")
# introduced this regression.  It'd cause 'Segmentation fault' error.
#
# The upstream fix is
#	commit 97bf5a5589aa ("Btrfs: fix segmentation fault when doing dio read")
#
#-----------------------------------------------------------------------
# Copyright (c) 2017 Liu Bo.  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

_cleanup()
{
	cd /
	rm -f $tmp.*
}

# 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 btrfs
_supported_os Linux
_require_fail_make_request
_require_scratch_dev_pool 2

_require_btrfs_command inspect-internal dump-tree
_require_command "$FILEFRAG_PROG" filefrag

get_physical()
{
        # $1 is logical address
        # print chunk tree and find devid 2 which is $SCRATCH_DEV
        $BTRFS_UTIL_PROG inspect-internal dump-tree -t 3 $SCRATCH_DEV | \
	grep $1 -A 6 | awk '($1 ~ /stripe/ && $3 ~ /devid/ && $4 ~ /1/) { print $6 }'
}


SYSFS_BDEV=`_sysfs_dev $SCRATCH_DEV`

start_fail()
{
	echo 100 > $DEBUGFS_MNT/fail_make_request/probability
	echo 2 > $DEBUGFS_MNT/fail_make_request/times
	echo 1 > $DEBUGFS_MNT/fail_make_request/task-filter
	echo 0 > $DEBUGFS_MNT/fail_make_request/verbose
	echo 1 > $SYSFS_BDEV/make-it-fail
}

stop_fail()
{
	echo 0 > $DEBUGFS_MNT/fail_make_request/probability
	echo 0 > $DEBUGFS_MNT/fail_make_request/times
	echo 0 > $DEBUGFS_MNT/fail_make_request/task-filter
	echo 0 > $SYSFS_BDEV/make-it-fail
}

_scratch_dev_pool_get 2
# step 1, create a raid1 btrfs which contains one 128k file.
echo "step 1......mkfs.btrfs" >>$seqres.full

mkfs_opts="-d raid1 -b 1G"
_scratch_pool_mkfs $mkfs_opts >>$seqres.full 2>&1

# -o nospace_cache makes sure data is written to the start position of the data
# chunk
_scratch_mount -o nospace_cache,nodatasum

$XFS_IO_PROG -f -d -c "pwrite -S 0xaa -b 128K 0 128K" "$SCRATCH_MNT/foobar" |\
	_filter_xfs_io_offset

# step 2, corrupt the first 64k of one copy (on SCRATCH_DEV which is the first
# one in $SCRATCH_DEV_POOL
echo "step 2......corrupt file extent" >>$seqres.full

${FILEFRAG_PROG} -v $SCRATCH_MNT/foobar >> $seqres.full
logical_in_btrfs=`${FILEFRAG_PROG} -v $SCRATCH_MNT/foobar | _filter_filefrag | cut -d '#' -f 1`
physical_on_scratch=`get_physical ${logical_in_btrfs}`

_scratch_unmount
$XFS_IO_PROG -d -c "pwrite -S 0xbb -b 64K $physical_on_scratch 64K" $SCRATCH_DEV |\
	_filter_xfs_io_offset

_scratch_mount -o nospace_cache

# step 3, 128k dio read (this read can repair bad copy)
echo "step 3......repair the bad copy" >>$seqres.full

# since raid1 consists of two copies, and the bad copy was put on stripe #1
# while the good copy lies on stripe #0, the bad copy only gets access when the
# reader's pid % 2 == 1 is true
start_fail
while [[ -z ${result} ]]; do
	# enable task-filter only fails the following dio read so the repair is
	# supposed to work.
	result=$(bash -c "
	if [[ \$((\$\$ % 2)) -eq 1 ]]; then
		echo 1 > /proc/\$\$/make-it-fail
		exec $XFS_IO_PROG -d -c \"pread -b 128K 0 128K\" \"$SCRATCH_MNT/foobar\"
	fi");
done
stop_fail

_scratch_unmount

# check if the repair works
$XFS_IO_PROG -c "pread -v -b 512 $physical_on_scratch 512" $SCRATCH_DEV |\
	_filter_xfs_io_offset

_scratch_dev_pool_put
# success, all done
status=0
exit