#! /bin/bash # SPDX-License-Identifier: GPL-2.0 # Copyright (c) 2015 Oracle, Inc. All Rights Reserved. # # FS QA Test No. 006 # # Create and populate an ext4 filesystem, fuzz the metadata, then see how # the kernel reacts, how e2fsck fares in fixing the mess, and then # try more kernel accesses to see if it really fixed things. # 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 . ./common/attr . ./common/populate . ./common/fuzzy if [ ! -x "$(which e2fuzz)" ]; then _notrun "Couldn't find e2fuzz" fi # real QA test starts here _supported_fs ext4 _require_scratch _require_attrs _require_populate_commands repair_scratch() { fsck_pass="$1" FSCK_LOG="${tmp}-fuzz-${fsck_pass}.log" echo "++ fsck pass ${fsck_pass}" > "${FSCK_LOG}" e2fsck -f -y "${SCRATCH_DEV}" res=$? if [ "${res}" -eq 0 ]; then echo "++ allegedly fixed, reverify" >> "${FSCK_LOG}" _check_scratch_fs -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 [ "${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 } rm -f $seqres.full echo "See interesting results in $seqres.full" | sed -e "s,$RESULT_DIR,RESULT_DIR,g" SRCDIR=`pwd` test -z "${FUZZ_ARGS}" && FUZZ_ARGS="-b 32 -v" test -z "${FSCK_PASSES}" && FSCK_PASSES=10 BLK_SZ=4096 echo "fuzzing ext4 with FUZZ_ARGS=$FUZZ_ARGS and FSCK_PASSES=$FSCK_PASSES" > $seqres.full echo "+ create scratch fs" >> $seqres.full _scratch_mkfs_ext4 >> $seqres.full 2>&1 echo "+ populate fs image" >> $seqres.full _scratch_populate >> $seqres.full echo "+ check fs" >> $seqres.full _check_scratch_fs >> $seqres.full 2>&1 || _fail "should pass initial fsck" echo "++ corrupt image" >> $seqres.full e2fuzz ${FUZZ_ARGS} ${SCRATCH_DEV} >> $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 "++ unmount" >> $seqres.full umount "${SCRATCH_MNT}" # repair in a loop... for p in $(seq 1 "${FSCK_PASSES}"); do repair_scratch "$p" >> $seqres.full 2>&1 && break done echo "+ fsck loop returns ${fsck_loop_ret}" >> $seqres.full echo "++ check fs for round 2" >> $seqres.full _check_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 "++ unmount" >> $ROUND2_LOG umount "${SCRATCH_MNT}" >> $ROUND2_LOG 2>&1 cat "$ROUND2_LOG" >> $seqres.full echo "++ check fs (2)" >> $seqres.full _check_scratch_fs >> $seqres.full 2>&1 egrep -q '(did not fix|makes no progress)' $seqres.full && echo "e2fsck failed" | tee -a $seqres.full if [ "$(wc -l < "$ROUND2_LOG")" -ne 8 ]; then echo "e2fsck did not fix everything" | tee -a $seqres.full fi echo "finished fuzzing" | tee -a "$seqres.full" status=0 exit