| #! /bin/bash |
| # 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. |
| # |
| #----------------------------------------------------------------------- |
| # Copyright (c) 2015 Oracle, Inc. All Rights Reserved. |
| # |
| # This program is free software; you can redistribute it and/or |
| # modify it under the terms of the GNU General Public License as |
| # published by the Free Software Foundation. |
| # |
| # This program is distributed in the hope that it would be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write the Free Software Foundation, |
| # Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| #----------------------------------------------------------------------- |
| # |
| |
| 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 |
| _supported_os Linux |
| |
| _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 |