]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - misc/e2fuzz.sh
ext2fs: rename "s_overhead_blocks" to "s_overhead_clusters"
[thirdparty/e2fsprogs.git] / misc / e2fuzz.sh
CommitLineData
c4d5b81e
DW
1#!/bin/bash
2
3# Test harness to fuzz a filesystem over and over...
4# Copyright (C) 2014 Oracle.
5
6DIR=/tmp
7PASSES=10000
8SZ=32m
9SCRIPT_DIR="$(dirname "$0")"
10FEATURES="has_journal,extent,huge_file,flex_bg,uninit_bg,dir_nlink,extra_isize,64bit,metadata_csum,bigalloc,sparse_super2,inline_data"
11BLK_SZ=4096
12INODE_SZ=256
13EXTENDED_OPTS="discard"
14EXTENDED_FSCK_OPTIONS=""
15RUN_FSCK=1
16OVERRIDE_PATH=1
17HAS_FUSE2FS=0
18USE_FUSE2FS=0
19MAX_FSCK=10
20SRCDIR=/etc
21test -x "${SCRIPT_DIR}/fuse2fs" && HAS_FUSE2FS=1
22
23print_help() {
24 echo "Usage: $0 OPTIONS"
25 echo "-b: FS block size is this. (${BLK_SZ})"
26 echo "-B: Corrupt this many bytes per run."
27 echo "-d: Create test files in this directory. (${DIR})"
28 echo "-E: Extended mke2fs options."
29 echo "-f: Do not run e2fsck after each pass."
30 echo "-F: Extended e2fsck options."
31 echo "-I: Create inodes of this size. (${INODE_SZ})"
32 echo "-n: Run this many passes. (${PASSES})"
33 echo "-O: Create FS with these features."
34 echo "-p: Use system's mke2fs/e2fsck/tune2fs tools."
35 echo "-s: Create FS images of this size. (${SZ})"
36 echo "-S: Copy files from this dir. (${SRCDIR})"
be2ad9ed 37 echo "-x: Run e2fsck at most this many times. (${MAX_FSCK})"
c4d5b81e
DW
38 test "${HAS_FUSE2FS}" -gt 0 && echo "-u: Use fuse2fs instead of the kernel."
39 exit 0
40}
41
42GETOPT="d:n:s:O:I:b:B:E:F:fpx:S:"
43test "${HAS_FUSE2FS}" && GETOPT="${GETOPT}u"
44
45while getopts "${GETOPT}" opt; do
46 case "${opt}" in
47 "B")
48 E2FUZZ_ARGS="${E2FUZZ_ARGS} -b ${OPTARG}"
49 ;;
50 "d")
51 DIR="${OPTARG}"
52 ;;
53 "n")
54 PASSES="${OPTARG}"
55 ;;
56 "s")
57 SZ="${OPTARG}"
58 ;;
59 "O")
60 FEATURES="${FEATURES},${OPTARG}"
61 ;;
62 "I")
63 INODE_SZ="${OPTARG}"
64 ;;
65 "b")
66 BLK_SZ="${OPTARG}"
67 ;;
68 "E")
69 EXTENDED_OPTS="${OPTARG}"
70 ;;
71 "F")
72 EXTENDED_FSCK_OPTS="-E ${OPTARG}"
73 ;;
74 "f")
75 RUN_FSCK=0
76 ;;
77 "p")
78 OVERRIDE_PATH=0
79 ;;
80 "u")
81 USE_FUSE2FS=1
82 ;;
83 "x")
84 MAX_FSCK="${OPTARG}"
85 ;;
86 "S")
87 SRCDIR="${OPTARG}"
88 ;;
89 *)
90 print_help
91 ;;
92 esac
93done
94
95if [ "${OVERRIDE_PATH}" -gt 0 ]; then
96 PATH="${SCRIPT_DIR}:${SCRIPT_DIR}/../e2fsck/:${PATH}"
97 export PATH
98fi
99
100TESTDIR="${DIR}/tests/"
101TESTMNT="${DIR}/mnt/"
102BASE_IMG="${DIR}/e2fuzz.img"
103
104cat > /tmp/mke2fs.conf << ENDL
105[defaults]
106 base_features = ${FEATURES}
107 default_mntopts = acl,user_xattr,block_validity
108 enable_periodic_fsck = 0
109 blocksize = ${BLK_SZ}
110 inode_size = ${INODE_SZ}
111 inode_ratio = 4096
112 cluster_size = $((BLK_SZ * 2))
113 options = ${EXTENDED_OPTS}
114ENDL
115MKE2FS_CONFIG=/tmp/mke2fs.conf
116export MKE2FS_CONFIG
117
118# Set up FS image
119echo "+ create fs image"
120umount "${TESTDIR}"
121umount "${TESTMNT}"
122rm -rf "${TESTDIR}"
123rm -rf "${TESTMNT}"
124mkdir -p "${TESTDIR}"
125mkdir -p "${TESTMNT}"
126rm -rf "${BASE_IMG}"
127truncate -s "${SZ}" "${BASE_IMG}"
128mke2fs -F -v "${BASE_IMG}"
129if [ $? -ne 0 ]; then
130 exit $?
131fi
132
133# Populate FS image
134echo "+ populate fs image"
135modprobe loop
136mount "${BASE_IMG}" "${TESTMNT}" -o loop
137if [ $? -ne 0 ]; then
138 exit $?
139fi
140SRC_SZ="$(du -ks "${SRCDIR}" | awk '{print $1}')"
141FS_SZ="$(( $(stat -f "${TESTMNT}" -c '%a * %S') / 1024 ))"
e0d5dd36 142NR="$(( (FS_SZ * 4 / 10) / SRC_SZ ))"
c4d5b81e
DW
143if [ "${NR}" -lt 1 ]; then
144 NR=1
145fi
146echo "+ make ${NR} copies"
147seq 1 "${NR}" | while read nr; do
148 cp -pRdu "${SRCDIR}" "${TESTMNT}/test.${nr}" 2> /dev/null
149done
150umount "${TESTMNT}"
151e2fsck -fn "${BASE_IMG}"
152if [ $? -ne 0 ]; then
153 echo "fsck failed??"
154 exit 1
155fi
156
157# Run tests
158echo "+ run test"
159ret=0
160seq 1 "${PASSES}" | while read pass; do
161 echo "+ pass ${pass}"
162 PASS_IMG="${TESTDIR}/e2fuzz-${pass}.img"
163 FSCK_IMG="${TESTDIR}/e2fuzz-${pass}.fsck"
164 FUZZ_LOG="${TESTDIR}/e2fuzz-${pass}.fuzz.log"
165 OPS_LOG="${TESTDIR}/e2fuzz-${pass}.ops.log"
166
167 echo "++ corrupt image"
168 cp "${BASE_IMG}" "${PASS_IMG}"
169 if [ $? -ne 0 ]; then
170 exit $?
171 fi
172 tune2fs -L "e2fuzz-${pass}" "${PASS_IMG}"
173 e2fuzz -v "${PASS_IMG}" ${E2FUZZ_ARGS} > "${FUZZ_LOG}"
174 if [ $? -ne 0 ]; then
175 exit $?
176 fi
177
178 echo "++ mount image"
179 if [ "${USE_FUSE2FS}" -gt 0 ]; then
180 "${SCRIPT_DIR}/fuse2fs" "${PASS_IMG}" "${TESTMNT}"
181 res=$?
182 else
183 mount "${PASS_IMG}" "${TESTMNT}" -o loop
184 res=$?
185 fi
186
187 if [ "${res}" -eq 0 ]; then
188 echo "+++ ls -laR"
189 ls -laR "${TESTMNT}/test.1/" > /dev/null 2> "${OPS_LOG}"
190
191 echo "+++ cat files"
192 find "${TESTMNT}/test.1/" -type f -size -1048576k -print0 | xargs -0 cat > /dev/null 2>> "${OPS_LOG}"
193
194 echo "+++ expand"
be2ad9ed 195 find "${TESTMNT}/" -type f 2> /dev/null | head -n 50000 | while read f; do
c4d5b81e 196 attr -l "$f" > /dev/null 2>> "${OPS_LOG}"
c4d5b81e
DW
197 if [ -f "$f" -a -w "$f" ]; then
198 dd if=/dev/zero bs="${BLK_SZ}" count=1 >> "$f" 2>> "${OPS_LOG}"
199 fi
be2ad9ed 200 mv "$f" "$f.longer" > /dev/null 2>> "${OPS_LOG}"
c4d5b81e
DW
201 done
202 sync
203
204 echo "+++ create files"
205 cp -pRdu "${SRCDIR}" "${TESTMNT}/test.moo" 2>> "${OPS_LOG}"
206 sync
207
208 echo "+++ remove files"
209 rm -rf "${TESTMNT}/test.moo" 2>> "${OPS_LOG}"
210
211 umount "${TESTMNT}"
212 res=$?
213 if [ "${res}" -ne 0 ]; then
214 ret=1
215 break
216 fi
217 sync
218 test "${USE_FUSE2FS}" -gt 0 && sleep 2
219 fi
220 if [ "${RUN_FSCK}" -gt 0 ]; then
221 cp "${PASS_IMG}" "${FSCK_IMG}"
fac0c8ea 222 pass_img_sz="$(stat -c '%s' "${PASS_IMG}")"
c4d5b81e
DW
223
224 seq 1 "${MAX_FSCK}" | while read fsck_pass; do
225 echo "++ fsck pass ${fsck_pass}: $(which e2fsck) -fy ${FSCK_IMG} ${EXTENDED_FSCK_OPTS}"
226 FSCK_LOG="${TESTDIR}/e2fuzz-${pass}-${fsck_pass}.log"
227 e2fsck -fy "${FSCK_IMG}" ${EXTENDED_FSCK_OPTS} > "${FSCK_LOG}" 2>&1
228 res=$?
229 echo "++ fsck returns ${res}"
230 if [ "${res}" -eq 0 ]; then
231 exit 0
232 elif [ "${fsck_pass}" -eq "${MAX_FSCK}" ]; then
233 echo "++ fsck did not fix in ${MAX_FSCK} passes."
234 exit 1
235 fi
236 if [ "${res}" -gt 0 -a \
237 "$(grep 'Memory allocation failed' "${FSCK_LOG}" | wc -l)" -gt 0 ]; then
238 echo "++ Ran out of memory, get more RAM"
239 exit 0
240 fi
241 if [ "${res}" -gt 0 -a \
242 "$(grep 'Could not allocate block' "${FSCK_LOG}" | wc -l)" -gt 0 -a \
243 "$(dumpe2fs -h "${FSCK_IMG}" | grep '^Free blocks:' | awk '{print $3}')0" -eq 0 ]; then
244 echo "++ Ran out of space, get a bigger image"
245 exit 0
246 fi
247 if [ "${fsck_pass}" -gt 1 ]; then
248 diff -u "${TESTDIR}/e2fuzz-${pass}-$((fsck_pass - 1)).log" "${FSCK_LOG}"
249 if [ $? -eq 0 ]; then
250 echo "++ fsck makes no progress"
251 exit 2
252 fi
253 fi
fac0c8ea
DW
254
255 fsck_img_sz="$(stat -c '%s' "${FSCK_IMG}")"
256 if [ "${fsck_img_sz}" -ne "${pass_img_sz}" ]; then
257 echo "++ fsck image size changed"
258 exit 3
259 fi
c4d5b81e
DW
260 done
261 fsck_loop_ret=$?
262 if [ "${fsck_loop_ret}" -gt 0 ]; then
263 break;
264 fi
265 fi
e0d5dd36
DW
266
267 echo "+++ check fs for round 2"
268 FSCK_LOG="${TESTDIR}/e2fuzz-${pass}-round2.log"
269 e2fsck -fn "${FSCK_IMG}" ${EXTENDED_FSCK_OPTS} >> "${FSCK_LOG}" 2>&1
270 res=$?
271 if [ "${res}" -ne 0 ]; then
272 echo "++++ fsck failed."
273 exit 1
274 fi
275
276 echo "++ mount image (2)"
277 mount "${FSCK_IMG}" "${TESTMNT}" -o loop
278 res=$?
279
280 if [ "${res}" -eq 0 ]; then
281 echo "+++ ls -laR (2)"
282 ls -laR "${TESTMNT}/test.1/" > /dev/null 2> "${OPS_LOG}"
283
284 echo "+++ cat files (2)"
285 find "${TESTMNT}/test.1/" -type f -size -1048576k -print0 | xargs -0 cat > /dev/null 2>> "${OPS_LOG}"
286
287 echo "+++ expand (2)"
288 find "${TESTMNT}/" -type f 2> /dev/null | head -n 50000 | while read f; do
289 attr -l "$f" > /dev/null 2>> "${OPS_LOG}"
290 if [ -f "$f" -a -w "$f" ]; then
291 dd if=/dev/zero bs="${BLK_SZ}" count=1 >> "$f" 2>> "${OPS_LOG}"
292 fi
293 mv "$f" "$f.longer" > /dev/null 2>> "${OPS_LOG}"
294 done
295 sync
296
297 echo "+++ create files (2)"
298 cp -pRdu "${SRCDIR}" "${TESTMNT}/test.moo" 2>> "${OPS_LOG}"
299 sync
300
301 echo "+++ remove files (2)"
302 rm -rf "${TESTMNT}/test.moo" 2>> "${OPS_LOG}"
303
304 umount "${TESTMNT}"
305 res=$?
306 if [ "${res}" -ne 0 ]; then
307 ret=1
308 break
309 fi
310 sync
311 test "${USE_FUSE2FS}" -gt 0 && sleep 2
312
313 echo "+++ check fs (2)"
314 e2fsck -fn "${FSCK_IMG}" >> "${FSCK_LOG}" 2>&1
315 res=$?
316 if [ "${res}" -ne 0 ]; then
317 echo "++ fsck failed."
318 exit 1
319 fi
320 else
321 echo "++ mount(2) failed with ${res}"
322 exit 1
323 fi
c4d5b81e
DW
324 rm -rf "${FSCK_IMG}" "${PASS_IMG}" "${FUZZ_LOG}" "${TESTDIR}"/e2fuzz*.log
325done
326
327exit $ret