generic: test MADV_POPULATE_READ with IO errors
[xfstests-dev.git] / tests / xfs / 083
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2015 Oracle, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. 083
6 #
7 # Create and populate an XFS filesystem, fuzz the metadata, then see how
8 # the kernel reacts, how xfs_repair fares in fixing the mess, and then
9 # try more kernel accesses to see if it really fixed things.
10 #
11 . ./common/preamble
12 _begin_fstest dangerous_fuzzers punch
13
14 # Override the default cleanup function.
15 _cleanup()
16 {
17     cd /
18     #rm -f $tmp.*
19 }
20
21 # Import common functions.
22 . ./common/filter
23 . ./common/attr
24 . ./common/populate
25 . ./common/fuzzy
26
27 # real QA test starts here
28 _supported_fs xfs
29
30 _require_scratch
31 #_require_xfs_crc       # checksum not required, but you probably want it anyway...
32 #_require_xfs_mkfs_crc
33 _require_attrs
34 _require_populate_commands
35
36 scratch_repair() {
37         fsck_pass="$1"
38
39         FSCK_LOG="${tmp}-fuzz-${fsck_pass}.log"
40         echo "++ fsck pass ${fsck_pass}" > "${FSCK_LOG}"
41         _repair_scratch_fs >> "${FSCK_LOG}" 2>&1
42         res=$?
43         if [ "${res}" -eq 0 ]; then
44                 echo "++ allegedly fixed, reverify" >> "${FSCK_LOG}"
45                 _scratch_xfs_repair -n >> "${FSCK_LOG}" 2>&1
46                 res=$?
47         fi
48         echo "++ fsck returns ${res}" >> "${FSCK_LOG}"
49         if [ "${res}" -eq 0 ]; then
50                 echo "++ fsck thinks we are done" >> "${FSCK_LOG}"
51                 cat "${FSCK_LOG}"
52                 return 0
53         elif [ "${res}" -eq 2 ]; then
54                 # replay log?
55                 echo "+++ replaying log" >> "${FSCK_LOG}"
56                 _try_scratch_mount >> "${FSCK_LOG}" 2>&1
57                 res=$?
58                 echo "+++ mount returns ${res}" >> "${FSCK_LOG}"
59                 if [ "${res}" -gt 0 ]; then
60                         echo "+++ zeroing log" >> "${FSCK_LOG}"
61                         _scratch_xfs_repair -L >> "${FSCK_LOG}" 2>&1
62                         echo "+++ returns $?" >> "${FSCK_LOG}"
63                 else
64                         umount "${SCRATCH_MNT}" >> "${FSCK_LOG}" 2>&1
65                 fi
66         elif [ "${fsck_pass}" -eq "${FSCK_PASSES}" ]; then
67                 echo "++ fsck did not fix in ${FSCK_PASSES} passes." >> "${FSCK_LOG}"
68                 cat "${FSCK_LOG}"
69                 return 0
70         fi
71         cat "${FSCK_LOG}"
72         if [ "${fsck_pass}" -gt 1 ]; then
73                 cmp -s "${tmp}-fuzz-$((fsck_pass - 1)).log" "${FSCK_LOG}"
74                 if [ $? -eq 0 ]; then
75                         echo "++ fsck makes no progress"
76                         return 2
77                 fi
78         fi
79         return 1
80 }
81
82 # This test will corrupt fs intentionally, so there will be WARNINGs
83 # in dmesg as expected
84 _disable_dmesg_check
85
86 echo "See interesting results in $seqres.full" | sed -e "s,$RESULT_DIR,RESULT_DIR,g"
87 SRCDIR=`pwd`
88 test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-3 -n 32"
89 test -z "${FSCK_PASSES}" && FSCK_PASSES=10
90 BLK_SZ=4096
91
92 echo "fuzzing xfs with FUZZ_ARGS=$FUZZ_ARGS and FSCK_PASSES=$FSCK_PASSES" > $seqres.full
93
94 echo "+ create scratch fs" >> $seqres.full
95 _scratch_mkfs_xfs >> $seqres.full 2>&1
96
97 echo "+ populate fs image" >> $seqres.full
98 _scratch_populate >> $seqres.full
99
100 echo "+ check fs" >> $seqres.full
101 _repair_scratch_fs >> $seqres.full 2>&1 || _fail "should pass initial fsck"
102
103 echo "++ corrupt image" >> $seqres.full
104 _scratch_xfs_db -x -c blockget -c "blocktrash ${FUZZ_ARGS}" >> $seqres.full 2>&1
105
106 echo "++ mount image" >> $seqres.full
107 _try_scratch_mount >> $seqres.full 2>&1
108
109 echo "+++ test scratch" >> $seqres.full
110 _scratch_fuzz_test >> $seqres.full 2>&1
111
112 echo "+++ modify scratch" >> $seqres.full
113 _scratch_fuzz_modify >> $seqres.full 2>&1
114
115 echo "++ umount" >> $seqres.full
116 umount "${SCRATCH_MNT}"
117
118 # repair in a loop...
119 for p in $(seq 1 "${FSCK_PASSES}"); do
120         scratch_repair "$p" >> $seqres.full 2>&1 && break
121 done
122 echo "+ fsck loop returns ${fsck_loop_ret}" >> $seqres.full
123
124 echo "++ check fs for round 2" >> $seqres.full
125 _repair_scratch_fs >> $seqres.full 2>&1
126
127 ROUND2_LOG="${tmp}-round2-${fsck_pass}.log"
128 echo "++ mount image (2)" >> $ROUND2_LOG
129 _try_scratch_mount >> $ROUND2_LOG 2>&1
130
131 echo "++ chattr -R -i" >> $ROUND2_LOG
132 $CHATTR_PROG -R -f -i "${SCRATCH_MNT}/" > /dev/null 2>> $ROUND2_LOG
133
134 echo "+++ test scratch" >> $ROUND2_LOG
135 _scratch_fuzz_test >> $ROUND2_LOG 2>&1
136
137 echo "+++ modify scratch" >> $ROUND2_LOG
138 _scratch_fuzz_modify >> $ROUND2_LOG 2>&1
139
140 echo "++ umount" >> $ROUND2_LOG
141 umount "${SCRATCH_MNT}" >> $ROUND2_LOG 2>&1
142
143 cat "$ROUND2_LOG" >> $seqres.full
144
145 echo "++ check fs (2)" >> $seqres.full
146 _repair_scratch_fs >> $seqres.full 2>&1
147
148 grep -E -q '(did not fix|makes no progress)' $seqres.full && echo "xfs_repair failed" | tee -a $seqres.full
149 if [ "$(wc -l < "$ROUND2_LOG")" -ne 8 ]; then
150         echo "xfs_repair did not fix everything" | tee -a $seqres.full
151 fi
152 echo "finished fuzzing" | tee -a "$seqres.full"
153
154 status=0
155 exit