summaryrefslogtreecommitdiff
path: root/tests/xfs/083
blob: e8ce2221c8ffa0e5e62c417b10bf8e62dbd95738 (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
147
148
149
150
151
152
153
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2015 Oracle, Inc.  All Rights Reserved.
#
# FS QA Test No. 083
#
# Create and populate an XFS filesystem, fuzz the metadata, then see how
# the kernel reacts, how xfs_repair fares in fixing the mess, and then
# try more kernel accesses to see if it really fixed things.
#
. ./common/preamble
_begin_fstest dangerous_fuzzers punch

# Override the default cleanup function.
_cleanup()
{
    cd /
    #rm -f $tmp.*
}

# Import common functions.
. ./common/filter
. ./common/attr
. ./common/populate
. ./common/fuzzy

# real QA test starts here
_supported_fs xfs

_require_scratch
_require_attrs
_require_populate_commands

scratch_repair() {
	fsck_pass="$1"

	FSCK_LOG="${tmp}-fuzz-${fsck_pass}.log"
	echo "++ fsck pass ${fsck_pass}" > "${FSCK_LOG}"
	_repair_scratch_fs >> "${FSCK_LOG}" 2>&1
	res=$?
	if [ "${res}" -eq 0 ]; then
		echo "++ allegedly fixed, reverify" >> "${FSCK_LOG}"
		_scratch_xfs_repair -n >> "${FSCK_LOG}" 2>&1
		res=$?
	fi
	echo "++ fsck returns ${res}" >> "${FSCK_LOG}"
	if [ "${res}" -eq 0 ]; then
		echo "++ fsck thinks we are done" >> "${FSCK_LOG}"
		cat "${FSCK_LOG}"
		return 0
	elif [ "${res}" -eq 2 ]; then
		# replay log?
		echo "+++ replaying log" >> "${FSCK_LOG}"
		_try_scratch_mount >> "${FSCK_LOG}" 2>&1
		res=$?
		echo "+++ mount returns ${res}" >> "${FSCK_LOG}"
		if [ "${res}" -gt 0 ]; then
			echo "+++ zeroing log" >> "${FSCK_LOG}"
			_scratch_xfs_repair -L >> "${FSCK_LOG}" 2>&1
			echo "+++ returns $?" >> "${FSCK_LOG}"
		else
			umount "${SCRATCH_MNT}" >> "${FSCK_LOG}" 2>&1
		fi
	elif [ "${fsck_pass}" -eq "${FSCK_PASSES}" ]; then
		echo "++ fsck did not fix in ${FSCK_PASSES} passes." >> "${FSCK_LOG}"
		cat "${FSCK_LOG}"
		return 0
	fi
	cat "${FSCK_LOG}"
	if [ "${fsck_pass}" -gt 1 ]; then
		cmp -s "${tmp}-fuzz-$((fsck_pass - 1)).log" "${FSCK_LOG}"
		if [ $? -eq 0 ]; then
			echo "++ fsck makes no progress"
			return 2
		fi
	fi
	return 1
}

# This test will corrupt fs intentionally, so there will be WARNINGs
# in dmesg as expected
_disable_dmesg_check

echo "See interesting results in $seqres.full" | sed -e "s,$RESULT_DIR,RESULT_DIR,g"
SRCDIR=`pwd`
test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-3 -n 32"
test -z "${FSCK_PASSES}" && FSCK_PASSES=10
BLK_SZ=4096

echo "fuzzing xfs with FUZZ_ARGS=$FUZZ_ARGS and FSCK_PASSES=$FSCK_PASSES" > $seqres.full

echo "+ create scratch fs" >> $seqres.full
_scratch_mkfs_xfs >> $seqres.full 2>&1

echo "+ populate fs image" >> $seqres.full
_scratch_populate >> $seqres.full

echo "+ check fs" >> $seqres.full
_repair_scratch_fs >> $seqres.full 2>&1 || _fail "should pass initial fsck"

echo "++ corrupt image" >> $seqres.full
_scratch_xfs_db -x -c blockget -c "blocktrash ${FUZZ_ARGS}" >> $seqres.full 2>&1

echo "++ mount image" >> $seqres.full
_try_scratch_mount >> $seqres.full 2>&1

echo "+++ test scratch" >> $seqres.full
_scratch_fuzz_test >> $seqres.full 2>&1

echo "+++ modify scratch" >> $seqres.full
_scratch_fuzz_modify >> $seqres.full 2>&1

echo "++ umount" >> $seqres.full
umount "${SCRATCH_MNT}"

# repair in a loop...
for p in $(seq 1 "${FSCK_PASSES}"); do
	scratch_repair "$p" >> $seqres.full 2>&1 && break
done
echo "+ fsck loop returns ${fsck_loop_ret}" >> $seqres.full

echo "++ check fs for round 2" >> $seqres.full
_repair_scratch_fs >> $seqres.full 2>&1

ROUND2_LOG="${tmp}-round2-${fsck_pass}.log"
echo "++ mount image (2)" >> $ROUND2_LOG
_try_scratch_mount >> $ROUND2_LOG 2>&1

echo "++ chattr -R -i" >> $ROUND2_LOG
$CHATTR_PROG -R -f -i "${SCRATCH_MNT}/" > /dev/null 2>> $ROUND2_LOG

echo "+++ test scratch" >> $ROUND2_LOG
_scratch_fuzz_test >> $ROUND2_LOG 2>&1

echo "+++ modify scratch" >> $ROUND2_LOG
_scratch_fuzz_modify >> $ROUND2_LOG 2>&1

echo "++ umount" >> $ROUND2_LOG
umount "${SCRATCH_MNT}" >> $ROUND2_LOG 2>&1

cat "$ROUND2_LOG" >> $seqres.full

echo "++ check fs (2)" >> $seqres.full
_repair_scratch_fs >> $seqres.full 2>&1

grep -E -q '(did not fix|makes no progress)' $seqres.full && echo "xfs_repair failed" | tee -a $seqres.full
if [ "$(wc -l < "$ROUND2_LOG")" -ne 8 ]; then
	echo "xfs_repair did not fix everything" | tee -a $seqres.full
fi
echo "finished fuzzing" | tee -a "$seqres.full"

status=0
exit