xfs: test that the needsrepair feature works as advertised
[xfstests-dev.git] / tests / xfs / 155
1 #! /bin/bash
2 # SPDX-License-Identifier: GPL-2.0-or-later
3 # Copyright (c) 2021 Oracle.  All Rights Reserved.
4 #
5 # FS QA Test No. 155
6 #
7 # Populate a filesystem with all types of metadata, then run repair with the
8 # libxfs write failure trigger set to go after a single write.  Check that the
9 # injected error trips, causing repair to abort, that needsrepair is set on the
10 # fs, the kernel won't mount; and that a non-injecting repair run clears
11 # needsrepair and makes the filesystem mountable again.
12 #
13 # Repeat with the trip point set to successively higher numbers of writes until
14 # we hit ~200 writes or repair manages to run to completion without tripping.
15
16 seq=`basename $0`
17 seqres=$RESULT_DIR/$seq
18 echo "QA output created by $seq"
19
20 here=`pwd`
21 tmp=/tmp/$$
22 status=1    # failure is the default!
23 trap "_cleanup; exit \$status" 0 1 2 3 15
24
25 _cleanup()
26 {
27         cd /
28         rm -f $tmp.*
29 }
30
31 # get standard environment, filters and checks
32 . ./common/rc
33 . ./common/populate
34 . ./common/filter
35
36 # real QA test starts here
37 _supported_fs xfs
38 _require_scratch_nocheck
39 _require_scratch_xfs_crc                # needsrepair only exists for v5
40 _require_populate_commands
41 _require_libxfs_debug_flag LIBXFS_DEBUG_WRITE_CRASH
42
43 rm -f $seqres.full
44
45 # Populate the filesystem
46 _scratch_populate_cached nofill >> $seqres.full 2>&1
47
48 max_writes=200                  # 200 loops should be enough for anyone
49 nr_incr=$((13 / TIME_FACTOR))
50 test $nr_incr -lt 1 && nr_incr=1
51 for ((nr_writes = 1; nr_writes < max_writes; nr_writes += nr_incr)); do
52         # Add a tiny bit of randomness into each run
53         allowed_writes=$(( nr_writes + (RANDOM % 7) ))
54         echo "Setting debug hook to crash after $allowed_writes writes." >> $seqres.full
55
56         # Start a repair and force it to abort after some number of writes
57         LIBXFS_DEBUG_WRITE_CRASH=ddev=$allowed_writes \
58                         _scratch_xfs_repair 2>> $seqres.full
59         res=$?
60         if [ $res -ne 0 ] && [ $res -ne 137 ]; then
61                 echo "repair failed with $res??"
62                 break
63         elif [ $res -eq 0 ]; then
64                 [ $nr_writes -eq 1 ] && \
65                         echo "ran to completion on the first try?"
66                 break
67         fi
68
69         # Check the state of NEEDSREPAIR after repair fails.  If it isn't set
70         # but repair -n says the fs is clean, then it's possible that the
71         # injected error caused it to abort immediately after the write that
72         # cleared NEEDSREPAIR.
73         if ! _check_scratch_xfs_features NEEDSREPAIR > /dev/null &&
74            ! _scratch_xfs_repair -n &>> $seqres.full; then
75                 echo "NEEDSREPAIR should be set on corrupt fs"
76         fi
77 done
78
79 # If NEEDSREPAIR is still set on the filesystem, ensure that a full run
80 # cleans everything up.
81 if _check_scratch_xfs_features NEEDSREPAIR > /dev/null; then
82         echo "Clearing NEEDSREPAIR" >> $seqres.full
83         _scratch_xfs_repair 2>> $seqres.full
84         _check_scratch_xfs_features NEEDSREPAIR > /dev/null && \
85                 echo "Repair failed to clear NEEDSREPAIR on the $nr_writes writes test"
86 fi
87
88 # success, all done
89 echo Silence is golden.
90 status=0
91 exit