summaryrefslogtreecommitdiff
path: root/tests/btrfs/215
blob: 7054a9ba79ce25f71c553e8aefe6f76aa444b425 (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
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (C) 2020 SUSE Linux Products GmbH. All Rights Reserved.
#
# FS QA Test 215
#
# Test that reading corrupted files would correctly increment device status
# counters. This is fixed by the following linux kernel commit:
# 814723e0a55a ("btrfs: increment device corruption error in case of checksum error")
#
. ./common/preamble
_begin_fstest auto quick read_repair

. ./common/filter

get_physical()
{
	$BTRFS_UTIL_PROG inspect-internal dump-tree -t 3 $SCRATCH_DEV | \
		grep $1 -A2 | \
		$AWK_PROG "(\$1 ~ /stripe/ && \$3 ~ /devid/ && \$2 ~ /0/) { print \$6 }"
}

_supported_fs btrfs
_require_scratch
# No data checksums for NOCOW case, so can't detect corruption and repair data.
_require_btrfs_no_nodatacow
# Overwriting data is forbidden on a zoned block device
_require_non_zoned_device $SCRATCH_DEV

_scratch_mkfs > /dev/null
# disable freespace inode to ensure file is the first thing in the data
# blobk group
_scratch_mount $(_btrfs_no_v1_cache_opt)

pagesize=$(_get_page_size)
blocksize=$(_get_block_size $SCRATCH_MNT)

# For subpage case, since we still do read in full page size, if have 8 corrupted
# sectors in one page, then even we just try to read one sector of that page,
# all 8 corruption will be reported.
# So here we chose the filesize using page size.
filesize=$((8*$pagesize))
if [ $blocksize -le $pagesize ]; then
	sectors_per_page=$(($pagesize / $blocksize))
else
	# We don't support multi-page sectorsize yet
	_notrun "this test doesn't support sectorsize $blocksize with page size $pagesize yet"
fi

uuid=$(findmnt -n -o UUID "$SCRATCH_MNT")

if [ ! -e /sys/fs/btrfs/$uuid/bdi ]; then
	_notrun "bdi link not found"
fi

#create an 8 block file
$XFS_IO_PROG -d -f -c "pwrite -S 0xbb -b $filesize 0 $filesize" "$SCRATCH_MNT/foobar" > /dev/null

logical_extent=$(_btrfs_get_first_logical $SCRATCH_MNT/foobar)
physical_extent=$(get_physical $logical_extent)

echo "logical = $logical_extent physical=$physical_extent" >> $seqres.full

# corrupt first 4 blocks of file
_scratch_unmount
$XFS_IO_PROG -d -c "pwrite -S 0xaa -b $pagesize $physical_extent $((4 * $pagesize))" $SCRATCH_DEV > /dev/null
_scratch_mount

# disable readahead to avoid skewing the counter
echo 0 > /sys/fs/btrfs/$uuid/bdi/read_ahead_kb

# buffered reads whould result in 2 * sectors_per_page errors since readahead code always submits
# at least 1 page worth of IO and it will be counted as error(s) as well
$XFS_IO_PROG -c "pread -b $filesize 0 $filesize" "$SCRATCH_MNT/foobar" > /dev/null 2>&1
errs=$($BTRFS_UTIL_PROG device stats $SCRATCH_DEV | $AWK_PROG '/corruption_errs/ { print $2 }')
if [ $errs -ne $((2 * $sectors_per_page)) ]; then
	_fail "Errors: $errs expected: 2"
fi

# DIO does check every sector
$XFS_IO_PROG -d -c "pread -b $filesize 0 $filesize" "$SCRATCH_MNT/foobar" > /dev/null 2>&1
errs=$($BTRFS_UTIL_PROG device stats $SCRATCH_DEV | $AWK_PROG '/corruption_errs/ { print $2 }')
if [ $errs -ne $((6 * $sectors_per_page)) ]; then
	_fail "Errors: $errs expected: 6"
fi

# success, all done
echo "Silence is golden"
status=0
exit