#! /bin/bash # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (c) 2021 Oracle. All Rights Reserved. # # FS QA Test No. 154 # # Make sure that the kernel won't mount a filesystem if repair forcibly sets # NEEDSREPAIR while fixing metadata. Corrupt a directory in such a way as # to force repair to write an invalid dirent value as a sentinel to trigger a # repair activity in a later phase. Use a debug knob in xfs_repair to abort # the repair immediately after forcing the flag on. 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 # real QA test starts here _supported_fs xfs _require_scratch_nocheck _require_scratch_xfs_crc # needsrepair only exists for v5 _require_libxfs_debug_flag LIBXFS_DEBUG_WRITE_CRASH rm -f $seqres.full # Set up a real filesystem for our actual test _scratch_mkfs >> $seqres.full # Create a directory large enough to have a dir data block. 2k worth of # dirent names ought to do it. _scratch_mount mkdir -p $SCRATCH_MNT/fubar for i in $(seq 0 256 2048); do fname=$(printf "%0255d" $i) ln -s -f urk $SCRATCH_MNT/fubar/$fname done inum=$(stat -c '%i' $SCRATCH_MNT/fubar) _scratch_unmount # Fuzz the directory _scratch_xfs_db -x -c "inode $inum" -c "dblock 0" \ -c "fuzz -d bu[2].inumber add" >> $seqres.full # Try to repair the directory, force it to crash after setting needsrepair LIBXFS_DEBUG_WRITE_CRASH=ddev=2 _scratch_xfs_repair 2>> $seqres.full test $? -eq 137 || echo "repair should have been killed??" # We can't mount, right? _check_scratch_xfs_features NEEDSREPAIR _try_scratch_mount &> $tmp.mount res=$? _filter_scratch < $tmp.mount if [ $res -eq 0 ]; then echo "Should not be able to mount after needsrepair crash" _scratch_unmount fi # Repair properly this time and retry the mount _scratch_xfs_repair 2>> $seqres.full _check_scratch_xfs_features NEEDSREPAIR _scratch_mount # success, all done status=0 exit